paperlint 3.2.0 → 4.1.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 (442) hide show
  1. package/.github/workflows/ci.yml +16 -23
  2. package/CLAUDE.md +33 -13
  3. package/CONTRIBUTING.md +23 -7
  4. package/README.md +11 -8
  5. package/dist/adapters/banal/failure.d.ts +1 -7
  6. package/dist/adapters/banal/failure.d.ts.map +1 -1
  7. package/dist/adapters/banal/failure.js +5 -7
  8. package/dist/adapters/banal/failure.js.map +1 -1
  9. package/dist/adapters/banal/index.d.ts.map +1 -1
  10. package/dist/adapters/banal/index.js +8 -11
  11. package/dist/adapters/banal/index.js.map +1 -1
  12. package/dist/adapters/banal/install.d.ts.map +1 -1
  13. package/dist/adapters/banal/install.js +4 -3
  14. package/dist/adapters/banal/install.js.map +1 -1
  15. package/dist/adapters/banal/invocation.d.ts +10 -5
  16. package/dist/adapters/banal/invocation.d.ts.map +1 -1
  17. package/dist/adapters/banal/invocation.js +13 -1
  18. package/dist/adapters/banal/invocation.js.map +1 -1
  19. package/dist/adapters/banal/locate.d.ts +12 -9
  20. package/dist/adapters/banal/locate.d.ts.map +1 -1
  21. package/dist/adapters/banal/locate.js +19 -12
  22. package/dist/adapters/banal/locate.js.map +1 -1
  23. package/dist/adapters/banal/run.d.ts +10 -1
  24. package/dist/adapters/banal/run.d.ts.map +1 -1
  25. package/dist/adapters/banal/run.js +8 -4
  26. package/dist/adapters/banal/run.js.map +1 -1
  27. package/dist/adapters/banal/settings.d.ts +1 -1
  28. package/dist/adapters/banal/settings.d.ts.map +1 -1
  29. package/dist/adapters/banal/settings.js +2 -1
  30. package/dist/adapters/banal/settings.js.map +1 -1
  31. package/dist/adapters/latex/document-class.d.ts +22 -0
  32. package/dist/adapters/latex/document-class.d.ts.map +1 -0
  33. package/dist/adapters/latex/document-class.js +102 -0
  34. package/dist/adapters/latex/document-class.js.map +1 -0
  35. package/dist/adapters/latex/hidden.d.ts +16 -0
  36. package/dist/adapters/latex/hidden.d.ts.map +1 -0
  37. package/dist/adapters/latex/hidden.js +49 -0
  38. package/dist/adapters/latex/hidden.js.map +1 -0
  39. package/dist/adapters/latex/index.d.ts +29 -0
  40. package/dist/adapters/latex/index.d.ts.map +1 -0
  41. package/dist/adapters/latex/index.js +18 -0
  42. package/dist/adapters/latex/index.js.map +1 -0
  43. package/dist/adapters/latex/nodes.d.ts +54 -0
  44. package/dist/adapters/latex/nodes.d.ts.map +1 -0
  45. package/dist/adapters/latex/nodes.js +93 -0
  46. package/dist/adapters/latex/nodes.js.map +1 -0
  47. package/dist/adapters/latex/outline.d.ts +10 -0
  48. package/dist/adapters/latex/outline.d.ts.map +1 -0
  49. package/dist/adapters/latex/outline.js +39 -0
  50. package/dist/adapters/latex/outline.js.map +1 -0
  51. package/dist/adapters/latex/parse.d.ts +42 -0
  52. package/dist/adapters/latex/parse.d.ts.map +1 -0
  53. package/dist/adapters/latex/parse.js +94 -0
  54. package/dist/adapters/latex/parse.js.map +1 -0
  55. package/dist/adapters/latex/rendered.d.ts +10 -0
  56. package/dist/adapters/latex/rendered.d.ts.map +1 -0
  57. package/dist/adapters/latex/rendered.js +39 -0
  58. package/dist/adapters/latex/rendered.js.map +1 -0
  59. package/dist/adapters/memory/index.d.ts.map +1 -1
  60. package/dist/adapters/memory/index.js +8 -2
  61. package/dist/adapters/memory/index.js.map +1 -1
  62. package/dist/adapters/node/process.io.d.ts +6 -3
  63. package/dist/adapters/node/process.io.d.ts.map +1 -1
  64. package/dist/adapters/node/process.io.js.map +1 -1
  65. package/dist/adapters/node/workspace.io.d.ts.map +1 -1
  66. package/dist/adapters/node/workspace.io.js +4 -2
  67. package/dist/adapters/node/workspace.io.js.map +1 -1
  68. package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
  69. package/dist/adapters/pdfjs/fill.js +12 -12
  70. package/dist/adapters/pdfjs/fill.js.map +1 -1
  71. package/dist/adapters/references/index.d.ts.map +1 -1
  72. package/dist/adapters/references/index.js +4 -2
  73. package/dist/adapters/references/index.js.map +1 -1
  74. package/dist/build-engine.d.ts +1 -1
  75. package/dist/build-engine.d.ts.map +1 -1
  76. package/dist/build-engine.js +8 -1
  77. package/dist/build-engine.js.map +1 -1
  78. package/dist/build.d.ts +2 -3
  79. package/dist/build.d.ts.map +1 -1
  80. package/dist/build.js +9 -10
  81. package/dist/build.js.map +1 -1
  82. package/dist/caller-path.d.ts +3 -0
  83. package/dist/caller-path.d.ts.map +1 -0
  84. package/dist/caller-path.js +13 -0
  85. package/dist/caller-path.js.map +1 -0
  86. package/dist/cli.d.ts +10 -17
  87. package/dist/cli.d.ts.map +1 -1
  88. package/dist/cli.js +91 -17
  89. package/dist/cli.js.map +1 -1
  90. package/dist/doctor.d.ts +12 -3
  91. package/dist/doctor.d.ts.map +1 -1
  92. package/dist/doctor.js +2 -1
  93. package/dist/doctor.js.map +1 -1
  94. package/dist/domain/paths.d.ts +8 -2
  95. package/dist/domain/paths.d.ts.map +1 -1
  96. package/dist/domain/paths.js +12 -1
  97. package/dist/domain/paths.js.map +1 -1
  98. package/dist/domain/ready.d.ts +24 -0
  99. package/dist/domain/ready.d.ts.map +1 -0
  100. package/dist/domain/ready.js +11 -0
  101. package/dist/domain/ready.js.map +1 -0
  102. package/dist/domain/record.d.ts +8 -0
  103. package/dist/domain/record.d.ts.map +1 -0
  104. package/dist/domain/record.js +8 -0
  105. package/dist/domain/record.js.map +1 -0
  106. package/dist/domain/sha256.d.ts.map +1 -1
  107. package/dist/domain/sha256.js +4 -2
  108. package/dist/domain/sha256.js.map +1 -1
  109. package/dist/domain/tex-document.d.ts +84 -0
  110. package/dist/domain/tex-document.d.ts.map +1 -0
  111. package/dist/domain/tex-document.js +43 -0
  112. package/dist/domain/tex-document.js.map +1 -0
  113. package/dist/engine.d.ts +23 -22
  114. package/dist/engine.d.ts.map +1 -1
  115. package/dist/engine.js.map +1 -1
  116. package/dist/eslint-rules/bib-reachable-entry.d.ts +1 -1
  117. package/dist/eslint-rules/bib-reachable-entry.js.map +1 -1
  118. package/dist/eslint-rules/install-path-literals.d.ts +2 -2
  119. package/dist/eslint-rules/install-path-literals.js.map +1 -1
  120. package/dist/eslint-rules/paper-research-question.d.ts +1 -1
  121. package/dist/eslint-rules/paper-research-question.js.map +1 -1
  122. package/dist/eslint-rules/paper-stages.d.ts +2 -2
  123. package/dist/eslint-rules/paper-stages.js.map +1 -1
  124. package/dist/eslint-rules/paper-typography.d.ts +6 -6
  125. package/dist/eslint-rules/paper-typography.js.map +1 -1
  126. package/dist/eslint-rules/pdf-last-page-balance.d.ts +1 -1
  127. package/dist/eslint-rules/pdf-last-page-balance.js.map +1 -1
  128. package/dist/eslint-rules/review-frontmatter.d.ts +2 -2
  129. package/dist/eslint-rules/review-frontmatter.js.map +1 -1
  130. package/dist/eslint-rules/sibling-frontmatter.d.ts +1 -1
  131. package/dist/eslint-rules/sibling-frontmatter.d.ts.map +1 -1
  132. package/dist/eslint-rules/temp-root-realpath.d.ts +1 -1
  133. package/dist/eslint-rules/temp-root-realpath.js.map +1 -1
  134. package/dist/eslint-rules/tex-build.d.ts +2 -2
  135. package/dist/eslint-rules/tex-build.js.map +1 -1
  136. package/dist/facts-file.d.ts.map +1 -1
  137. package/dist/facts-file.js +31 -28
  138. package/dist/facts-file.js.map +1 -1
  139. package/dist/hooks-settings.d.ts.map +1 -1
  140. package/dist/hooks-settings.js +17 -2
  141. package/dist/hooks-settings.js.map +1 -1
  142. package/dist/init.d.ts +3 -4
  143. package/dist/init.d.ts.map +1 -1
  144. package/dist/init.js +18 -8
  145. package/dist/init.js.map +1 -1
  146. package/dist/lib/paper-config.d.ts.map +1 -1
  147. package/dist/lib/paper-config.js +1 -5
  148. package/dist/lib/paper-config.js.map +1 -1
  149. package/dist/new-paper.d.ts +5 -0
  150. package/dist/new-paper.d.ts.map +1 -1
  151. package/dist/new-paper.js +8 -1
  152. package/dist/new-paper.js.map +1 -1
  153. package/dist/package-dirs.d.ts +5 -0
  154. package/dist/package-dirs.d.ts.map +1 -0
  155. package/dist/package-dirs.js +14 -0
  156. package/dist/package-dirs.js.map +1 -0
  157. package/dist/paper-files.d.ts +4 -4
  158. package/dist/paper-files.d.ts.map +1 -1
  159. package/dist/paper-files.js +6 -6
  160. package/dist/paper-files.js.map +1 -1
  161. package/dist/paper-settings.js +3 -3
  162. package/dist/paper-settings.js.map +1 -1
  163. package/dist/pdf-facts.d.ts +51 -1
  164. package/dist/pdf-facts.d.ts.map +1 -1
  165. package/dist/pdf-facts.js +23 -15
  166. package/dist/pdf-facts.js.map +1 -1
  167. package/dist/pdf-geometry.d.ts.map +1 -1
  168. package/dist/pdf-geometry.js +2 -3
  169. package/dist/pdf-geometry.js.map +1 -1
  170. package/dist/ports/latex.d.ts +24 -0
  171. package/dist/ports/latex.d.ts.map +1 -0
  172. package/dist/ports/latex.js +2 -0
  173. package/dist/ports/latex.js.map +1 -0
  174. package/dist/ports/tool-installer.d.ts +2 -14
  175. package/dist/ports/tool-installer.d.ts.map +1 -1
  176. package/dist/presets.d.ts +15 -2
  177. package/dist/presets.d.ts.map +1 -1
  178. package/dist/presets.js +35 -10
  179. package/dist/presets.js.map +1 -1
  180. package/dist/references.d.ts.map +1 -1
  181. package/dist/references.js +4 -4
  182. package/dist/references.js.map +1 -1
  183. package/dist/rules-config.d.ts +26 -1
  184. package/dist/rules-config.d.ts.map +1 -1
  185. package/dist/rules-config.js +9 -9
  186. package/dist/rules-config.js.map +1 -1
  187. package/dist/tex-requirements.d.ts +15 -0
  188. package/dist/tex-requirements.d.ts.map +1 -1
  189. package/dist/tex-requirements.js +28 -10
  190. package/dist/tex-requirements.js.map +1 -1
  191. package/dist/tex-venue-rules.d.ts +83 -0
  192. package/dist/tex-venue-rules.d.ts.map +1 -0
  193. package/dist/tex-venue-rules.js +254 -0
  194. package/dist/tex-venue-rules.js.map +1 -0
  195. package/dist/types.d.ts +5 -3
  196. package/dist/types.d.ts.map +1 -1
  197. package/dist/venue-rules.d.ts +1 -1
  198. package/dist/venue-rules.d.ts.map +1 -1
  199. package/dist/venue-rules.js +20 -7
  200. package/dist/venue-rules.js.map +1 -1
  201. package/docs/configuration.md +5 -4
  202. package/docs/e2e.md +69 -40
  203. package/docs/install.md +1 -1
  204. package/docs/prior-art/README.md +1 -1
  205. package/docs/prior-art/package-location.md +5 -5
  206. package/docs/prior-art/repro/README.md +1 -1
  207. package/docs/prior-art/test-tooling.md +21 -10
  208. package/docs/rules/tex/required-section.md +73 -0
  209. package/docs/rules/tex/template.md +62 -0
  210. package/docs/rules/tex/venue-leftover.md +71 -0
  211. package/docs/rules.md +70 -48
  212. package/docs/testing.md +17 -4
  213. package/docs/texlive-install-decision.md +1 -1
  214. package/docs/toolchain.md +2 -2
  215. package/eslint-rules/bib-reachable-entry.ts +1 -1
  216. package/eslint-rules/install-path-literals.ts +2 -2
  217. package/eslint-rules/paper-research-question.ts +1 -1
  218. package/eslint-rules/paper-stages.ts +2 -2
  219. package/eslint-rules/paper-typography.ts +2 -2
  220. package/eslint-rules/pdf-last-page-balance.ts +1 -1
  221. package/eslint-rules/review-frontmatter.ts +1 -1
  222. package/eslint-rules/temp-root-realpath.ts +1 -1
  223. package/eslint-rules/tex-build.ts +2 -2
  224. package/eslint.config.mjs +162 -15
  225. package/fixtures/build-e2e/acmart/expect.json +26 -0
  226. package/fixtures/build-e2e/aidc/PIPELINE-STATUS.md +3 -0
  227. package/fixtures/build-e2e/aidc/expect.json +14 -0
  228. package/fixtures/build-e2e/aidc/paper.tex +46 -0
  229. package/fixtures/build-e2e/aidc/paperlint.json +1 -0
  230. package/fixtures/build-e2e/broken/expect.json +11 -0
  231. package/fixtures/build-e2e/cite/expect.json +27 -0
  232. package/fixtures/build-e2e/empty/expect.json +12 -0
  233. package/fixtures/build-e2e/fallback/expect.json +53 -0
  234. package/fixtures/build-e2e/guards/expect.json +6 -0
  235. package/fixtures/build-e2e/no-source/expect.json +10 -0
  236. package/fixtures/build-e2e/unbalanced/expect.json +60 -0
  237. package/fixtures/install-path-literals/clean.fixture.mjs +1 -1
  238. package/fixtures/install-path-literals/clean.md +2 -2
  239. package/fixtures/install-path-literals/defect.fixture.mjs +1 -1
  240. package/fixtures/install-path-literals/defect.md +2 -2
  241. package/fixtures/pdf-facts/README.md +1 -1
  242. package/fixtures/real-markdown-paper/baseline.ts +1 -1
  243. package/fixtures/render-paper/build-clean.sh +3 -5
  244. package/hooks/paper-status-gates.sh +9 -19
  245. package/lib/paper-config.harness.mjs +1 -1
  246. package/lib/paper-config.ts +1 -5
  247. package/lib/skill-checks.mjs +24 -381
  248. package/lib/skill-checks.test.mjs +63 -115
  249. package/lib/skill-corpus.mjs +10 -251
  250. package/lib/skill-corpus.test.mjs +2 -13
  251. package/lib/skill-trigger-cases.mjs +1 -1
  252. package/package.json +13 -2
  253. package/{skills/submit-paper/references/venues → presets}/acm-sigconf.jsonc +4 -1
  254. package/{skills/submit-paper/references/venues → presets}/agenticdev.jsonc +4 -0
  255. package/presets/aidc.jsonc +73 -0
  256. package/{skills/submit-paper/references/venues → presets}/aisec.jsonc +4 -0
  257. package/presets/ieee-conference.jsonc +66 -0
  258. package/{skills/submit-paper/references/venues → presets}/realm.jsonc +8 -1
  259. package/{skills/submit-paper/references/venues → presets/tex}/paper-guards.tex +1 -1
  260. package/{skills/submit-paper/references/venues → presets}/venue-profile.schema.json +30 -2
  261. package/scripts/check.harness.ts +64 -10
  262. package/scripts/check.test.ts +60 -13
  263. package/scripts/check.ts +83 -30
  264. package/scripts/coverage-config.test.ts +0 -1
  265. package/scripts/harness-api.frozen.json +0 -1
  266. package/scripts/test.test.ts +1 -1
  267. package/scripts/test.ts +1 -1
  268. package/skills/analyze-sibling-paper/SKILL.md +1 -39
  269. package/skills/analyze-sibling-paper/SKILL.md.spec.ts +0 -38
  270. package/skills/argument-arc/SKILL.md +2 -36
  271. package/skills/argument-arc/SKILL.md.spec.ts +1 -43
  272. package/skills/build-benchmark/SKILL.md +1 -41
  273. package/skills/build-benchmark/SKILL.md.spec.ts +0 -40
  274. package/skills/camera-ready/SKILL.md +1 -34
  275. package/skills/camera-ready/SKILL.md.spec.ts +0 -33
  276. package/skills/cold-read-diff/SKILL.md +1 -35
  277. package/skills/cold-read-diff/SKILL.md.spec.ts +0 -34
  278. package/skills/draft-paper/SKILL.md +2 -41
  279. package/skills/draft-paper/SKILL.md.spec.ts +1 -50
  280. package/skills/extend-paper/SKILL.md +2 -33
  281. package/skills/extend-paper/SKILL.md.spec.ts +1 -42
  282. package/skills/find-venue/SKILL.md +2 -38
  283. package/skills/find-venue/SKILL.md.spec.ts +1 -47
  284. package/skills/grade-paper-writing/SKILL.md +3 -38
  285. package/skills/grade-paper-writing/SKILL.md.spec.ts +2 -47
  286. package/skills/grade-paper-writing/prose-lint.mjs +2 -3
  287. package/skills/grade-paper-writing/prose-lint.test.ts +1 -1
  288. package/skills/harden-paper/SKILL.md +1 -39
  289. package/skills/harden-paper/SKILL.md.spec.ts +0 -38
  290. package/skills/map-prior-work/SKILL.md +1 -35
  291. package/skills/map-prior-work/SKILL.md.spec.ts +0 -34
  292. package/skills/osf-artifact-upload/osf-artifact-upload.harness.ts +3 -4
  293. package/skills/paper-adversarial-review/SKILL.md +2 -35
  294. package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -43
  295. package/skills/paper-pipeline/PIPELINE-MAP.md +2 -2
  296. package/skills/paper-pipeline/SKILL.md +3 -29
  297. package/skills/paper-pipeline/SKILL.md.spec.ts +2 -28
  298. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1 -1
  299. package/skills/paper-pipeline/paper-pipeline.harness.mjs +25 -40
  300. package/skills/paper-pipeline/references/acceptance-gate.md +1 -6
  301. package/skills/paper-pipeline/references/pipeline-status-template.md +8 -35
  302. package/skills/paper-pipeline/scripts/README.md +30 -225
  303. package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +4 -8
  304. package/skills/paper-pipeline/scripts/consumer.d.mts +0 -2
  305. package/skills/paper-pipeline/scripts/consumer.harness.mjs +6 -104
  306. package/skills/paper-pipeline/scripts/consumer.mjs +24 -119
  307. package/skills/paper-pipeline/scripts/generated-code.harness.mjs +2 -3
  308. package/skills/paper-pipeline/scripts/population-map.harness.mjs +3 -3
  309. package/skills/paper-status/SKILL.md +2 -42
  310. package/skills/paper-status/SKILL.md.spec.ts +1 -41
  311. package/skills/pc-panel-review/SKILL.md +2 -46
  312. package/skills/pc-panel-review/SKILL.md.spec.ts +1 -45
  313. package/skills/plan-paper-timeline/SKILL.md +2 -36
  314. package/skills/plan-paper-timeline/SKILL.md.spec.ts +0 -36
  315. package/skills/render-paper/SKILL.md +2 -38
  316. package/skills/render-paper/SKILL.md.spec.ts +1 -37
  317. package/skills/render-paper/check-render.sh +16 -63
  318. package/skills/render-paper/render-paper.harness.mjs +17 -59
  319. package/skills/research-ideate/SKILL.md +2 -39
  320. package/skills/research-ideate/SKILL.md.spec.ts +1 -47
  321. package/skills/study-accepted-papers/SKILL.md +1 -34
  322. package/skills/study-accepted-papers/SKILL.md.spec.ts +0 -33
  323. package/skills/submit-paper/SKILL.md +1 -33
  324. package/skills/submit-paper/SKILL.md.spec.ts +0 -32
  325. package/skills/sweep-design-space/SKILL.md +1 -38
  326. package/skills/sweep-design-space/SKILL.md.spec.ts +0 -37
  327. package/skills/tighten-paper/SKILL.md +2 -39
  328. package/skills/tighten-paper/SKILL.md.spec.ts +1 -47
  329. package/skills/tighten-paper/structure.mjs +4 -11
  330. package/skills/verify-citations/SKILL.md +2 -38
  331. package/skills/verify-citations/SKILL.md.spec.ts +1 -37
  332. package/src/adapters/banal/failure.ts +9 -10
  333. package/src/adapters/banal/index.test.ts +3 -3
  334. package/src/adapters/banal/index.ts +8 -10
  335. package/src/adapters/banal/install.ts +9 -4
  336. package/src/adapters/banal/invocation.test.ts +20 -8
  337. package/src/adapters/banal/invocation.ts +24 -9
  338. package/src/adapters/banal/locate.test.ts +2 -2
  339. package/src/adapters/banal/locate.ts +27 -21
  340. package/src/adapters/banal/output.test.ts +1 -1
  341. package/src/adapters/banal/run.test.ts +3 -3
  342. package/src/adapters/banal/run.ts +16 -10
  343. package/src/adapters/banal/settings.ts +2 -2
  344. package/src/adapters/banal/xml.test.ts +1 -1
  345. package/src/adapters/curl/download.test.ts +4 -4
  346. package/src/adapters/latex/document-class.ts +147 -0
  347. package/src/adapters/latex/hidden.ts +70 -0
  348. package/src/adapters/latex/index.test.ts +361 -0
  349. package/src/adapters/latex/index.ts +55 -0
  350. package/src/adapters/latex/nodes.ts +141 -0
  351. package/src/adapters/latex/outline.ts +64 -0
  352. package/src/adapters/latex/parse.ts +136 -0
  353. package/src/adapters/latex/rendered.ts +59 -0
  354. package/src/adapters/memory/index.ts +4 -3
  355. package/src/adapters/node/files.test.ts +5 -3
  356. package/src/adapters/node/process.io.ts +9 -2
  357. package/src/adapters/node/process.test.ts +4 -4
  358. package/src/adapters/node/workspace.io.ts +9 -4
  359. package/src/adapters/pdfjs/fill.test.ts +1 -1
  360. package/src/adapters/pdfjs/fill.ts +18 -10
  361. package/src/adapters/references/index.ts +7 -2
  362. package/src/build-engine.test.ts +11 -6
  363. package/src/build-engine.ts +10 -5
  364. package/src/build.harness.mjs +5 -7
  365. package/src/build.test.ts +10 -11
  366. package/src/build.ts +12 -13
  367. package/src/caller-path.ts +13 -0
  368. package/src/cli.harness.mjs +1 -3
  369. package/src/cli.test.ts +21 -16
  370. package/src/cli.ts +115 -33
  371. package/src/doctor.test.ts +1 -1
  372. package/src/doctor.ts +14 -5
  373. package/src/domain/paths.test.ts +15 -0
  374. package/src/domain/paths.ts +20 -1
  375. package/src/domain/ready.ts +31 -0
  376. package/src/domain/record.test.ts +20 -0
  377. package/src/domain/record.ts +12 -0
  378. package/src/domain/sha256.ts +5 -3
  379. package/src/domain/tex-document.test.ts +80 -0
  380. package/src/domain/tex-document.ts +110 -0
  381. package/src/engine.harness.mjs +1 -1
  382. package/src/engine.ts +30 -2
  383. package/src/facts-file.test.ts +4 -7
  384. package/src/facts-file.ts +45 -30
  385. package/src/hooks-settings.harness.ts +17 -0
  386. package/src/hooks-settings.ts +28 -4
  387. package/src/init.test.ts +25 -5
  388. package/src/init.ts +26 -12
  389. package/src/latex-loop.harness.ts +1 -1
  390. package/src/new-paper.harness.mjs +7 -23
  391. package/src/new-paper.test.ts +28 -3
  392. package/src/new-paper.ts +15 -3
  393. package/src/package-dirs.ts +17 -0
  394. package/src/paper-files.test.ts +22 -19
  395. package/src/paper-files.ts +16 -27
  396. package/src/paper-settings-commands.test.ts +6 -1
  397. package/src/paper-settings.test.ts +2 -2
  398. package/src/paper-settings.ts +5 -5
  399. package/src/pdf-facts.test.ts +16 -5
  400. package/src/pdf-facts.ts +79 -22
  401. package/src/pdf-geometry.ts +5 -3
  402. package/src/ports/latex.ts +29 -0
  403. package/src/ports/tool-installer.ts +2 -17
  404. package/src/presets.test.ts +65 -4
  405. package/src/presets.ts +65 -28
  406. package/src/references.test.ts +25 -19
  407. package/src/references.ts +4 -5
  408. package/src/rule-cases.test.ts +474 -0
  409. package/src/rule-docs.test.ts +159 -0
  410. package/src/rules-config.ts +40 -11
  411. package/src/tex-requirements.harness.ts +13 -23
  412. package/src/tex-requirements.test.ts +21 -0
  413. package/src/tex-requirements.ts +64 -14
  414. package/src/tex-venue-rules.test.ts +659 -0
  415. package/src/tex-venue-rules.ts +429 -0
  416. package/src/toolchain.harness.mjs +1 -1
  417. package/src/toolchain.test.ts +9 -5
  418. package/src/toolchain.ts +2 -2
  419. package/src/types.ts +5 -3
  420. package/src/venue-rules.test.ts +104 -8
  421. package/src/venue-rules.ts +22 -12
  422. package/templates/paper/paper.tex +2 -1
  423. package/skills/paper-pipeline/scripts/announce.mjs +0 -67
  424. package/skills/paper-pipeline/scripts/announce.test.mjs +0 -102
  425. package/skills/paper-pipeline/scripts/fixtures/clean/PIPELINE-STATUS.md +0 -51
  426. package/skills/paper-pipeline/scripts/fixtures/dirty/PIPELINE-STATUS.md +0 -52
  427. package/skills/paper-pipeline/scripts/fixtures/dirty/paper.md +0 -6
  428. package/skills/paper-pipeline/scripts/fixtures/scorecard.ts +0 -100
  429. package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +0 -302
  430. package/skills/paper-pipeline/scripts/ledger.mjs +0 -623
  431. package/skills/paper-pipeline/scripts/ledger.test.mjs +0 -254
  432. package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +0 -474
  433. package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +0 -328
  434. package/skills/paper-pipeline/scripts/pipeline-check.mjs +0 -750
  435. package/skills/paper-pipeline/scripts/pipeline-edges.mjs +0 -169
  436. package/skills/paper-pipeline/scripts/pipeline-edges.test.mjs +0 -73
  437. package/skills/paper-pipeline/scripts/run-mechanical.mjs +0 -648
  438. package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +0 -468
  439. package/skills/paper-pipeline/scripts/status.mjs +0 -295
  440. package/skills/paper-pipeline/scripts/status.test.mjs +0 -232
  441. /package/{skills/submit-paper/references/venues → presets/tex}/agenticdev.tex +0 -0
  442. /package/{skills/submit-paper/references/venues → presets}/tex-base.jsonc +0 -0
@@ -19,7 +19,7 @@
19
19
  # vigiles lint . README.md 6 s
20
20
  # rules-see-files.mjs 5 s
21
21
  # layer-legacy-frozen.ts 3 s
22
- # install e2e --strict (npm + pnpm) 28 s
22
+ # npm run test:e2e:install (npm+pnpm) 38 s
23
23
  # ───────────────────────────────────────────
24
24
  # total work ~96 s, plus checkout + install + the claude binary
25
25
  #
@@ -178,10 +178,11 @@ jobs:
178
178
  run: corepack enable pnpm
179
179
  timeout-minutes: 2
180
180
 
181
- # Called directly with --strict, the same as the build e2e below. --strict: a manager that does not launch is a declared skip on a
182
- # contributor's clone and a FAILURE here, because in CI it means a broken environment.
183
- - name: install e2e (--strict)
184
- run: node test/e2e/install.ts --strict
181
+ # The vitest project `e2e-install`: pack, install under npm and pnpm, run the binary. A manager
182
+ # that does not launch is a skip on a contributor's clone and a FAILURE here, because `CI` is set
183
+ # and in CI it means a broken environment (test/e2e/need.ts).
184
+ - name: npm run test:e2e:install
185
+ run: npm run test:e2e:install
185
186
  timeout-minutes: 10
186
187
 
187
188
  # ── BUILDING THE PAPER WITH REAL pdflatex, ON LINUX AND macOS ──────────────────────────────────
@@ -199,7 +200,7 @@ jobs:
199
200
  # 🔴 WHY ON EVERY PUSH. It catches silent font substitution — a class that HAS ALREADY shipped a
200
201
  # paper typeset in the wrong font. This repository is public, so the macOS minutes are free.
201
202
  #
202
- # `--strict`: absence of TeX locally is a legitimate skip; here it is an environment failure.
203
+ # `CI` is set: absence of TeX locally is a legitimate skip; here it is an environment failure.
203
204
  build-e2e:
204
205
  if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
205
206
  strategy:
@@ -258,7 +259,7 @@ jobs:
258
259
  uses: actions/cache@v6
259
260
  with:
260
261
  path: ~/.cache/paperlint-texlive
261
- key: texlive-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('skills/submit-paper/references/venues/*.jsonc') }}
262
+ key: texlive-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('presets/*.jsonc') }}
262
263
 
263
264
  # The same command a user runs. On a cache hit it verifies and says "nothing to do"; on a miss
264
265
  # it installs from an empty directory and verifies every declared file with kpsewhich.
@@ -271,19 +272,11 @@ jobs:
271
272
  run: node bin/paperlint.mjs toolchain
272
273
  timeout-minutes: 15
273
274
 
274
- # Proves banal works without poppler. This runner has no poppler, and the test also limits
275
- # PATH to perl. paperlint turns each fixture PDF into XML with pdf.js, banal measures it, and the
276
- # result must equal the numbers banal gave on the same PDFs through poppler's pdftohtml
277
- # (recorded once, hardcoded in the test). Runs in seconds, hence the short timeout.
278
- - name: banal e2e (--strict)
279
- run: node test/e2e/banal.ts --strict
280
- timeout-minutes: 3
281
-
282
- # Called directly with --strict (see the install e2e step in the `gates` job).
283
- - name: build e2e (--strict)
284
- run: node test/e2e/build.ts --strict
285
- timeout-minutes: 10
286
-
287
- - name: toolchain e2e (--strict)
288
- run: node test/e2e/toolchain.ts --strict
289
- timeout-minutes: 10
275
+ # Every e2e test under test/e2e/tex/, found by the vitest project `e2e-tex`: the toolchain again
276
+ # (a no-op on the tree above, then a build with only it on PATH), the real banal on the XML
277
+ # paperlint writes (no poppler on this runner), and a real pdflatex build of every fixture in
278
+ # fixtures/build-e2e/, each against its own expect.json. `CI` is set on every runner, so a
279
+ # missing TeX Live or banal FAILS here instead of skipping (test/e2e/need.ts).
280
+ - name: npm run test:e2e:tex
281
+ run: npm run test:e2e:tex
282
+ timeout-minutes: 20
package/CLAUDE.md CHANGED
@@ -77,6 +77,13 @@ and stay QUIET on a clean fixture. A check that has only been seen quiet is
77
77
  indistinguishable from a dead one — silence is its success state. Prove the fire half by
78
78
  seeing the test go RED before the fix lands ([`docs/testing.md`](docs/testing.md)).
79
79
 
80
+ **A new rule ships with its page**, `docs/rules/<group>/<rule>.md`, in these sections: What it
81
+ catches · Why · Examples (failing / passing) · Options / preset fields · What it does not check ·
82
+ How to fix. Its `meta.docs.url` points at that page, and its row in `docs/rules.md` is one line
83
+ linking there. `src/rule-docs.test.ts` holds every rule the config registers to this; the rules
84
+ older than the convention wait in its `AWAITING_PAGE` list, which only shrinks — #131 writes their
85
+ pages.
86
+
80
87
  **4. `exit 0` with empty output is NOT "clean".** A rule whose glob matched no files reports
81
88
  exactly like a rule that passed. Any rule shipped here must be loud when its input set is
82
89
  empty. This is the specific defect that blocks stage 1 of the plan: in the source base a
@@ -150,13 +157,15 @@ Four proposals were made and withdrawn in one session on 2026-09-17 for exactly
150
157
 
151
158
  **10. Effects live in adapters, and WHERE paperlint IS INSTALLED lives in ONE of them.** Rule 6 generalised: the caller's cwd is one case of it. Checking logic — lint rules,
152
159
  skills, hooks — must not know its own location, nor its distance from anything else. Every
153
- answer to _where_ comes from `skills/paper-pipeline/scripts/consumer.mjs`, which adapts per
154
- channel: own checkout · `node_modules` · plugin cache · CI. A skill naming a script by an
155
- install-specific path in its own prose walks around that door, and 208 such literals across 190
156
- lines do exactly that.
160
+ answer to _where_ comes from one of two modules, each for one side: the consumer (its root, the
161
+ package's name) from `skills/paper-pipeline/scripts/consumer.mjs`, which adapts per channel — own
162
+ checkout · `node_modules` · plugin cache · CI; the package's own data (`presets/`, `presets/tex/`)
163
+ from `src/package-dirs.ts`. A skill naming a script by an install-specific path in its own prose
164
+ walks around that door, and 208 such literals across 190 lines do exactly that.
157
165
 
158
- <!-- The port's path above is resolved by `npm run check` (vigiles lint), since #67. -->
166
+ <!-- The ports' paths above are resolved by `npm run check` (vigiles lint), since #67. -->
159
167
  <!-- vigiles:file skills/paper-pipeline/scripts/consumer.mjs -->
168
+ <!-- vigiles:file src/package-dirs.ts -->
160
169
 
161
170
  The layer rules for `src/` live in [`src/CLAUDE.md`](src/CLAUDE.md) and are enforced by the linter.
162
171
 
@@ -363,8 +372,8 @@ paid for by a consumer who only wants the ESLint rules and never loads a hook.
363
372
 
364
373
  `optional: true` is the entry that matches what this section already argues: the consumer brings
365
374
  its own `vigiles` _when it uses the hooks_, and npm stops deciding that for them. Both halves
366
- measured on the 56 MB tree: `eslint-rules/latex-language.mjs` and
367
- `skills/paper-pipeline/scripts/pipeline-check.mjs` load and run (RC=0), while
375
+ measured on the 56 MB tree: `eslint-rules/latex-language.mjs` and the skill scripts load and
376
+ run (RC=0), while
368
377
  `hooks/paper-edit-guard.hook.mjs` fails with `ERR_MODULE_NOT_FOUND` — which is this contract
369
378
  working, not a defect, exactly as argued below.
370
379
 
@@ -493,18 +502,29 @@ justified two hundred lines above precisely by these minutes being free.
493
502
 
494
503
  ## Testing
495
504
 
496
- | you are testing | kind |
497
- | -------------------------------------------------------------------------- | --------------------------------------------- |
498
- | a pure function | unit — vitest, `<module>.test.ts` beside it |
499
- | a use case or adapter that reaches disk, a process, the network, the clock | integration — vitest, fakes through the ports |
500
- | a hook's decision, a skill's contract | harness — vigiles, `<surface>.harness.ts` |
501
- | the installed package, a real TeX build | e2e — `test/e2e/*.ts` |
505
+ | you are testing | kind |
506
+ | -------------------------------------------------------------------------- | ----------------------------------------------------------- |
507
+ | a pure function | unit — vitest, `<module>.test.ts` beside it |
508
+ | a use case or adapter that reaches disk, a process, the network, the clock | integration — vitest, fakes through the ports |
509
+ | a hook's decision, a skill's contract | harness — vigiles, `<surface>.harness.ts` |
510
+ | the installed package, a real TeX build | e2e — `test/e2e/<area>/*.e2e.ts`, `npm run test:e2e:<area>` |
502
511
 
503
512
  Red first · assert the whole value · test what the code does, never what its source says · no test
504
513
  touches the real network · 100% coverage, no `c8 ignore`. **Before every push: `npm run check`,
505
514
  exit code read without a pipe.** Everything else — where files live, how fakes are injected, the
506
515
  `--min=1` trap: [`docs/testing.md`](docs/testing.md).
507
516
 
517
+ **A new rule** needs unit tests beside it and a reporting and a silent case in
518
+ `src/rule-cases.test.ts`, which runs every registered rule through real ESLint and fails on one
519
+ without cases. An e2e fixture only when [`docs/e2e.md`](docs/e2e.md)'s triggers say so.
520
+
521
+ **New code is functional.** In `src/`, `eslint-rules/` and `lib/` (tests aside) there is no
522
+ `let`, no mutation, no loop, and types are read-only (`eslint-plugin-functional`); a `switch` over a
523
+ union names every member. Collections go through [Remeda](https://remedajs.com/) — `lodash`,
524
+ `lodash-es` and `ramda` are refused by `npm run lint`. Old code is listed in
525
+ `eslint-suppressions.json`, ESLint's own bulk suppressions, which may only shrink: fixing a listed
526
+ site without `npx eslint . --prune-suppressions` fails lint, and #134 burns the list down.
527
+
508
528
  ## Commits
509
529
 
510
530
  Conventional-commit subject, body says what was MEASURED, not what was intended. A number in
package/CONTRIBUTING.md CHANGED
@@ -37,12 +37,14 @@ install e2e under npm and pnpm, and a real `pdflatex` build — and ends
37
37
  by printing **which CI jobs it does not reproduce, and why**.
38
38
 
39
39
  🔴 **There is no `--fast` flag, and that is the point.** On 2026-09-19 a rule change was pushed
40
- that broke the suite: the gates were run afterwards and were green, but `npm test` and
41
- `test:install` were not among them, because there were eleven separate scripts and the only way
40
+ that broke the suite: the gates were run afterwards and were green, but `npm test` and the
41
+ install e2e were not among them, because there were eleven separate scripts and the only way
42
42
  to run them all was from memory. A subset flag re-creates exactly that — the cheap half gets run
43
43
  and reported as "the gates". If a step genuinely cannot run here, it says so out loud rather than
44
- being skipped quietly: an e2e that finds no TeX or no pnpm exits 77 _having stated_ why, and
45
- `npm run check` lists it as skipped instead of counting it as passed.
44
+ being skipped quietly: an e2e test that finds no TeX or no pnpm is reported SKIPPED by vitest,
45
+ and `npm run check` reads that count from vitest's JSON report and lists the gate as skipped
46
+ instead of counting it as passed. The e2e areas also run alone: `npm run test:e2e:install`,
47
+ `npm run test:e2e:tex`, or both with `npm run test:e2e`.
46
48
 
47
49
  Each gate's command is listed in `scripts/check.ts`; run one of them directly while iterating on
48
50
  one rule. They are not what you run before pushing.
@@ -75,6 +77,13 @@ Most of the package's rules run on users' papers and are described for users in
75
77
  [`docs/rules.md`](docs/rules.md); the rest lint this package's own source and never see a user's
76
78
  files.
77
79
 
80
+ A new rule ships with its page, `docs/rules/<group>/<rule>.md`, in these sections: What it
81
+ catches · Why · Examples (failing / passing) · Options / preset fields · What it does not check ·
82
+ How to fix. Its `meta.docs.url` points at that page, and its row in `docs/rules.md` is one line
83
+ linking there. `src/rule-docs.test.ts` holds every rule the config registers to this; the rules
84
+ older than the convention wait in its `AWAITING_PAGE` list, which only shrinks — #131 writes their
85
+ pages.
86
+
78
87
  ## Maintainer docs
79
88
 
80
89
  The README links only what a user needs. These are for people changing the package:
@@ -102,6 +111,13 @@ npm run coverage # the same, under c8, failing below the thresholds in .
102
111
  None of these are needed to USE the tool — they are here because the gates are part of the
103
112
  argument, not decoration.
104
113
 
114
+ **New code is functional.** In `src/`, `eslint-rules/` and `lib/` (tests aside) there is no
115
+ `let`, no mutation, no loop, and types are read-only (`eslint-plugin-functional`); a `switch` over a
116
+ union names every member. Collections go through [Remeda](https://remedajs.com/) — `lodash`,
117
+ `lodash-es` and `ramda` are refused by `npm run lint`. Old code is listed in
118
+ `eslint-suppressions.json`, ESLint's own bulk suppressions, which may only shrink: fixing a listed
119
+ site without `npx eslint . --prune-suppressions` fails lint, and #134 burns the list down.
120
+
105
121
  New code is TypeScript (#78). The last block of [`eslint.config.mjs`](eslint.config.mjs) makes any
106
122
  `.js`, `.mjs` or `.cjs` file an error in the directories already converted (`TYPESCRIPT_ONLY`), so
107
123
  `npm run lint` fails on one; a directory that still mixes the two is not listed yet, and the change
@@ -139,17 +155,17 @@ change to `.c8rc.json`'s exclude list that was not made there on purpose.
139
155
 
140
156
  ## Adding a venue
141
157
 
142
- A venue is a **preset**, a JSONC file in `skills/submit-paper/references/venues/`, validated by
158
+ A venue is a **preset**, a JSONC file in `presets/`, validated by
143
159
  `venue-profile.schema.json` beside it. Adding one is three files and no code:
144
160
 
145
- 1. **The preset, thin.** `venues/<name>.jsonc` extends the template family it is built on
161
+ 1. **The preset, thin.** `presets/<name>.jsonc` extends the template family it is built on
146
162
  (`"extends": "paperlint:acm-sigconf"` for an ACM venue) and adds only what the call for papers
147
163
  sets: `format.kinds` (the page limit of each kind of paper) and, when the venue's producer asks
148
164
  for something an optional rule checks, `rules`. Every number carries the quote it came from.
149
165
  A venue on a template with no family yet stands alone (`template`, `tex`, `format`) — or, better,
150
166
  add the family first: measured on a real template build (banal + pdf.js), not copied from
151
167
  documentation ([#88](https://github.com/zernie/paperlint/issues/88)).
152
- 2. **The card.** `venues/<name>.md` — prose about the venue: deadlines, tracks, the blind model,
168
+ 2. **The card.** `skills/submit-paper/references/venues/<name>.md` — prose about the venue: deadlines, tracks, the blind model,
153
169
  what the form asks.
154
170
  3. **A test.** A case in `src/presets.test.ts` that `paperlint:<name>` resolves over its family with
155
171
  the kinds you declared; `src/tex-requirements.harness.ts` already checks every shipped preset
package/README.md CHANGED
@@ -69,14 +69,17 @@ build: compiles and measures the PDF; lint then checks pages, fonts, references
69
69
  A **venue preset** holds a venue's format and page limits. A paper's **kind** picks which limit
70
70
  applies: at AgenticDev a `short` paper gets 5 pages and a `full` one 10. You choose it once per paper.
71
71
 
72
- | preset | venue | format | kinds and page limits |
73
- | ----------------------- | ------------------ | ------------------ | ------------------------------------------------------------------------------------------- |
74
- | `paperlint:acm-sigconf` | any ACM conference | ACM two-column | no kinds: the format only, no page limit |
75
- | `paperlint:agenticdev` | AgenticDev @ ASE | ACM two-column | `short` 5, `full` 10, `demo` 5 pages, + 2 pages of references |
76
- | `paperlint:aisec` | AISec @ ACM CCS | ACM two-column | `research`, `benchmark`, `position`, `sok`: 10 pages + 2 pages of references |
77
- | `paperlint:realm` | REALM @ EMNLP | ACL two-column, A4 | `long` 8, `short` 4 — recorded, not checked ([why](docs/rules.md#checks-against-the-venue)) |
78
-
79
- Not shipped yet: IEEE, USENIX, NeurIPS, Springer, and ACL venues other than REALM.
72
+ | preset | venue | format | kinds and page limits |
73
+ | --------------------------- | ------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
74
+ | `paperlint:acm-sigconf` | any ACM conference | ACM two-column | no kinds: the format only, no page limit |
75
+ | `paperlint:agenticdev` | AgenticDev @ ASE | ACM two-column | `short` 5, `full` 10, `demo` 5 pages, + 2 pages of references |
76
+ | `paperlint:aisec` | AISec @ ACM CCS | ACM two-column | `research`, `benchmark`, `position`, `sok`: 10 pages + 2 pages of references |
77
+ | `paperlint:realm` | REALM @ EMNLP | ACL two-column, A4 | `long` 8, `short` 4 — recorded, not checked ([why](docs/rules.md#checks-against-the-venue)) |
78
+ | `paperlint:ieee-conference` | any IEEE conference | IEEE two-column | no kinds: the format only, no page limit |
79
+ | `paperlint:aidc` | AIDC @ IEEE ACSAC | IEEE two-column, `compsoc` | `regular` 12, `short` 6 — recorded, not checked ([why](docs/rules.md#checks-against-the-venue)); requires the «LLM Usage Statement» |
80
+
81
+ Not shipped yet: USENIX, NeurIPS, Springer, IEEE venues other than AIDC, and ACL venues other than
82
+ REALM.
80
83
  [Add yours](#-add-a-venue-that-isnt-listed) in one small file.
81
84
 
82
85
  ## 🚀 Getting started
@@ -60,13 +60,7 @@ export type BanalFailure = {
60
60
  readonly why: BanalFailure;
61
61
  };
62
62
  export declare const PERL_MISSING: string;
63
- /**
64
- * What to tell a person. Most failures are one line; a sha256 mismatch shows both hashes.
65
- *
66
- * The one assertion below narrows the table's entry for `f.kind` to a function of `f`: the mapped
67
- * type already pairs each kind with its own variant, and TypeScript cannot correlate the index with
68
- * the argument on its own.
69
- */
63
+ /** What to tell a person. Most failures are one line; a sha256 mismatch shows both hashes. */
70
64
  export declare function describe(f: BanalFailure): Lines;
71
65
  /** `describe` as one line, for a caller that has a single line to fill. */
72
66
  export declare function describeLine(f: BanalFailure): string;
@@ -1 +1 @@
1
- {"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/failure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAClE;IACE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACrD,0FAA0F;GACxF;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAC1D;IACE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AACH,uDAAuD;GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACxD,kEAAkE;GAChE;IACE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEN,eAAO,MAAM,YAAY,QAE+E,CAAC;AAmDzG;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,YAAY,GAAG,KAAK,CAG/C;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/failure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAClE;IACE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACrD,0FAA0F;GACxF;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAC1D;IACE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AACH,uDAAuD;GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACxD,kEAAkE;GAChE;IACE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEN,eAAO,MAAM,YAAY,QAE+E,CAAC;AAyDzG,8FAA8F;AAC9F,wBAAgB,QAAQ,CAAC,CAAC,EAAE,YAAY,GAAG,KAAK,CAE/C;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAEpD"}
@@ -41,15 +41,13 @@ const DESCRIBE = {
41
41
  ],
42
42
  };
43
43
  /**
44
- * What to tell a person. Most failures are one line; a sha256 mismatch shows both hashes.
45
- *
46
- * The one assertion below narrows the table's entry for `f.kind` to a function of `f`: the mapped
47
- * type already pairs each kind with its own variant, and TypeScript cannot correlate the index with
48
- * the argument on its own.
44
+ * The describer for `kind`, applied to its own variant. Generic over the kind, so the table's entry
45
+ * and the argument are correlated through `FailureOf[K]` and need no assertion (TypeScript#47109).
49
46
  */
47
+ const describeKind = (kind, f) => DESCRIBE[kind](f);
48
+ /** What to tell a person. Most failures are one line; a sha256 mismatch shows both hashes. */
50
49
  export function describe(f) {
51
- const write = DESCRIBE[f.kind];
52
- return write(f);
50
+ return describeKind(f.kind, f);
53
51
  }
54
52
  /** `describe` as one line, for a caller that has a single line to fill. */
55
53
  export function describeLine(f) {
@@ -1 +1 @@
1
- {"version":3,"file":"failure.js","sourceRoot":"","sources":["../../../src/adapters/banal/failure.ts"],"names":[],"mappings":"AAiDA,MAAM,CAAC,MAAM,YAAY,GACvB,0FAA0F;IAC1F,sGAAsG,CAAC;AAEzG,SAAS,OAAO,CAAC,CAAe;IAC9B,OAAO,CAAC,CAAC,IAAI,KAAK,oBAAoB;QACpC,CAAC,CAAC,iCAAiC,CAAC,CAAC,IAAI,wBAAwB;QACjE,CAAC,CAAC,oBAAoB,CAAC,CAAC,SAAS,4CAA4C,CAAC;AAClF,CAAC;AAQD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC;AAEvD,MAAM,QAAQ,GAAe;IAC3B,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC;IACpC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5C,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,sBAAsB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;KACnE;IACD,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,MAAM,MAAM,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;IACzE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC;IACrD,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iCAAiC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IAC7E,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,0BAA0B,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC;IACnE,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACpB,6CAA6C,CAAC,CAAC,UAAU,EAAE;KAC5D;IACD,kBAAkB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACzB,iDAAiD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KACvE;IACD,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,uDAAuD,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;KAC/E;IACD,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACxB,iCAAiC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE;KACtD;IACD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACrB,cAAc,CAAC,CAAC,GAAG,2DAA2D;QAC9E,YAAY,CAAC,CAAC,QAAQ,EAAE;QACxB,YAAY,CAAC,CAAC,GAAG,EAAE;KACpB;IACD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACnB,YAAY,CAAC,CAAC,IAAI,yCAAyC;KAC5D;IACD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACrB,YAAY,CAAC,CAAC,IAAI,kBAAkB,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;KAC1D;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAe;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAA+B,CAAC;IAC7D,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAAC,CAAe;IAC1C,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"failure.js","sourceRoot":"","sources":["../../../src/adapters/banal/failure.ts"],"names":[],"mappings":"AAiDA,MAAM,CAAC,MAAM,YAAY,GACvB,0FAA0F;IAC1F,sGAAsG,CAAC;AAEzG,SAAS,OAAO,CAAC,CAAe;IAC9B,OAAO,CAAC,CAAC,IAAI,KAAK,oBAAoB;QACpC,CAAC,CAAC,iCAAiC,CAAC,CAAC,IAAI,wBAAwB;QACjE,CAAC,CAAC,oBAAoB,CAAC,CAAC,SAAS,4CAA4C,CAAC;AAClF,CAAC;AAOD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC;AAEvD,MAAM,QAAQ,GAAe;IAC3B,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC;IACpC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5C,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,sBAAsB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;KACnE;IACD,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,MAAM,MAAM,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;IACzE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC;IACrD,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iCAAiC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IAC7E,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,0BAA0B,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC;IACnE,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACpB,6CAA6C,CAAC,CAAC,UAAU,EAAE;KAC5D;IACD,kBAAkB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACzB,iDAAiD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KACvE;IACD,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,uDAAuD,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;KAC/E;IACD,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACxB,iCAAiC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE;KACtD;IACD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACrB,cAAc,CAAC,CAAC,GAAG,2DAA2D;QAC9E,YAAY,CAAC,CAAC,QAAQ,EAAE;QACxB,YAAY,CAAC,CAAC,GAAG,EAAE;KACpB;IACD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACnB,YAAY,CAAC,CAAC,IAAI,yCAAyC;KAC5D;IACD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QACrB,YAAY,CAAC,CAAC,IAAI,kBAAkB,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;KAC1D;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,YAAY,GAAG,CAAiB,IAAO,EAAE,CAAe,EAAS,EAAE,CACvE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpB,8FAA8F;AAC9F,MAAM,UAAU,QAAQ,CAAC,CAAe;IACtC,OAAO,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAAC,CAAe;IAC1C,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAS,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAIL,KAAK,SAAS,EAEd,KAAK,WAAW,EACjB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EACL,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAS5C,mGAAmG;AACnG,wBAAgB,aAAa,CAC3B,CAAC,EAAE,SAAS,EACZ,CAAC,EAAE,aAAa,EAChB,WAAW,EAAE,YAAY,GACxB,eAAe,CAajB;AAaD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,WAAW,EACd,CAAC,EAAE,aAAa,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,aAAa,CAiBf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAIL,KAAK,SAAS,EAEd,KAAK,WAAW,EACjB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EACL,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAS5C,mGAAmG;AACnG,wBAAgB,aAAa,CAC3B,CAAC,EAAE,SAAS,EACZ,CAAC,EAAE,aAAa,EAChB,WAAW,EAAE,YAAY,GACxB,eAAe,CAajB;AAUD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,WAAW,EACd,CAAC,EAAE,aAAa,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,aAAa,CAiBf"}
@@ -1,4 +1,5 @@
1
1
  import { err, ok } from "../../domain/result.js";
2
+ import { ready } from "../../domain/ready.js";
2
3
  import { describe } from "./failure.js";
3
4
  import { provenanceLabel } from "./locate.js";
4
5
  import { pinLabel } from "./pin.js";
@@ -26,15 +27,11 @@ export function banalMeasurer(d, s, projectRoot) {
26
27
  };
27
28
  }
28
29
  /** The one place banal's `Ready` is minted: from an `Installed`, whose `PinnedBanal` only run.ts mints. */
29
- const ready = (i) => {
30
- // Widened by annotation: the brand of the path is not part of `Ready`'s shape.
31
- const where = i.banal.path;
32
- return {
33
- where,
34
- fresh: i.fresh,
35
- verified: "sha256 verified, and it measured a probe page",
36
- };
37
- };
30
+ const readyOf = (i) => ready({
31
+ where: i.banal.path,
32
+ fresh: i.fresh,
33
+ verified: "sha256 verified, and it measured a probe page",
34
+ });
38
35
  /**
39
36
  * banal as the `ToolInstaller` port: download at the pin, check the sha256, accept by measuring a
40
37
  * probe page. `source` is the pin unless a test passes a local file.
@@ -47,12 +44,12 @@ export function banalInstaller(d, s, source) {
47
44
  ...(source ? { source } : {}),
48
45
  onDownload: report,
49
46
  });
50
- return r.ok ? ok(ready(r.value)) : err(describe(r.error));
47
+ return r.ok ? ok(readyOf(r.value)) : err(describe(r.error));
51
48
  },
52
49
  check() {
53
50
  const r = checkBanal(d, s, source);
54
51
  return r.ok
55
- ? ok(ready({ banal: r.value, fresh: false }))
52
+ ? ok(readyOf({ banal: r.value, fresh: false }))
56
53
  : err(describe(r.error));
57
54
  },
58
55
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/banal/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAuB,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAoB,MAAM,UAAU,CAAC;AACtD,OAAO,EACL,UAAU,EACV,WAAW,EACX,eAAe,GAIhB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,aAAa,EACb,SAAS,EACT,kBAAkB,GAEnB,MAAM,eAAe,CAAC;AAIvB,gGAAgG;AAChG,MAAM,UAAU,GAAG,CAAC,CAAiB,EAAc,EAAE,CAAC,CAAC;IACrD,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,CAAC,CAAC,IAAI;IACZ,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;CACnC,CAAC,CAAC;AAEH,mGAAmG;AACnG,MAAM,UAAU,aAAa,CAC3B,CAAY,EACZ,CAAgB,EAChB,WAAyB;IAEzB,OAAO;QACL,OAAO,CAAC,KAAK;YACX,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC,MAAM,KAAK,OAAO;gBACzB,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE;gBAClE,CAAC,CAAC;oBACE,IAAI,EAAE,YAAY;oBAClB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;oBACpB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;iBAC5C,CAAC;QACR,CAAC;KACF,CAAC;AACJ,CAAC;AAED,2GAA2G;AAC3G,MAAM,KAAK,GAAG,CAAC,CAAY,EAAS,EAAE;IACpC,+EAA+E;IAC/E,MAAM,KAAK,GAAW,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IACnC,OAAO;QACL,KAAK;QACL,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,QAAQ,EAAE,+CAA+C;KACjD,CAAC;AACb,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,CAAc,EACd,CAAgB,EAChB,MAAoB;IAEpB,OAAO;QACL,KAAK,EAAE,QAAQ,EAAE;QACjB,MAAM,CAAC,MAAM;YACX,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE;gBAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7B,UAAU,EAAE,MAAM;aACnB,CAAC,CAAC;YACH,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,KAAK;YACH,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YACnC,OAAO,CAAC,CAAC,EAAE;gBACT,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC7C,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/banal/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAc,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAuB,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAoB,MAAM,UAAU,CAAC;AACtD,OAAO,EACL,UAAU,EACV,WAAW,EACX,eAAe,GAIhB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,aAAa,EACb,SAAS,EACT,kBAAkB,GAEnB,MAAM,eAAe,CAAC;AAIvB,gGAAgG;AAChG,MAAM,UAAU,GAAG,CAAC,CAAiB,EAAc,EAAE,CAAC,CAAC;IACrD,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,CAAC,CAAC,IAAI;IACZ,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;CACnC,CAAC,CAAC;AAEH,mGAAmG;AACnG,MAAM,UAAU,aAAa,CAC3B,CAAY,EACZ,CAAgB,EAChB,WAAyB;IAEzB,OAAO;QACL,OAAO,CAAC,KAAK;YACX,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC,MAAM,KAAK,OAAO;gBACzB,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE;gBAClE,CAAC,CAAC;oBACE,IAAI,EAAE,YAAY;oBAClB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;oBACpB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;iBAC5C,CAAC;QACR,CAAC;KACF,CAAC;AACJ,CAAC;AAED,2GAA2G;AAC3G,MAAM,OAAO,GAAG,CAAC,CAAY,EAAS,EAAE,CACtC,KAAK,CAAC;IACJ,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI;IACnB,KAAK,EAAE,CAAC,CAAC,KAAK;IACd,QAAQ,EAAE,+CAA+C;CAC1D,CAAC,CAAC;AAEL;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,CAAc,EACd,CAAgB,EAChB,MAAoB;IAEpB,OAAO;QACL,KAAK,EAAE,QAAQ,EAAE;QACjB,MAAM,CAAC,MAAM;YACX,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE;gBAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7B,UAAU,EAAE,MAAM;aACnB,CAAC,CAAC;YACH,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,KAAK;YACH,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YACnC,OAAO,CAAC,CAAC,EAAE;gBACT,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC/C,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/install.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,iGAAiG;AACjG,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,GAClB,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAKlC;AAED,iDAAiD;AACjD,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEhC,wBAAgB,cAAc,CAC5B,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,MAAM,EAAE,WAAW,GAClB,cAAc,CAIhB"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/install.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,iGAAiG;AACjG,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAQD,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,GAClB,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAIlC;AAED,iDAAiD;AACjD,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEhC,wBAAgB,cAAc,CAC5B,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,MAAM,EAAE,WAAW,GAClB,cAAc,CAIhB"}
@@ -1,10 +1,11 @@
1
1
  import { err, ok } from "../../domain/result.js";
2
2
  import { sha256Hex } from "../../domain/sha256.js";
3
+ // The brand's one owner: the predicate IS the pin check, so no assertion is needed to mint the type.
4
+ const isPinned = (bytes, source) => sha256Hex(bytes) === source.sha256;
3
5
  export function verifyPin(bytes, source) {
4
- const got = sha256Hex(bytes);
5
- return got === source.sha256
6
+ return isPinned(bytes, source)
6
7
  ? ok(bytes)
7
- : err({ expected: source.sha256, got });
8
+ : err({ expected: source.sha256, got: sha256Hex(bytes) });
8
9
  }
9
10
  export function installedState(current, source) {
10
11
  if (current === null)
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/adapters/banal/install.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAe,MAAM,wBAAwB,CAAC;AAWhE,MAAM,UAAU,SAAS,CACvB,KAAiB,EACjB,MAAmB;IAEnB,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,GAAG,KAAK,MAAM,CAAC,MAAM;QAC1B,CAAC,CAAC,EAAE,CAAC,KAAoB,CAAC;QAC1B,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAC5C,CAAC;AAQD,MAAM,UAAU,cAAc,CAC5B,OAA0B,EAC1B,MAAmB;IAEnB,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAChD,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;AAChF,CAAC"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/adapters/banal/install.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAe,MAAM,wBAAwB,CAAC;AAWhE,qGAAqG;AACrG,MAAM,QAAQ,GAAG,CACf,KAAiB,EACjB,MAAmB,EACG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC;AAE9D,MAAM,UAAU,SAAS,CACvB,KAAiB,EACjB,MAAmB;IAEnB,OAAO,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAC5B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QACX,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC;AAQD,MAAM,UAAU,cAAc,CAC5B,OAA0B,EAC1B,MAAmB;IAEnB,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAChD,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;AAChF,CAAC"}
@@ -7,18 +7,20 @@
7
7
  * (`Error: Failed to run pdftohtml`, measured); told a version below 0.85 it applies a larger
8
8
  * correction and every font size moves. So `$PDFTOHTML` (banal's own override, line 166) points at a
9
9
  * stub that answers `-v` with `XML_DIALECT.version` — the pdftohtml whose XML `xml.ts` writes — and
10
- * refuses anything else. `test/e2e/banal.ts` shows both failures with the real banal.
10
+ * refuses anything else. `test/e2e/tex/banal.e2e.ts` shows both failures with the real banal.
11
11
  */
12
12
  import type { Opaque } from "ts-essentials";
13
13
  import type { AbsolutePath } from "../../domain/paths.ts";
14
14
  import type { Command } from "../../ports/process.ts";
15
15
  import type { Scratch } from "../../ports/workspace.ts";
16
- import type { LocatedBanal } from "./locate.ts";
16
+ import type { BanalCandidate } from "./locate.ts";
17
17
  import type { PageLayout } from "../../domain/page-layout.ts";
18
18
  /** banal takes well under a second on a paper; a hang still has to end. */
19
19
  export declare const BANAL_RUN_MS = 120000;
20
20
  /** A path quoted for `/bin/sh`. Minted by `shQuote` only. */
21
21
  export type ShQuoted = Opaque<string, "ShQuoted">;
22
+ /** A word already quoted for `/bin/sh`, checked; anything else throws. */
23
+ export declare function parseShQuoted(s: string): ShQuoted;
22
24
  /** banal interpolates `$PDFTOHTML` into a shell command unquoted — so the value is quoted here. */
23
25
  export declare const shQuote: (s: string) => ShQuoted;
24
26
  /** The stub standing in for `pdftohtml`: it answers `-v` and refuses to convert anything. */
@@ -36,13 +38,16 @@ export interface BanalStaging {
36
38
  ];
37
39
  }
38
40
  export declare const stageBanalInput: (pages: readonly PageLayout[]) => BanalStaging;
41
+ declare const STAGED: unique symbol;
39
42
  /** The staging written to disk. Minted by `stage` only: both files written, or nothing returned. */
40
- export type StagedInput = Opaque<{
43
+ export interface StagedInput {
41
44
  readonly xml: AbsolutePath;
42
45
  readonly stub: AbsolutePath;
43
- }, "StagedInput">;
46
+ readonly [STAGED]: true;
47
+ }
44
48
  /** Write a staging into a scratch directory, the stub executable. The only minter of `StagedInput`. */
45
49
  export declare function stage(s: Scratch, staging: BanalStaging): StagedInput;
46
50
  /** `perl banal -no-time -json <xml>`, with `$PDFTOHTML` quoted by construction. */
47
- export declare function banalCommand(banal: LocatedBanal, staged: StagedInput, baseEnv: Readonly<Record<string, string>>): Command;
51
+ export declare function banalCommand(banal: Pick<BanalCandidate, "path">, staged: StagedInput, baseEnv: Readonly<Record<string, string>>): Command;
52
+ export {};
48
53
  //# sourceMappingURL=invocation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"invocation.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/invocation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,2EAA2E;AAC3E,eAAO,MAAM,YAAY,SAAU,CAAC;AAEpC,6DAA6D;AAC7D,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAElD,mGAAmG;AACnG,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,KAAG,QACS,CAAC;AAE9C,6FAA6F;AAC7F,eAAO,MAAM,cAAc,QAWf,CAAC;AAEb,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IACrE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CAClB;AAED,yGAAyG;AACzG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS;QACvB,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC;QAC/B,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,eAAO,MAAM,eAAe,GAC1B,OAAO,SAAS,UAAU,EAAE,KAC3B,YAKD,CAAC;AAEH,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG,MAAM,CAC9B;IAAE,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,EAC3D,aAAa,CACd,CAAC;AAEF,uGAAuG;AACvG,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAMpE;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAC1B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACxC,OAAO,CAQT"}
1
+ {"version":3,"file":"invocation.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/invocation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,2EAA2E;AAC3E,eAAO,MAAM,YAAY,SAAU,CAAC;AAEpC,6DAA6D;AAC7D,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAMlD,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAGjD;AAED,mGAAmG;AACnG,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,KAAG,QACY,CAAC;AAEjD,6FAA6F;AAC7F,eAAO,MAAM,cAAc,QAWf,CAAC;AAEb,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IACrE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CAClB;AAED,yGAAyG;AACzG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS;QACvB,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC;QAC/B,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,eAAO,MAAM,eAAe,GAC1B,OAAO,SAAS,UAAU,EAAE,KAC3B,YAKD,CAAC;AAGH,QAAA,MAAM,MAAM,eAAwB,CAAC;AAErC,oGAAoG;AACpG,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;CACzB;AAED,uGAAuG;AACvG,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAOpE;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAC1B,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,EACnC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACxC,OAAO,CAQT"}
@@ -1,8 +1,17 @@
1
1
  import { pdf2xml, XML_DIALECT } from "./xml.js";
2
2
  /** banal takes well under a second on a paper; a hang still has to end. */
3
3
  export const BANAL_RUN_MS = 120_000;
4
+ // One single-quoted word: any run of non-quotes, each quote spelled `'"'"'`. What `shQuote` writes.
5
+ const SH_QUOTED = /^'(?:[^']|'"'"')*'$/;
6
+ const isShQuoted = (s) => SH_QUOTED.test(s);
7
+ /** A word already quoted for `/bin/sh`, checked; anything else throws. */
8
+ export function parseShQuoted(s) {
9
+ if (!isShQuoted(s))
10
+ throw new Error(`not one single-quoted shell word: ${s}`);
11
+ return s;
12
+ }
4
13
  /** banal interpolates `$PDFTOHTML` into a shell command unquoted — so the value is quoted here. */
5
- export const shQuote = (s) => `'${s.replace(/'/g, `'"'"'`)}'`;
14
+ export const shQuote = (s) => parseShQuoted(`'${s.replace(/'/g, `'"'"'`)}'`);
6
15
  /** The stub standing in for `pdftohtml`: it answers `-v` and refuses to convert anything. */
7
16
  export const PDFTOHTML_STUB = [
8
17
  "#!/bin/sh",
@@ -22,12 +31,15 @@ export const stageBanalInput = (pages) => ({
22
31
  { name: "pdftohtml", content: PDFTOHTML_STUB, mode: "exec" },
23
32
  ],
24
33
  });
34
+ // Not exported: only `stage` can write the property, so only it can make a StagedInput.
35
+ const STAGED = Symbol("StagedInput");
25
36
  /** Write a staging into a scratch directory, the stub executable. The only minter of `StagedInput`. */
26
37
  export function stage(s, staging) {
27
38
  const [xml, stub] = staging.files;
28
39
  return {
29
40
  xml: s.write(xml.name, xml.content, xml.mode),
30
41
  stub: s.write(stub.name, stub.content, stub.mode),
42
+ [STAGED]: true,
31
43
  };
32
44
  }
33
45
  /** `perl banal -no-time -json <xml>`, with `$PDFTOHTML` quoted by construction. */
@@ -1 +1 @@
1
- {"version":3,"file":"invocation.js","sourceRoot":"","sources":["../../../src/adapters/banal/invocation.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEhD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAKpC,mGAAmG;AACnG,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAY,EAAE,CAC7C,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAe,CAAC;AAE9C,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW;IACX,kFAAkF;IAClF,4FAA4F;IAC5F,0BAA0B;IAC1B,6BAA6B,WAAW,CAAC,OAAO,GAAG;IACnD,UAAU;IACV,IAAI;IACJ,4GAA4G;IAC5G,QAAQ;IACR,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAgBb,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAA4B,EACd,EAAE,CAAC,CAAC;IAClB,KAAK,EAAE;QACL,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;QAC5D,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE;KAC7D;CACF,CAAC,CAAC;AAQH,uGAAuG;AACvG,MAAM,UAAU,KAAK,CAAC,CAAU,EAAE,OAAqB;IACrD,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAClC,OAAO;QACL,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;KACnC,CAAC;AACnB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAC1B,KAAmB,EACnB,MAAmB,EACnB,OAAyC;IAEzC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC;QACnD,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;QACpD,SAAS,EAAE,YAAY;QACvB,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KACjC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"invocation.js","sourceRoot":"","sources":["../../../src/adapters/banal/invocation.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEhD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAKpC,oGAAoG;AACpG,MAAM,SAAS,GAAG,qBAAqB,CAAC;AACxC,MAAM,UAAU,GAAG,CAAC,CAAS,EAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEnE,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAAC,CAAS;IACrC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC,CAAC;IAC9E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,mGAAmG;AACnG,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAY,EAAE,CAC7C,aAAa,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAEjD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW;IACX,kFAAkF;IAClF,4FAA4F;IAC5F,0BAA0B;IAC1B,6BAA6B,WAAW,CAAC,OAAO,GAAG;IACnD,UAAU;IACV,IAAI;IACJ,4GAA4G;IAC5G,QAAQ;IACR,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAgBb,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAA4B,EACd,EAAE,CAAC,CAAC;IAClB,KAAK,EAAE;QACL,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;QAC5D,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE;KAC7D;CACF,CAAC,CAAC;AAEH,wFAAwF;AACxF,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AASrC,uGAAuG;AACvG,MAAM,UAAU,KAAK,CAAC,CAAU,EAAE,OAAqB;IACrD,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAClC,OAAO;QACL,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;QACjD,CAAC,MAAM,CAAC,EAAE,IAAI;KACf,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAC1B,KAAmC,EACnC,MAAmB,EACnB,OAAyC;IAEzC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC;QACnD,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;QACpD,SAAS,EAAE,YAAY;QACvB,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KACjC,CAAC;AACJ,CAAC"}
@@ -1,5 +1,9 @@
1
- import type { Opaque } from "ts-essentials";
2
- import type { AbsolutePath } from "../../domain/paths.ts";
1
+ /**
2
+ * Where a banal may be, in order; which one is there; and which rule found it. The order:
3
+ * `$BANAL` (an explicit choice — if it names nothing, there is NO fallback), `<project>/vendor/banal`
4
+ * (a project that vendors its own copy), then the one `paperlint toolchain` installed.
5
+ */
6
+ import { type AbsolutePath } from "../../domain/paths.ts";
3
7
  import { type Result } from "../../domain/result.ts";
4
8
  import type { BanalSettings } from "./settings.ts";
5
9
  export type Provenance = {
@@ -13,13 +17,11 @@ export interface BanalCandidate {
13
17
  readonly path: AbsolutePath;
14
18
  readonly provenance: Provenance;
15
19
  }
16
- /** A candidate the `Files` port confirmed is a file. Minted by `pickBanal` only. */
17
- export type LocatedBanal = Opaque<BanalCandidate, "LocatedBanal">;
18
- /**
19
- * `paperlint toolchain`'s banal after its bytes hashed to the pin AND it measured the probe page. Minted by
20
- * `ensureBanal` / `checkBanal` only (`./index.ts`): a "ready" line cannot be printed without one.
21
- */
22
- export type PinnedBanal = Opaque<BanalCandidate, "PinnedBanal">;
20
+ declare const LOCATED: unique symbol;
21
+ /** A candidate the `Files` port confirmed is a file. Minted by `pickBanal` (through `locate`) only. */
22
+ export type LocatedBanal = BanalCandidate & {
23
+ readonly [LOCATED]: true;
24
+ };
23
25
  /** Why there is no banal to run. */
24
26
  export type BanalMissing =
25
27
  /** `$BANAL` names a file that is not there. An explicit choice: no fallback to another banal. */
@@ -47,4 +49,5 @@ export declare function lookupOrder(s: BanalSettings, projectRoot: AbsolutePath)
47
49
  export declare function pickBanal(order: LookupOrder, isFile: (p: AbsolutePath) => boolean): Result<LocatedBanal, BanalMissing>;
48
50
  /** Which rule found it, as a person reads it. */
49
51
  export declare const provenanceLabel: (p: Provenance) => string;
52
+ export {};
50
53
  //# sourceMappingURL=locate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/locate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAED,oFAAoF;AACpF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;AAEhE,oCAAoC;AACpC,MAAM,MAAM,YAAY;AACtB,iGAAiG;AAC/F;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChE,8FAA8F;GAC5F;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,iGAAiG;AACjG,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAC1D;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;CAC9B,CAAC;AAEN,0FAA0F;AAC1F,eAAO,MAAM,cAAc,GAAI,GAAG,aAAa,KAAG,YACwB,CAAC;AAE3E,wBAAgB,WAAW,CACzB,CAAC,EAAE,aAAa,EAChB,WAAW,EAAE,YAAY,GACxB,WAAW,CAOb;AAKD,wBAAgB,SAAS,CACvB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,OAAO,GACnC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAQpC;AAED,iDAAiD;AACjD,eAAO,MAAM,eAAe,GAAI,GAAG,UAAU,KAAG,MAG7C,CAAC"}
1
+ {"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../../src/adapters/banal/locate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAGD,QAAA,MAAM,OAAO,eAAyB,CAAC;AAEvC,uGAAuG;AACvG,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG;IAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAWzE,oCAAoC;AACpC,MAAM,MAAM,YAAY;AACtB,iGAAiG;AAC/F;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChE,8FAA8F;GAC5F;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,iGAAiG;AACjG,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAC1D;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;CAC9B,CAAC;AAEN,0FAA0F;AAC1F,eAAO,MAAM,cAAc,GAAI,GAAG,aAAa,KAAG,YACY,CAAC;AAE/D,wBAAgB,WAAW,CACzB,CAAC,EAAE,aAAa,EAChB,WAAW,EAAE,YAAY,GACxB,WAAW,CAOb;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,OAAO,GACnC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAapC;AAED,iDAAiD;AACjD,eAAO,MAAM,eAAe,GAAI,GAAG,UAAU,KAAG,MAG7C,CAAC"}