paperlint 2.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 (762) hide show
  1. package/.github/dependabot.yml +72 -0
  2. package/.github/workflows/ci.yml +297 -0
  3. package/.github/workflows/dependabot-automerge.yml +70 -0
  4. package/.github/workflows/pr-title.yml +59 -0
  5. package/.github/workflows/release.yml +54 -0
  6. package/CLAUDE.md +598 -0
  7. package/CONTRIBUTING.md +159 -0
  8. package/LICENSE +21 -0
  9. package/README.md +240 -0
  10. package/action.harness.mjs +287 -0
  11. package/action.mutations.mjs +162 -0
  12. package/action.yml +138 -0
  13. package/bin/rpp.mjs +43 -0
  14. package/dist/action-ref.d.ts +12 -0
  15. package/dist/action-ref.d.ts.map +1 -0
  16. package/dist/action-ref.js +16 -0
  17. package/dist/action-ref.js.map +1 -0
  18. package/dist/adapters/banal/failure.d.ts +73 -0
  19. package/dist/adapters/banal/failure.d.ts.map +1 -0
  20. package/dist/adapters/banal/failure.js +58 -0
  21. package/dist/adapters/banal/failure.js.map +1 -0
  22. package/dist/adapters/banal/index.d.ts +17 -0
  23. package/dist/adapters/banal/index.d.ts.map +1 -0
  24. package/dist/adapters/banal/index.js +56 -0
  25. package/dist/adapters/banal/index.js.map +1 -0
  26. package/dist/adapters/banal/install.d.ts +26 -0
  27. package/dist/adapters/banal/install.d.ts.map +1 -0
  28. package/dist/adapters/banal/install.js +15 -0
  29. package/dist/adapters/banal/install.js.map +1 -0
  30. package/dist/adapters/banal/invocation.d.ts +48 -0
  31. package/dist/adapters/banal/invocation.d.ts.map +1 -0
  32. package/dist/adapters/banal/invocation.js +43 -0
  33. package/dist/adapters/banal/invocation.js.map +1 -0
  34. package/dist/adapters/banal/locate.d.ts +50 -0
  35. package/dist/adapters/banal/locate.d.ts.map +1 -0
  36. package/dist/adapters/banal/locate.js +34 -0
  37. package/dist/adapters/banal/locate.js.map +1 -0
  38. package/dist/adapters/banal/output.d.ts +27 -0
  39. package/dist/adapters/banal/output.d.ts.map +1 -0
  40. package/dist/adapters/banal/output.js +112 -0
  41. package/dist/adapters/banal/output.js.map +1 -0
  42. package/dist/adapters/banal/pin.d.ts +19 -0
  43. package/dist/adapters/banal/pin.d.ts.map +1 -0
  44. package/dist/adapters/banal/pin.js +15 -0
  45. package/dist/adapters/banal/pin.js.map +1 -0
  46. package/dist/adapters/banal/probe.d.ts +12 -0
  47. package/dist/adapters/banal/probe.d.ts.map +1 -0
  48. package/dist/adapters/banal/probe.js +27 -0
  49. package/dist/adapters/banal/probe.js.map +1 -0
  50. package/dist/adapters/banal/run.d.ts +89 -0
  51. package/dist/adapters/banal/run.d.ts.map +1 -0
  52. package/dist/adapters/banal/run.js +104 -0
  53. package/dist/adapters/banal/run.js.map +1 -0
  54. package/dist/adapters/banal/settings.d.ts +18 -0
  55. package/dist/adapters/banal/settings.d.ts.map +1 -0
  56. package/dist/adapters/banal/settings.js +29 -0
  57. package/dist/adapters/banal/settings.js.map +1 -0
  58. package/dist/adapters/banal/xml.d.ts +48 -0
  59. package/dist/adapters/banal/xml.d.ts.map +1 -0
  60. package/dist/adapters/banal/xml.js +67 -0
  61. package/dist/adapters/banal/xml.js.map +1 -0
  62. package/dist/adapters/curl/download.io.d.ts +14 -0
  63. package/dist/adapters/curl/download.io.d.ts.map +1 -0
  64. package/dist/adapters/curl/download.io.js +69 -0
  65. package/dist/adapters/curl/download.io.js.map +1 -0
  66. package/dist/adapters/curl/index.d.ts +6 -0
  67. package/dist/adapters/curl/index.d.ts.map +1 -0
  68. package/dist/adapters/curl/index.js +6 -0
  69. package/dist/adapters/curl/index.js.map +1 -0
  70. package/dist/adapters/memory/index.d.ts +43 -0
  71. package/dist/adapters/memory/index.d.ts.map +1 -0
  72. package/dist/adapters/memory/index.js +79 -0
  73. package/dist/adapters/memory/index.js.map +1 -0
  74. package/dist/adapters/node/files.io.d.ts +3 -0
  75. package/dist/adapters/node/files.io.d.ts.map +1 -0
  76. package/dist/adapters/node/files.io.js +31 -0
  77. package/dist/adapters/node/files.io.js.map +1 -0
  78. package/dist/adapters/node/host.io.d.ts +3 -0
  79. package/dist/adapters/node/host.io.d.ts.map +1 -0
  80. package/dist/adapters/node/host.io.js +14 -0
  81. package/dist/adapters/node/host.io.js.map +1 -0
  82. package/dist/adapters/node/index.d.ts +25 -0
  83. package/dist/adapters/node/index.d.ts.map +1 -0
  84. package/dist/adapters/node/index.js +14 -0
  85. package/dist/adapters/node/index.js.map +1 -0
  86. package/dist/adapters/node/process.io.d.ts +14 -0
  87. package/dist/adapters/node/process.io.d.ts.map +1 -0
  88. package/dist/adapters/node/process.io.js +41 -0
  89. package/dist/adapters/node/process.io.js.map +1 -0
  90. package/dist/adapters/node/workspace.io.d.ts +4 -0
  91. package/dist/adapters/node/workspace.io.d.ts.map +1 -0
  92. package/dist/adapters/node/workspace.io.js +33 -0
  93. package/dist/adapters/node/workspace.io.js.map +1 -0
  94. package/dist/adapters/pdfjs/fill.d.ts +42 -0
  95. package/dist/adapters/pdfjs/fill.d.ts.map +1 -0
  96. package/dist/adapters/pdfjs/fill.js +91 -0
  97. package/dist/adapters/pdfjs/fill.js.map +1 -0
  98. package/dist/build-engine.d.ts +48 -0
  99. package/dist/build-engine.d.ts.map +1 -0
  100. package/dist/build-engine.js +148 -0
  101. package/dist/build-engine.js.map +1 -0
  102. package/dist/build.d.ts +163 -0
  103. package/dist/build.d.ts.map +1 -0
  104. package/dist/build.js +575 -0
  105. package/dist/build.js.map +1 -0
  106. package/dist/cli.d.ts +151 -0
  107. package/dist/cli.d.ts.map +1 -0
  108. package/dist/cli.js +951 -0
  109. package/dist/cli.js.map +1 -0
  110. package/dist/doctor.d.ts +42 -0
  111. package/dist/doctor.d.ts.map +1 -0
  112. package/dist/doctor.js +280 -0
  113. package/dist/doctor.js.map +1 -0
  114. package/dist/domain/geometry.d.ts +71 -0
  115. package/dist/domain/geometry.d.ts.map +1 -0
  116. package/dist/domain/geometry.js +35 -0
  117. package/dist/domain/geometry.js.map +1 -0
  118. package/dist/domain/host.d.ts +16 -0
  119. package/dist/domain/host.d.ts.map +1 -0
  120. package/dist/domain/host.js +8 -0
  121. package/dist/domain/host.js.map +1 -0
  122. package/dist/domain/page-layout.d.ts +34 -0
  123. package/dist/domain/page-layout.d.ts.map +1 -0
  124. package/dist/domain/page-layout.js +8 -0
  125. package/dist/domain/page-layout.js.map +1 -0
  126. package/dist/domain/paths.d.ts +5 -0
  127. package/dist/domain/paths.d.ts.map +1 -0
  128. package/dist/domain/paths.js +2 -0
  129. package/dist/domain/paths.js.map +1 -0
  130. package/dist/domain/result.d.ts +23 -0
  131. package/dist/domain/result.d.ts.map +1 -0
  132. package/dist/domain/result.js +10 -0
  133. package/dist/domain/result.js.map +1 -0
  134. package/dist/domain/sha256.d.ts +7 -0
  135. package/dist/domain/sha256.d.ts.map +1 -0
  136. package/dist/domain/sha256.js +14 -0
  137. package/dist/domain/sha256.js.map +1 -0
  138. package/dist/domain/text.d.ts +6 -0
  139. package/dist/domain/text.d.ts.map +1 -0
  140. package/dist/domain/text.js +7 -0
  141. package/dist/domain/text.js.map +1 -0
  142. package/dist/engine.d.ts +93 -0
  143. package/dist/engine.d.ts.map +1 -0
  144. package/dist/engine.js +119 -0
  145. package/dist/engine.js.map +1 -0
  146. package/dist/exit-code.d.ts +22 -0
  147. package/dist/exit-code.d.ts.map +1 -0
  148. package/dist/exit-code.js +10 -0
  149. package/dist/exit-code.js.map +1 -0
  150. package/dist/facts-file.d.ts +96 -0
  151. package/dist/facts-file.d.ts.map +1 -0
  152. package/dist/facts-file.js +134 -0
  153. package/dist/facts-file.js.map +1 -0
  154. package/dist/hooks-settings.d.ts +141 -0
  155. package/dist/hooks-settings.d.ts.map +1 -0
  156. package/dist/hooks-settings.js +306 -0
  157. package/dist/hooks-settings.js.map +1 -0
  158. package/dist/init.d.ts +201 -0
  159. package/dist/init.d.ts.map +1 -0
  160. package/dist/init.js +579 -0
  161. package/dist/init.js.map +1 -0
  162. package/dist/latex-log.d.ts +80 -0
  163. package/dist/latex-log.d.ts.map +1 -0
  164. package/dist/latex-log.js +187 -0
  165. package/dist/latex-log.js.map +1 -0
  166. package/dist/latex-loop.d.ts +129 -0
  167. package/dist/latex-loop.d.ts.map +1 -0
  168. package/dist/latex-loop.js +113 -0
  169. package/dist/latex-loop.js.map +1 -0
  170. package/dist/link-skills.d.ts +51 -0
  171. package/dist/link-skills.d.ts.map +1 -0
  172. package/dist/link-skills.js +199 -0
  173. package/dist/link-skills.js.map +1 -0
  174. package/dist/new-paper.d.ts +48 -0
  175. package/dist/new-paper.d.ts.map +1 -0
  176. package/dist/new-paper.js +110 -0
  177. package/dist/new-paper.js.map +1 -0
  178. package/dist/pdf-facts.d.ts +44 -0
  179. package/dist/pdf-facts.d.ts.map +1 -0
  180. package/dist/pdf-facts.js +239 -0
  181. package/dist/pdf-facts.js.map +1 -0
  182. package/dist/pdf-geometry.d.ts +170 -0
  183. package/dist/pdf-geometry.d.ts.map +1 -0
  184. package/dist/pdf-geometry.js +158 -0
  185. package/dist/pdf-geometry.js.map +1 -0
  186. package/dist/ports/download.d.ts +9 -0
  187. package/dist/ports/download.d.ts.map +1 -0
  188. package/dist/ports/download.js +2 -0
  189. package/dist/ports/download.js.map +1 -0
  190. package/dist/ports/files.d.ts +11 -0
  191. package/dist/ports/files.d.ts.map +1 -0
  192. package/dist/ports/files.js +2 -0
  193. package/dist/ports/files.js.map +1 -0
  194. package/dist/ports/measure-geometry.d.ts +8 -0
  195. package/dist/ports/measure-geometry.d.ts.map +1 -0
  196. package/dist/ports/measure-geometry.js +2 -0
  197. package/dist/ports/measure-geometry.js.map +1 -0
  198. package/dist/ports/process.d.ts +45 -0
  199. package/dist/ports/process.d.ts.map +1 -0
  200. package/dist/ports/process.js +2 -0
  201. package/dist/ports/process.js.map +1 -0
  202. package/dist/ports/tool-installer.d.ts +29 -0
  203. package/dist/ports/tool-installer.d.ts.map +1 -0
  204. package/dist/ports/tool-installer.js +2 -0
  205. package/dist/ports/tool-installer.js.map +1 -0
  206. package/dist/ports/workspace.d.ts +18 -0
  207. package/dist/ports/workspace.d.ts.map +1 -0
  208. package/dist/ports/workspace.js +2 -0
  209. package/dist/ports/workspace.js.map +1 -0
  210. package/dist/rules-config.d.ts +34 -0
  211. package/dist/rules-config.d.ts.map +1 -0
  212. package/dist/rules-config.js +132 -0
  213. package/dist/rules-config.js.map +1 -0
  214. package/dist/structure.d.ts +34 -0
  215. package/dist/structure.d.ts.map +1 -0
  216. package/dist/structure.js +149 -0
  217. package/dist/structure.js.map +1 -0
  218. package/dist/tex-requirements.d.ts +43 -0
  219. package/dist/tex-requirements.d.ts.map +1 -0
  220. package/dist/tex-requirements.js +127 -0
  221. package/dist/tex-requirements.js.map +1 -0
  222. package/dist/toolchain.d.ts +159 -0
  223. package/dist/toolchain.d.ts.map +1 -0
  224. package/dist/toolchain.js +542 -0
  225. package/dist/toolchain.js.map +1 -0
  226. package/dist/types.d.ts +110 -0
  227. package/dist/types.d.ts.map +1 -0
  228. package/dist/types.js +2 -0
  229. package/dist/types.js.map +1 -0
  230. package/docs/configuration.md +235 -0
  231. package/docs/e2e.md +152 -0
  232. package/docs/incidents.md +59 -0
  233. package/docs/install.md +170 -0
  234. package/docs/optional-rules.md +107 -0
  235. package/docs/package-shape-options.md +262 -0
  236. package/docs/prior-art/README.md +76 -0
  237. package/docs/prior-art/blocking-vs-advisory.md +83 -0
  238. package/docs/prior-art/content-delivery.md +124 -0
  239. package/docs/prior-art/multi-mode-tools.md +106 -0
  240. package/docs/prior-art/nondeterministic-checks.md +99 -0
  241. package/docs/prior-art/package-location.md +422 -0
  242. package/docs/prior-art/paper-folder-scaffolding.md +538 -0
  243. package/docs/prior-art/readme-structure.md +69 -0
  244. package/docs/prior-art/repro/README.md +92 -0
  245. package/docs/prior-art/repro/claim1-allowedtools.mjs +66 -0
  246. package/docs/prior-art/repro/claim1-at2.mjs +40 -0
  247. package/docs/prior-art/repro/claim1-crosschannel.mjs +54 -0
  248. package/docs/prior-art/repro/claim1-frontmatter.mjs +76 -0
  249. package/docs/prior-art/repro/claim1-hook-payload-reporter.mjs +10 -0
  250. package/docs/prior-art/repro/claim1-plugin-frontmatter.mjs +27 -0
  251. package/docs/prior-art/repro/claim1-plugin-skill.mjs +52 -0
  252. package/docs/prior-art/repro/claim1-project-skill.mjs +81 -0
  253. package/docs/prior-art/repro/claim2-marketplace-flat-asclaimed.json +1 -0
  254. package/docs/prior-art/repro/claim2-marketplace-negative-control.json +1 -0
  255. package/docs/prior-art/repro/claim2-marketplace-nested-exact.json +9 -0
  256. package/docs/prior-art/repro/claim2-marketplace-nested-noversion.json +9 -0
  257. package/docs/prior-art/repro/claim2-marketplace-nested-range.json +1 -0
  258. package/docs/prior-art/repro/claim3-imports.mjs +50 -0
  259. package/docs/prior-art/repro/claim4-find-package-json.mjs +8 -0
  260. package/docs/prior-art/repro/claim4-package-dir.mjs +39 -0
  261. package/docs/prior-art/repro/claim4-parent-arg.mjs +17 -0
  262. package/docs/prior-art/repro/claim4-resolve-apis.mjs +21 -0
  263. package/docs/prior-art/repro/claim4-setup-consumers.mjs +45 -0
  264. package/docs/prior-art/repro/claim4-yarn-pnp.mjs +70 -0
  265. package/docs/prior-art/repro/claim5-bin-launch.mjs +39 -0
  266. package/docs/prior-art/repro/claim5-exports-mutation.mjs +57 -0
  267. package/docs/prior-art/repro/claim5-resolved-location-and-bin.mjs +33 -0
  268. package/docs/prior-art/repro/claim6-candidate-ambiguity.mjs +17 -0
  269. package/docs/prior-art/repro/claim6-doc-path-candidates.mjs +27 -0
  270. package/docs/prior-art/test-tooling.md +131 -0
  271. package/docs/rules.md +58 -0
  272. package/docs/texlive-install-decision.md +230 -0
  273. package/docs/toolchain.md +152 -0
  274. package/eslint-rules/doc-fields.harness.mjs +336 -0
  275. package/eslint-rules/doc-fields.mjs +186 -0
  276. package/eslint-rules/doc-fields.mutations.mjs +96 -0
  277. package/eslint-rules/install-path-literals.harness.mjs +121 -0
  278. package/eslint-rules/install-path-literals.mjs +108 -0
  279. package/eslint-rules/install-path-literals.mutations.mjs +62 -0
  280. package/eslint-rules/latex-language.harness.mjs +599 -0
  281. package/eslint-rules/latex-language.mjs +591 -0
  282. package/eslint-rules/latex-language.mutations.mjs +196 -0
  283. package/eslint-rules/paper-research-question.harness.mjs +146 -0
  284. package/eslint-rules/paper-research-question.mjs +180 -0
  285. package/eslint-rules/paper-research-question.mutations.mjs +127 -0
  286. package/eslint-rules/paper-stages.harness.mjs +356 -0
  287. package/eslint-rules/paper-stages.mjs +455 -0
  288. package/eslint-rules/paper-stages.mutations.mjs +157 -0
  289. package/eslint-rules/paper-typography.harness.mjs +291 -0
  290. package/eslint-rules/paper-typography.mjs +313 -0
  291. package/eslint-rules/paper-typography.mutations.mjs +131 -0
  292. package/eslint-rules/papers.harness.mjs +259 -0
  293. package/eslint-rules/papers.mjs +166 -0
  294. package/eslint-rules/papers.mutations.mjs +186 -0
  295. package/eslint-rules/pdf-last-page-balance.harness.mjs +206 -0
  296. package/eslint-rules/pdf-last-page-balance.mjs +208 -0
  297. package/eslint-rules/review-findings-cause.harness.mjs +228 -0
  298. package/eslint-rules/review-findings-cause.mjs +135 -0
  299. package/eslint-rules/review-findings-cause.mutations.mjs +72 -0
  300. package/eslint-rules/temp-root-realpath.harness.mjs +176 -0
  301. package/eslint-rules/temp-root-realpath.mjs +129 -0
  302. package/eslint-rules/temp-root-realpath.mutations.mjs +99 -0
  303. package/eslint-rules/tex-build.harness.mjs +753 -0
  304. package/eslint-rules/tex-build.mjs +322 -0
  305. package/eslint-rules/tex-build.mutations.mjs +258 -0
  306. package/eslint.config.mjs +521 -0
  307. package/fixtures/build-e2e/acmart/PIPELINE-STATUS.md +3 -0
  308. package/fixtures/build-e2e/acmart/paper.tex +11 -0
  309. package/fixtures/build-e2e/acmart/venue.json +1 -0
  310. package/fixtures/build-e2e/broken/PIPELINE-STATUS.md +3 -0
  311. package/fixtures/build-e2e/broken/paper.tex +7 -0
  312. package/fixtures/build-e2e/cite/PIPELINE-STATUS.md +3 -0
  313. package/fixtures/build-e2e/cite/build.sh +5 -0
  314. package/fixtures/build-e2e/cite/paper.tex +10 -0
  315. package/fixtures/build-e2e/cite/refs.bib +9 -0
  316. package/fixtures/build-e2e/empty/PIPELINE-STATUS.md +3 -0
  317. package/fixtures/build-e2e/empty/paper.tex +6 -0
  318. package/fixtures/build-e2e/fallback/PIPELINE-STATUS.md +3 -0
  319. package/fixtures/build-e2e/fallback/paper.tex +11 -0
  320. package/fixtures/build-e2e/guards/PIPELINE-STATUS.md +3 -0
  321. package/fixtures/build-e2e/guards/paper.tex +10 -0
  322. package/fixtures/build-e2e/no-source/PIPELINE-STATUS.md +3 -0
  323. package/fixtures/build-e2e/unbalanced/PIPELINE-STATUS.md +3 -0
  324. package/fixtures/build-e2e/unbalanced/paper.tex +28 -0
  325. package/fixtures/build-e2e/unbalanced/refs.bib +269 -0
  326. package/fixtures/install-path-literals/clean.fixture.mjs +3 -0
  327. package/fixtures/install-path-literals/clean.md +15 -0
  328. package/fixtures/install-path-literals/defect.fixture.mjs +3 -0
  329. package/fixtures/install-path-literals/defect.md +14 -0
  330. package/fixtures/latex-language/clean.tex +50 -0
  331. package/fixtures/latex-language/defect.tex +52 -0
  332. package/fixtures/paper-research-question/comment-only/PIPELINE-STATUS.md +9 -0
  333. package/fixtures/paper-research-question/comment-only/paper.tex +7 -0
  334. package/fixtures/paper-research-question/declared-not-in-paper/PIPELINE-STATUS.md +10 -0
  335. package/fixtures/paper-research-question/declared-not-in-paper/paper.tex +6 -0
  336. package/fixtures/paper-research-question/draft/PIPELINE-STATUS.md +6 -0
  337. package/fixtures/paper-research-question/draft/paper.tex +2 -0
  338. package/fixtures/paper-research-question/markdown-no-rq/PIPELINE-STATUS.md +9 -0
  339. package/fixtures/paper-research-question/markdown-no-rq/paper.md +4 -0
  340. package/fixtures/paper-research-question/shipped-no-rq/PIPELINE-STATUS.md +12 -0
  341. package/fixtures/paper-research-question/shipped-no-rq/paper.tex +3 -0
  342. package/fixtures/paper-research-question/shipped-with-rq/PIPELINE-STATUS.md +10 -0
  343. package/fixtures/paper-research-question/shipped-with-rq/paper.tex +2 -0
  344. package/fixtures/paper-stages/authors-ran/PIPELINE-STATUS.md +16 -0
  345. package/fixtures/paper-stages/marker-in-prose/PIPELINE-STATUS.md +17 -0
  346. package/fixtures/paper-stages/nofile/PIPELINE-STATUS.md +8 -0
  347. package/fixtures/paper-stages/noheader/PIPELINE-STATUS.md +1 -0
  348. package/fixtures/paper-stages/noheader/versions/2026-07-22-submitted.pdf +0 -0
  349. package/fixtures/paper-stages/nothing/PIPELINE-STATUS.md +3 -0
  350. package/fixtures/paper-stages/ok/PIPELINE-STATUS.md +9 -0
  351. package/fixtures/paper-stages/ok/versions/2026-07-22-submitted.pdf +0 -0
  352. package/fixtures/paper-stages/stale/PIPELINE-STATUS.md +1 -0
  353. package/fixtures/paper-stages/stale/versions/2026-07-22-submitted.STALE-WRONG-FILE.pdf +0 -0
  354. package/fixtures/paper-stages/twice/PIPELINE-STATUS.md +14 -0
  355. package/fixtures/paper-stages/twice/versions/2026-08-06-submitted.pdf +0 -0
  356. package/fixtures/paper-stages/twice/versions/2026-10-24-submitted.pdf +0 -0
  357. package/fixtures/paper-stages/undeclared/PIPELINE-STATUS.md +8 -0
  358. package/fixtures/paper-stages/undeclared/versions/2026-07-22-submitted.pdf +0 -0
  359. package/fixtures/paper-stages/undeclared/versions/2026-08-29-camera-ready.pdf +0 -0
  360. package/fixtures/paper-stages/wrongsize/PIPELINE-STATUS.md +8 -0
  361. package/fixtures/paper-stages/wrongsize/versions/2026-07-22-submitted.pdf +0 -0
  362. package/fixtures/paper-typography/clean-paper/paper.tex +29 -0
  363. package/fixtures/paper-typography/messy-paper/paper.tex +27 -0
  364. package/fixtures/pdf-facts/README.md +22 -0
  365. package/fixtures/pdf-facts/corrupt-font.pdf +0 -0
  366. package/fixtures/pdf-facts/encrypted.pdf +0 -0
  367. package/fixtures/pdf-facts/hidden-text.pdf +0 -0
  368. package/fixtures/pdf-facts/hidden-text.tex +28 -0
  369. package/fixtures/pdf-facts/t3-all.pdf +0 -0
  370. package/fixtures/pdf-facts/t3-all.tex +8 -0
  371. package/fixtures/pdf-facts/t3-mixed.pdf +0 -0
  372. package/fixtures/pdf-facts/t3-mixed.tex +9 -0
  373. package/fixtures/pdf-facts/ttf.pdf +2240 -1
  374. package/fixtures/pdf-facts/ttf.tex +6 -0
  375. package/fixtures/real-markdown-paper/baseline.json +24 -0
  376. package/fixtures/real-markdown-paper/baseline.mjs +48 -0
  377. package/fixtures/render-paper/build-clean.sh +25 -0
  378. package/fixtures/render-paper/build-defect.sh +15 -0
  379. package/fixtures/review-findings-cause/clean.md +17 -0
  380. package/fixtures/review-findings-cause/defect.md +14 -0
  381. package/fixtures/review-findings-cause/old-debt.md +14 -0
  382. package/fixtures/review-findings-cause/quiet-in-fence.md +16 -0
  383. package/fixtures/tex-build/clean.tex +21 -0
  384. package/fixtures/tex-build/defect.tex +24 -0
  385. package/fixtures/tex-build/frontmatter-clean.tex +25 -0
  386. package/fixtures/tex-build/frontmatter-defect.tex +23 -0
  387. package/fixtures/toolchain-mirror/catalog.txt +5 -0
  388. package/fixtures/toolchain-mirror/install-tl +27 -0
  389. package/fixtures/toolchain-mirror/release-texlive.txt +3 -0
  390. package/fixtures/toolchain-mirror/release-year +1 -0
  391. package/fixtures/toolchain-mirror/stub-kpsewhich +8 -0
  392. package/fixtures/toolchain-mirror/stub-pdflatex +3 -0
  393. package/fixtures/toolchain-mirror/stub-tlmgr +44 -0
  394. package/hooks/hooks.harness.mjs +713 -0
  395. package/hooks/hooks.mutations.mjs +337 -0
  396. package/hooks/paper-edit-guard.hook.d.mts +13 -0
  397. package/hooks/paper-edit-guard.hook.mjs +457 -0
  398. package/hooks/paper-skills-nudge.hook.mjs +136 -0
  399. package/hooks/paper-status-gates.hook.mjs +156 -0
  400. package/hooks/paper-status-gates.sh +91 -0
  401. package/lib/agent-cli-version.harness.mjs +165 -0
  402. package/lib/agent-cli-version.mjs +106 -0
  403. package/lib/agent-cli-version.mutations.mjs +109 -0
  404. package/lib/markdown.mjs +386 -0
  405. package/lib/mutation-driver.harness.mjs +227 -0
  406. package/lib/mutation-driver.mjs +397 -0
  407. package/lib/mutation-driver.mutations.mjs +68 -0
  408. package/lib/paper-config.d.mts +34 -0
  409. package/lib/paper-config.harness.mjs +286 -0
  410. package/lib/paper-config.mjs +142 -0
  411. package/lib/paper-config.mutations.mjs +143 -0
  412. package/lib/skill-checks.mjs +701 -0
  413. package/lib/skill-corpus.mjs +403 -0
  414. package/lib/skill-eval-fixture.mjs +63 -0
  415. package/lib/skill-eval-kit.mjs +257 -0
  416. package/lib/skill-trigger-cases.harness.mjs +170 -0
  417. package/lib/skill-trigger-cases.mjs +446 -0
  418. package/lib/skill-trigger-cases.mutations.mjs +65 -0
  419. package/lib/trigger-ledger.mjs +215 -0
  420. package/package.json +97 -0
  421. package/plugin/.claude-plugin/plugin.json +8 -0
  422. package/plugin/hooks/hooks.json +30 -0
  423. package/scripts/check.harness.mjs +177 -0
  424. package/scripts/check.mjs +239 -0
  425. package/scripts/check.mutations.mjs +110 -0
  426. package/scripts/eslint-report-guard.mjs +82 -0
  427. package/scripts/exclusive.mjs +138 -0
  428. package/scripts/harness-api.frozen.json +76 -0
  429. package/scripts/harness-api.test.ts +175 -0
  430. package/scripts/layer-legacy-frozen.d.mts +28 -0
  431. package/scripts/layer-legacy-frozen.mjs +152 -0
  432. package/scripts/layer-legacy-frozen.test.ts +115 -0
  433. package/scripts/layer-legacy.frozen.json +50 -0
  434. package/scripts/mutation-batteries-frozen.harness.mjs +204 -0
  435. package/scripts/mutation-batteries-frozen.mjs +238 -0
  436. package/scripts/mutation-batteries.frozen.json +117 -0
  437. package/scripts/release-config.test.ts +90 -0
  438. package/scripts/rules-are-content-only.harness.mjs +113 -0
  439. package/scripts/rules-are-content-only.mjs +138 -0
  440. package/scripts/rules-are-content-only.mutations.mjs +81 -0
  441. package/scripts/rules-see-files.harness.mjs +115 -0
  442. package/scripts/rules-see-files.mjs +99 -0
  443. package/scripts/rules-see-files.mutations.mjs +131 -0
  444. package/scripts/run-mutations.mjs +100 -0
  445. package/scripts/semantic-release-plugins.d.ts +16 -0
  446. package/skills/README.md +15 -0
  447. package/skills/analyze-sibling-paper/SKILL.md +170 -0
  448. package/skills/analyze-sibling-paper/SKILL.md.spec.ts +186 -0
  449. package/skills/analyze-sibling-paper/analyze-sibling-paper.eval.mjs +19 -0
  450. package/skills/analyze-sibling-paper/analyze-sibling-paper.harness.mjs +23 -0
  451. package/skills/argument-arc/SKILL.md +177 -0
  452. package/skills/argument-arc/SKILL.md.spec.ts +192 -0
  453. package/skills/argument-arc/argument-arc.eval.mjs +19 -0
  454. package/skills/argument-arc/argument-arc.harness.mjs +23 -0
  455. package/skills/build-benchmark/SKILL.md +213 -0
  456. package/skills/build-benchmark/SKILL.md.spec.ts +220 -0
  457. package/skills/build-benchmark/build-benchmark.eval.mjs +19 -0
  458. package/skills/build-benchmark/build-benchmark.harness.mjs +23 -0
  459. package/skills/build-benchmark/references/adversarial-cold-repro.md +68 -0
  460. package/skills/camera-ready/SKILL.md +148 -0
  461. package/skills/camera-ready/SKILL.md.spec.ts +164 -0
  462. package/skills/camera-ready/camera-ready.eval.mjs +19 -0
  463. package/skills/camera-ready/camera-ready.harness.mjs +23 -0
  464. package/skills/cold-read-diff/SKILL.md +160 -0
  465. package/skills/cold-read-diff/SKILL.md.spec.ts +166 -0
  466. package/skills/cold-read-diff/cold-read-diff.eval.mjs +19 -0
  467. package/skills/cold-read-diff/cold-read-diff.harness.mjs +23 -0
  468. package/skills/draft-paper/SKILL.md +152 -0
  469. package/skills/draft-paper/SKILL.md.spec.ts +169 -0
  470. package/skills/draft-paper/draft-paper.eval.mjs +19 -0
  471. package/skills/draft-paper/draft-paper.harness.mjs +23 -0
  472. package/skills/extend-paper/SKILL.md +99 -0
  473. package/skills/extend-paper/SKILL.md.spec.ts +116 -0
  474. package/skills/extend-paper/extend-paper.eval.mjs +19 -0
  475. package/skills/extend-paper/extend-paper.harness.mjs +23 -0
  476. package/skills/find-venue/SKILL.md +128 -0
  477. package/skills/find-venue/SKILL.md.spec.ts +145 -0
  478. package/skills/find-venue/find-venue.eval.mjs +19 -0
  479. package/skills/find-venue/find-venue.harness.mjs +23 -0
  480. package/skills/grade-paper-writing/SKILL.md +436 -0
  481. package/skills/grade-paper-writing/SKILL.md.spec.ts +453 -0
  482. package/skills/grade-paper-writing/fixtures/control_gopen.txt +1 -0
  483. package/skills/grade-paper-writing/fixtures/control_human_paper.txt +1 -0
  484. package/skills/grade-paper-writing/fixtures/rewrite.txt +1 -0
  485. package/skills/grade-paper-writing/fixtures/specimen.txt +1 -0
  486. package/skills/grade-paper-writing/fixtures/structure-checks.md +22 -0
  487. package/skills/grade-paper-writing/grade-paper-writing.eval.mjs +19 -0
  488. package/skills/grade-paper-writing/grade-paper-writing.harness.mjs +23 -0
  489. package/skills/grade-paper-writing/prose-lint.mjs +713 -0
  490. package/skills/harden-paper/SKILL.md +318 -0
  491. package/skills/harden-paper/SKILL.md.spec.ts +336 -0
  492. package/skills/harden-paper/check-numbers.sh +33 -0
  493. package/skills/harden-paper/check-release-claims.sh +35 -0
  494. package/skills/harden-paper/fixtures/uncited-assertions-sample.md +43 -0
  495. package/skills/harden-paper/fixtures/uncited-assertions-sample.tex +77 -0
  496. package/skills/harden-paper/harden-paper.eval.mjs +19 -0
  497. package/skills/harden-paper/harden-paper.harness.mjs +23 -0
  498. package/skills/map-prior-work/SKILL.md +211 -0
  499. package/skills/map-prior-work/SKILL.md.spec.ts +227 -0
  500. package/skills/map-prior-work/map-prior-work.eval.mjs +19 -0
  501. package/skills/map-prior-work/map-prior-work.harness.mjs +23 -0
  502. package/skills/osf-artifact-upload/SKILL.md +52 -0
  503. package/skills/osf-artifact-upload/SKILL.md.spec.ts +59 -0
  504. package/skills/osf-artifact-upload/osf-artifact-upload.eval.mjs +22 -0
  505. package/skills/osf-artifact-upload/osf-artifact-upload.harness.mjs +103 -0
  506. package/skills/paper-adversarial-review/SKILL.md +126 -0
  507. package/skills/paper-adversarial-review/SKILL.md.spec.ts +142 -0
  508. package/skills/paper-adversarial-review/paper-adversarial-review.eval.mjs +19 -0
  509. package/skills/paper-adversarial-review/paper-adversarial-review.harness.mjs +23 -0
  510. package/skills/paper-pipeline/PIPELINE-MAP.md +371 -0
  511. package/skills/paper-pipeline/SKILL.md +499 -0
  512. package/skills/paper-pipeline/SKILL.md.spec.ts +517 -0
  513. package/skills/paper-pipeline/description-language.eval.mjs +347 -0
  514. package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +891 -0
  515. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1254 -0
  516. package/skills/paper-pipeline/paper-pipeline.eval.mjs +22 -0
  517. package/skills/paper-pipeline/paper-pipeline.harness.mjs +143 -0
  518. package/skills/paper-pipeline/pipeline-firing.baseline.json +270 -0
  519. package/skills/paper-pipeline/pipeline-firing.eval.mjs +664 -0
  520. package/skills/paper-pipeline/pipeline-language.eval.mjs +672 -0
  521. package/skills/paper-pipeline/references/acceptance-gate.md +329 -0
  522. package/skills/paper-pipeline/references/acl-venue-rules.md +142 -0
  523. package/skills/paper-pipeline/references/anonymization.md +68 -0
  524. package/skills/paper-pipeline/references/artifact-checklist.md +93 -0
  525. package/skills/paper-pipeline/references/body-vs-appendix.md +97 -0
  526. package/skills/paper-pipeline/references/credit-criteria.md +69 -0
  527. package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/README.md +35 -0
  528. package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/run_retext.mjs +24 -0
  529. package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/sentences.txt +11 -0
  530. package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/test_sentences.py +25 -0
  531. package/skills/paper-pipeline/references/occupancy-2026-08-06-prose-checkers.md +538 -0
  532. package/skills/paper-pipeline/references/occupancy-2026-08-06-reproducible-tooling.md +431 -0
  533. package/skills/paper-pipeline/references/occupancy-2026-08-06-staleness-and-orchestration.md +592 -0
  534. package/skills/paper-pipeline/references/pipeline-status-template.md +162 -0
  535. package/skills/paper-pipeline/references/review-ratchet.md +36 -0
  536. package/skills/paper-pipeline/references/sweep-2026-08-09-ideal-pipeline.md +585 -0
  537. package/skills/paper-pipeline/references/writing-craft.md +448 -0
  538. package/skills/paper-pipeline/repro/2026-08-07-description-language-control.log +63 -0
  539. package/skills/paper-pipeline/repro/2026-08-07-fork-check.log +52 -0
  540. package/skills/paper-pipeline/repro/2026-08-07-fork-check2.log +33 -0
  541. package/skills/paper-pipeline/repro/2026-08-07-language-eval-pilot.log +33 -0
  542. package/skills/paper-pipeline/repro/2026-08-07-language-eval-raw.log +166 -0
  543. package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-oracle.json +338 -0
  544. package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-oracle.log +118 -0
  545. package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-raw.log +245 -0
  546. package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary.json +776 -0
  547. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-A6-oracle.log +53 -0
  548. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-A6-raw.log +89 -0
  549. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-oracle.json +450 -0
  550. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-oracle.log +136 -0
  551. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-raw.log +242 -0
  552. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-setupdiff.log +59 -0
  553. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation.json +1032 -0
  554. package/skills/paper-pipeline/repro/2026-08-08-parent-replication-gpw.json +139 -0
  555. package/skills/paper-pipeline/repro/2026-08-08-parent-replication-gpw.log +98 -0
  556. package/skills/paper-pipeline/repro/2026-08-08-parent-replication.mjs +92 -0
  557. package/skills/paper-pipeline/repro/README.md +129 -0
  558. package/skills/paper-pipeline/repro/analyze-language-eval.py +116 -0
  559. package/skills/paper-pipeline/scripts/README.md +344 -0
  560. package/skills/paper-pipeline/scripts/announce.mjs +67 -0
  561. package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +496 -0
  562. package/skills/paper-pipeline/scripts/artifact-coverage.mjs +397 -0
  563. package/skills/paper-pipeline/scripts/artifact-coverage.mutations.mjs +218 -0
  564. package/skills/paper-pipeline/scripts/check-provenance.mjs +184 -0
  565. package/skills/paper-pipeline/scripts/consumer.d.mts +32 -0
  566. package/skills/paper-pipeline/scripts/consumer.harness.mjs +562 -0
  567. package/skills/paper-pipeline/scripts/consumer.mjs +535 -0
  568. package/skills/paper-pipeline/scripts/consumer.mutations.mjs +190 -0
  569. package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +457 -0
  570. package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +656 -0
  571. package/skills/paper-pipeline/scripts/extract-ref-facts.mutations.mjs +54 -0
  572. package/skills/paper-pipeline/scripts/fixtures/clean/PIPELINE-STATUS.md +51 -0
  573. package/skills/paper-pipeline/scripts/fixtures/dirty/PIPELINE-STATUS.md +52 -0
  574. package/skills/paper-pipeline/scripts/fixtures/dirty/paper.md +6 -0
  575. package/skills/paper-pipeline/scripts/fixtures/real-bib/refs.bib +153 -0
  576. package/skills/paper-pipeline/scripts/generated-code.harness.mjs +466 -0
  577. package/skills/paper-pipeline/scripts/generated-code.mjs +338 -0
  578. package/skills/paper-pipeline/scripts/generated-code.mutations.mjs +254 -0
  579. package/skills/paper-pipeline/scripts/ledger.mjs +623 -0
  580. package/skills/paper-pipeline/scripts/ledger.selftest.mjs +286 -0
  581. package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +389 -0
  582. package/skills/paper-pipeline/scripts/pipeline-check.mjs +737 -0
  583. package/skills/paper-pipeline/scripts/pipeline-check.mutations.mjs +54 -0
  584. package/skills/paper-pipeline/scripts/pipeline-edges.mjs +169 -0
  585. package/skills/paper-pipeline/scripts/population-map.harness.mjs +178 -0
  586. package/skills/paper-pipeline/scripts/population-map.mjs +181 -0
  587. package/skills/paper-pipeline/scripts/population-map.mutations.mjs +65 -0
  588. package/skills/paper-pipeline/scripts/population-map.selftest.mjs +122 -0
  589. package/skills/paper-pipeline/scripts/provenance.harness.mjs +240 -0
  590. package/skills/paper-pipeline/scripts/provenance.mutations.mjs +59 -0
  591. package/skills/paper-pipeline/scripts/round-diff.harness.mjs +881 -0
  592. package/skills/paper-pipeline/scripts/round-diff.mjs +576 -0
  593. package/skills/paper-pipeline/scripts/round-diff.mutations.mjs +276 -0
  594. package/skills/paper-pipeline/scripts/run-mechanical.mjs +633 -0
  595. package/skills/paper-pipeline/scripts/status.mjs +295 -0
  596. package/skills/paper-status/SKILL.md +183 -0
  597. package/skills/paper-status/SKILL.md.spec.ts +190 -0
  598. package/skills/paper-status/paper-status.eval.mjs +22 -0
  599. package/skills/paper-status/paper-status.harness.mjs +25 -0
  600. package/skills/pc-panel-review/SKILL.md +263 -0
  601. package/skills/pc-panel-review/SKILL.md.spec.ts +280 -0
  602. package/skills/pc-panel-review/pc-panel-review.eval.mjs +19 -0
  603. package/skills/pc-panel-review/pc-panel-review.harness.mjs +23 -0
  604. package/skills/plan-paper-timeline/SKILL.md +182 -0
  605. package/skills/plan-paper-timeline/SKILL.md.spec.ts +200 -0
  606. package/skills/plan-paper-timeline/fixtures/fake-google-calendar.mjs +239 -0
  607. package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +431 -0
  608. package/skills/plan-paper-timeline/plan-paper-timeline.effects.mutations.mjs +65 -0
  609. package/skills/plan-paper-timeline/plan-paper-timeline.eval.mjs +19 -0
  610. package/skills/plan-paper-timeline/plan-paper-timeline.harness.mjs +23 -0
  611. package/skills/render-paper/SKILL.md +159 -0
  612. package/skills/render-paper/SKILL.md.spec.ts +166 -0
  613. package/skills/render-paper/check-render.sh +419 -0
  614. package/skills/render-paper/checkers-requirements.txt +55 -0
  615. package/skills/render-paper/ensure-checkers.sh +69 -0
  616. package/skills/render-paper/extract-pdf-facts.harness.mjs +166 -0
  617. package/skills/render-paper/extract-pdf-facts.mjs +144 -0
  618. package/skills/render-paper/render-paper.eval.mjs +19 -0
  619. package/skills/render-paper/render-paper.harness.mjs +339 -0
  620. package/skills/research-ideate/SKILL.md +136 -0
  621. package/skills/research-ideate/SKILL.md.spec.ts +152 -0
  622. package/skills/research-ideate/research-ideate.eval.mjs +19 -0
  623. package/skills/research-ideate/research-ideate.harness.mjs +23 -0
  624. package/skills/skill-contract.mutations.mjs +179 -0
  625. package/skills/study-accepted-papers/SKILL.md +206 -0
  626. package/skills/study-accepted-papers/SKILL.md.spec.ts +223 -0
  627. package/skills/study-accepted-papers/study-accepted-papers.eval.mjs +19 -0
  628. package/skills/study-accepted-papers/study-accepted-papers.harness.mjs +23 -0
  629. package/skills/submit-paper/SKILL.md +182 -0
  630. package/skills/submit-paper/SKILL.md.spec.ts +199 -0
  631. package/skills/submit-paper/check-deanon.sh +149 -0
  632. package/skills/submit-paper/references/publishers/acm.md +92 -0
  633. package/skills/submit-paper/references/venues/agenticdev.jsonc +108 -0
  634. package/skills/submit-paper/references/venues/agenticdev.md +139 -0
  635. package/skills/submit-paper/references/venues/agenticdev.tex +19 -0
  636. package/skills/submit-paper/references/venues/aisec.jsonc +101 -0
  637. package/skills/submit-paper/references/venues/aisec.md +105 -0
  638. package/skills/submit-paper/references/venues/paper-guards.tex +41 -0
  639. package/skills/submit-paper/references/venues/realm.jsonc +81 -0
  640. package/skills/submit-paper/references/venues/realm.md +155 -0
  641. package/skills/submit-paper/references/venues/tex-base.jsonc +50 -0
  642. package/skills/submit-paper/references/venues/venue-profile.schema.json +74 -0
  643. package/skills/submit-paper/submit-paper.eval.mjs +19 -0
  644. package/skills/submit-paper/submit-paper.harness.mjs +23 -0
  645. package/skills/sweep-design-space/SKILL.md +269 -0
  646. package/skills/sweep-design-space/SKILL.md.spec.ts +285 -0
  647. package/skills/sweep-design-space/sweep-design-space.eval.mjs +19 -0
  648. package/skills/sweep-design-space/sweep-design-space.harness.mjs +23 -0
  649. package/skills/tighten-paper/SKILL.md +368 -0
  650. package/skills/tighten-paper/SKILL.md.spec.ts +384 -0
  651. package/skills/tighten-paper/structure.mjs +371 -0
  652. package/skills/tighten-paper/tighten-paper.eval.mjs +19 -0
  653. package/skills/tighten-paper/tighten-paper.harness.mjs +23 -0
  654. package/skills/verify-citations/SKILL.md +328 -0
  655. package/skills/verify-citations/SKILL.md.spec.ts +345 -0
  656. package/skills/verify-citations/scripts/bib-authors.mjs +479 -0
  657. package/skills/verify-citations/scripts/bib-authors.test.mjs +175 -0
  658. package/skills/verify-citations/scripts/verify-cites.mjs +1108 -0
  659. package/skills/verify-citations/scripts/verify-cites.test.mjs +735 -0
  660. package/skills/verify-citations/verify-citations.eval.mjs +19 -0
  661. package/skills/verify-citations/verify-citations.harness.mjs +23 -0
  662. package/src/CLAUDE.md +51 -0
  663. package/src/action-ref.test.ts +26 -0
  664. package/src/action-ref.ts +15 -0
  665. package/src/adapters/banal/failure.test.ts +63 -0
  666. package/src/adapters/banal/failure.ts +118 -0
  667. package/src/adapters/banal/index.test.ts +119 -0
  668. package/src/adapters/banal/index.ts +100 -0
  669. package/src/adapters/banal/install.test.ts +20 -0
  670. package/src/adapters/banal/install.ts +41 -0
  671. package/src/adapters/banal/invocation.test.ts +74 -0
  672. package/src/adapters/banal/invocation.ts +95 -0
  673. package/src/adapters/banal/locate.test.ts +52 -0
  674. package/src/adapters/banal/locate.ts +84 -0
  675. package/src/adapters/banal/output.test.ts +140 -0
  676. package/src/adapters/banal/output.ts +141 -0
  677. package/src/adapters/banal/pin.ts +30 -0
  678. package/src/adapters/banal/probe.ts +35 -0
  679. package/src/adapters/banal/run.test.ts +191 -0
  680. package/src/adapters/banal/run.ts +244 -0
  681. package/src/adapters/banal/settings.test.ts +31 -0
  682. package/src/adapters/banal/settings.ts +55 -0
  683. package/src/adapters/banal/xml.test.ts +111 -0
  684. package/src/adapters/banal/xml.ts +112 -0
  685. package/src/adapters/curl/download.io.ts +73 -0
  686. package/src/adapters/curl/download.test.ts +55 -0
  687. package/src/adapters/curl/index.ts +5 -0
  688. package/src/adapters/memory/index.ts +131 -0
  689. package/src/adapters/node/files.io.ts +39 -0
  690. package/src/adapters/node/files.test.ts +28 -0
  691. package/src/adapters/node/host.io.ts +15 -0
  692. package/src/adapters/node/index.ts +36 -0
  693. package/src/adapters/node/process.io.ts +49 -0
  694. package/src/adapters/node/process.test.ts +46 -0
  695. package/src/adapters/node/workspace.io.ts +40 -0
  696. package/src/adapters/node/workspace.test.ts +58 -0
  697. package/src/adapters/pdfjs/fill.test.ts +111 -0
  698. package/src/adapters/pdfjs/fill.ts +141 -0
  699. package/src/build-engine.harness.mjs +314 -0
  700. package/src/build-engine.ts +219 -0
  701. package/src/build.harness.mjs +631 -0
  702. package/src/build.mutations.mjs +195 -0
  703. package/src/build.ts +793 -0
  704. package/src/cli.harness.mjs +2007 -0
  705. package/src/cli.mutations.mjs +448 -0
  706. package/src/cli.ts +1189 -0
  707. package/src/doctor.harness.mjs +396 -0
  708. package/src/doctor.mutations.mjs +175 -0
  709. package/src/doctor.ts +356 -0
  710. package/src/domain/geometry.ts +108 -0
  711. package/src/domain/host.ts +23 -0
  712. package/src/domain/page-layout.ts +32 -0
  713. package/src/domain/paths.ts +5 -0
  714. package/src/domain/result.test.ts +26 -0
  715. package/src/domain/result.ts +29 -0
  716. package/src/domain/sha256.test.ts +12 -0
  717. package/src/domain/sha256.ts +21 -0
  718. package/src/domain/text.ts +11 -0
  719. package/src/engine.harness.mjs +252 -0
  720. package/src/engine.ts +176 -0
  721. package/src/exit-code.test.ts +21 -0
  722. package/src/exit-code.ts +38 -0
  723. package/src/facts-file.test.ts +240 -0
  724. package/src/facts-file.ts +241 -0
  725. package/src/hooks-settings.harness.mjs +386 -0
  726. package/src/hooks-settings.mutations.mjs +116 -0
  727. package/src/hooks-settings.ts +434 -0
  728. package/src/init.ts +900 -0
  729. package/src/latex-log.harness.mjs +226 -0
  730. package/src/latex-log.ts +234 -0
  731. package/src/latex-loop.harness.mjs +449 -0
  732. package/src/latex-loop.ts +211 -0
  733. package/src/link-skills.harness.mjs +273 -0
  734. package/src/link-skills.mutations.mjs +136 -0
  735. package/src/link-skills.ts +258 -0
  736. package/src/new-paper.harness.mjs +216 -0
  737. package/src/new-paper.mutations.mjs +79 -0
  738. package/src/new-paper.ts +158 -0
  739. package/src/pdf-facts.harness.mjs +188 -0
  740. package/src/pdf-facts.ts +327 -0
  741. package/src/pdf-geometry.harness.mjs +254 -0
  742. package/src/pdf-geometry.ts +300 -0
  743. package/src/ports/download.ts +10 -0
  744. package/src/ports/files.ts +11 -0
  745. package/src/ports/measure-geometry.ts +8 -0
  746. package/src/ports/process.ts +46 -0
  747. package/src/ports/tool-installer.ts +33 -0
  748. package/src/ports/workspace.ts +20 -0
  749. package/src/rules-config.harness.mjs +114 -0
  750. package/src/rules-config.ts +178 -0
  751. package/src/structure.harness.mjs +179 -0
  752. package/src/structure.mutations.mjs +83 -0
  753. package/src/structure.ts +166 -0
  754. package/src/tex-requirements.harness.mjs +238 -0
  755. package/src/tex-requirements.ts +181 -0
  756. package/src/toolchain.harness.mjs +651 -0
  757. package/src/toolchain.ts +755 -0
  758. package/src/types.ts +106 -0
  759. package/templates/paper/PIPELINE-STATUS.md +72 -0
  760. package/templates/paper/paper.md +4 -0
  761. package/templates/paper/paper.tex +8 -0
  762. package/tsconfig.json +23 -0
@@ -0,0 +1,345 @@
1
+ // Compiled to SKILL.md by `vigiles compile`. Edit THIS file, never the markdown.
2
+ //
3
+ // Adopted 2026-08-17 (batch 3). Body carried over VERBATIM so the compiled diff shows
4
+ // only what the compiler adds. No `disallowedTools` fence yet — the field landed on
5
+ // `SkillSpec` in vigiles branch `claude/skill-disallowed-tools` and is not in a release
6
+ // this repo installs, so writing one here would not compile.
7
+ import { experimental_skill } from "vigiles/spec";
8
+
9
+ export default experimental_skill({
10
+ name: "verify-citations",
11
+ description:
12
+ "Verify every citation is a real work with correct metadata, and that the paper states its delta over the NEAREST prior work explicitly — before submit. For each \\cite, confirm the work exists (arXiv id / DOI / venue+year) and that author/title/venue/year are right (WebSearch/WebFetch); never fabricate — mark VERIFY on anything uncertain and flag invented-looking cites; make sure the paper says what it adds over its closest neighbor, and that the one obviously-expected citation a reviewer will miss if absent is present. Use as a pre-submission gate. Compose with draft-paper, map-prior-work, pc-panel-review.",
13
+ tools: [
14
+ "Read",
15
+ "Write",
16
+ "Edit",
17
+ "Grep",
18
+ "Glob",
19
+ "Bash",
20
+ "WebSearch",
21
+ "WebFetch",
22
+ "Agent",
23
+ ],
24
+ body: `
25
+ # verify-citations — every cite real, the delta explicit
26
+
27
+ ## Run me
28
+
29
+ 🔴 FIRST, before any other step:
30
+
31
+ \`\`\`
32
+ node .claude/skills/paper-pipeline/scripts/announce.mjs verify-citations <paper-dir>
33
+ \`\`\`
34
+
35
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
36
+ state — so starting is an event, and events get written down.
37
+
38
+ Reviewers reject on a single fabricated or wrong citation — it reads as either sloppiness or a
39
+ hallucinated bibliography, and either one is fatal. And they reject on "this was already done by ___" if
40
+ your delta over the nearest prior work isn't spelled out. This skill closes both holes before submit.
41
+
42
+ ## 🔴 This is a CONTINUOUS check, not a step you finish
43
+
44
+ **It re-runs whenever a \`\\cite\` is added or moved.** Not once, not "at the end" — every time the
45
+ bibliography changes, including the edit you make on the last day. Scorecard row **\`cites\`** in
46
+ \`<paper-dir>/PIPELINE-STATUS.md\`; see the CONTINUOUS section of \`paper-pipeline\`.
47
+
48
+ - **A pass dated before the current text is STALE, and stale reads as green.** The date in the \`cites\`
49
+ row is compared against the paper's own mtime, and \`../paper-pipeline/scripts/pipeline-check.mjs\` reports the
50
+ mismatch — because a \`☑\` from three days and forty edits ago is worse than a \`☐\`: it looks closed.
51
+ - **"We checked last cycle" does not count.** Say it plainly, because it is the exact sentence that
52
+ ships a fabricated cite: a review round adds text, added text adds citations, and the run that
53
+ cleared the bibliography never saw them.
54
+ - A single new \`\\cite\` is enough to fire it. There is no batch size below which this is skippable.
55
+
56
+ *This skill used to sit at a number in the middle of a stage list, which made it read like a one-shot
57
+ step you tick off and move past — one of the three concrete errors that numbering produced, and the
58
+ reason the list was replaced on 2026-08-03. The project rule was always that it re-runs every cycle;
59
+ the position contradicted the rule, and the position is what people followed.*
60
+
61
+ ## 1. Every \\cite is a real work with correct metadata
62
+
63
+ For EACH reference in the \`.bib\` / bibliography:
64
+
65
+ - **Confirm it exists.** A real **arXiv id**, **DOI**, or **venue + year** that resolves. WebSearch the
66
+ exact title + first author; WebFetch the landing page. "I'm fairly sure this paper exists" is not
67
+ verification.
68
+ - **Confirm the metadata is right** — author list, exact title, venue, year. LLM-drafted bibs love to
69
+ merge two papers, shift a year, or attach the wrong venue to a real title. Check each field.
70
+ - **Confirm it says what you attribute to it.** If you cite a number or claim, open the source and check
71
+ the number is actually in it — cite the source's real range, not a rounded max.
72
+ - **Never invent a citation to fill a gap.** If a claim needs support you don't have, either find real
73
+ support or soften the claim. Do not manufacture a plausible-looking cite.
74
+
75
+ ## 2. Mark uncertainty, flag the invented-looking
76
+
77
+ - Anything you couldn't fully confirm → mark **\`% VERIFY\`** in the \`.tex\` at the cite site and resolve it
78
+ before submit. A VERIFY that survives to submission is a bug.
79
+ - **Flag invented-looking cites explicitly** — a too-perfectly-on-topic title, an author+venue combo that
80
+ doesn't turn up, a DOI that 404s. These are the ones that sink the paper; treat a non-resolving cite as
81
+ guilty until proven real.
82
+ - Archive the verified set (id/DOI + one-line "confirms X") so it's reusable across papers in the area.
83
+
84
+ ## 3. The delta over the NEAREST prior work must be explicit
85
+
86
+ The most common substantive reject is "this was already done by ___." Defend against it in the prose,
87
+ not just the bibliography:
88
+
89
+ - Identify the **single closest** prior work and state, in one sentence a reviewer can quote, what THIS
90
+ paper adds that it didn't do. Nearest-neighbor, not a vague "unlike prior work."
91
+ - If the nearest work made the *argument* and you supply the *measurement* (or vice versa), say exactly
92
+ that — the delta is the contribution.
93
+
94
+ ## 4. The one obviously-expected citation
95
+
96
+ Every subfield has a paper a reviewer expects to see; its absence reads as "the authors don't know the
97
+ area." Ask: what is the one work a reviewer in this exact niche will look for first? Make sure it's cited
98
+ and positioned. If you genuinely shouldn't cite it, know why.
99
+
100
+ ## 5. The deterministic reducer — \`scripts/verify-cites.mjs\`
101
+
102
+ Sections 1–4 are LLM judgment: good for the *delta* and the *expected-citation* calls, but non-reproducible
103
+ for the mechanical part — "does this id actually resolve?". \`scripts/verify-cites.mjs\` compiles that part into
104
+ a deterministic, cacheable gate (same "prose isn't policy → make it a self-checking artifact" move as
105
+ \`build-benchmark\`). Ported fresh (own code) from the OSS mining note
106
+ \`papers/research/oss-skill-mining-imbad0202.md\` (STEAL #1) + the CVE/PoC-SHA pinning from
107
+ \`oss-skill-mining-euzun.md\`.
108
+
109
+ **What it does.** For each citation it hits four real databases — Crossref, OpenAlex, Semantic Scholar,
110
+ arXiv — DOI/arXiv-id first, then a title search. Title comparison is **robust**, not raw Levenshtein: it
111
+ also does token-set containment + acronym expansion, so a split subtitle ("Gotta Catch 'Em All" vs the
112
+ subtitled full title), an abbreviation ("Deep CNNs" ↔ "Deep Convolutional Neural Networks"), or a
113
+ preprint→published title drift does **not** read as an unrelated paper. Normalization preserves Unicode
114
+ letters, so two *different* non-Latin titles no longer collapse to the same empty string. A title search
115
+ match still needs year within ±1. A \`CVE-YYYY-NNNNN\` is checked against NVD; a PoC/exploit \`commit\` is
116
+ checked for **exactly** 40 hex chars (short / >40 / malformed → advisory flag, not a verdict).
117
+
118
+ **The DOI-authority gate (M1 — why a 404 is never fabrication).** A 404 from a *content registry*
119
+ (Crossref / OpenAlex / Semantic Scholar) means only "this registry has no metadata," which is the **common
120
+ case** for DataCite/Zenodo DOIs and freshly-minted 2026 DOIs (including a paper's own artifact DOI). It is
121
+ **not** disproof of existence. So before ever emitting \`false\` for a DOI, the reducer requires the DOI
122
+ *authority* — \`doi.org/api/handles/{doi}\` — to say the handle does not exist (\`responseCode 100\`). A DOI
123
+ that resolves at doi.org but has no registry metadata → \`unresolvable\` (exists, metadata unverifiable),
124
+ never \`false\`. For arXiv ids, only a definitive not-found from the *reachable arXiv API itself* is disproof
125
+ (a Semantic-Scholar miss on a fresh arXiv id is not); arXiv's "Error" sentinel entry is detected as
126
+ not-found, not mistaken for an unrelated paper.
127
+
128
+ **The narrowed-false rule (the important part).** The reducer collapses evidence to three verdicts:
129
+
130
+ | verdict | when | meaning |
131
+ |---|---|---|
132
+ | \`true\` | any resolver **matched** (match always wins) | found, metadata matches |
133
+ | \`false\` | no match **and** an *authoritative* disproof: doi.org says the DOI is \`responseCode 100\`, the reachable arXiv API definitively rejects the id, NVD has no such CVE, **or** a DOI/arXiv id resolves to a *confidently-different* paper (\`DOI_MISMATCH\`) | fabrication — the only thing we call fabrication |
134
+ | \`unresolvable\` | title-misses, registry-404s with no authority disproof, uncomparable titles, and/or unreachable resolvers | couldn't verify, but **no positive disproof** |
135
+
136
+ The whole point: **a title you simply can't find is NOT fabrication** → \`unresolvable\`, never \`false\`. A
137
+ real-but-unindexed / regional / pre-digital paper looks exactly like a title-miss; a registry-404 without a
138
+ doi.org not-found looks exactly like a DataCite DOI; a network outage looks like neither — all degrade to
139
+ \`unresolvable\`. The reducer never turns a transport failure or a registry-404 into \`false\`. Fabrication
140
+ requires *positive* disproof from the relevant **authority**, or a DOI pointing at a confidently-different
141
+ paper.
142
+
143
+ **How to run.**
144
+ \`\`\`
145
+ node scripts/verify-cites.mjs cites.json # JSON array of {id,doi?,arxiv?,title?,year?,cve?,commit?}
146
+ node scripts/verify-cites.mjs refs.bib # best-effort .bib extraction
147
+ cat cites.json | node scripts/verify-cites.mjs -
148
+ node scripts/verify-cites.mjs cites.json --offline # no network (everything degrades to unresolvable)
149
+ \`\`\`
150
+ It prints per-cite \`{id, verdict, reason, matched_db, matched_title?, flags?}\` + a summary, and **exits 1 iff
151
+ any \`false\` (fabrication)** — \`unresolvable\` alone is advisory and does NOT fail the gate, matching the
152
+ narrowed-false philosophy. API responses are cached to \`scripts/.cite-cache.json\` (gitignored) so re-runs are
153
+ cheap and deterministic.
154
+
155
+ ## 5b. The author-list gate — \`scripts/bib-authors.mjs\`
156
+
157
+ \`verify-cites.mjs\` answers *"does this citation exist, and does the id point at it?"*. There is a second
158
+ question it structurally cannot ask, and on 2026-08-24 that gap cost three real defects in a bibliography
159
+ this skill had already reported as **"ALL 23 cites verified real"**:
160
+
161
+ > We write \`@inproceedings{... NeurIPS 2023}\`. Is our author list the **NeurIPS** one — or did we copy the
162
+ > **arXiv preprint's**?
163
+
164
+ The preprint and the published version are frequently **different lists**, and every existence check passes
165
+ either way: the paper is real, the id resolves, the title matches. What was found:
166
+
167
+ | entry | ours | the version we CLAIM to cite |
168
+ |---|---|---|
169
+ | \`schick2023toolformer\` | 8 authors | NeurIPS 2023 has **9** — **Eric Hambro** was simply absent |
170
+ | \`dehghani2022efficiency\` | Dehghani, Arnab, Beyer, Vaswani, Tay | ICLR 2022: Dehghani, **Tay**, Arnab, Beyer, Vaswani |
171
+ | \`raji2021benchmark\` | Raji, Bender, Paullada, Denton, Hanna | NeurIPS D&B 2021: Raji, **Denton**, Bender, **Hanna**, **Paullada** |
172
+
173
+ The first is a **real person dropped from a citation in an archival publication** — by our own scale that is
174
+ heavier than a typo, and it is exactly the class §"any regalia about third parties" already warns about.
175
+
176
+ **How to run.**
177
+ \`\`\`
178
+ node scripts/bib-authors.mjs <paper-dir> # or a .bib, or a .tex with a filecontents block
179
+ node scripts/bib-authors.mjs <paper-dir> --json
180
+ \`\`\`
181
+ Exits **1** on any author-set or author-order disagreement, **0** when clean, **2** on usage/IO error.
182
+
183
+ **Source is DBLP, and that choice is the evidence.** DBLP indexes the proceedings record and the CoRR record
184
+ **separately**, so a single query returns both lists side by side — the cleanest proof available that the
185
+ difference is real and not a metadata glitch. Entries that themselves declare a preprint venue are out of
186
+ scope (a preprint entry is allowed to carry preprint metadata).
187
+
188
+ ⚠️ **Discovery credit, and why it is NOT a dependency.** The class was found by running **rebiber**
189
+ (\`yuchenlin/rebiber\`), which rewrites bib entries into their DBLP records. We deliberately do not depend on
190
+ it: its install fights modern setuptools (the \`bibtexparser\` wheel dies with \`AttributeError:
191
+ install_layout\`), and its *output* replaces our entries with DBLP's very long official booktitles — wrong for
192
+ a page-limited paper. We needed the **comparison**, not the rewrite, and that is one fetch with zero deps.
193
+ Note also that live DBLP beat rebiber's bundled dump: \`raji2021benchmark\` was found only by the live query.
194
+
195
+ 🔴 **Two design decisions that are load-bearing, both learned by measurement the same day:**
196
+ 1. **Compare surname SEQUENCES, nothing else.** A first cut reported 13 differences of which **11 were
197
+ "Last, First" vs "First Last"** — pure formatting. A checker that cries 13 when 2 are real is read once
198
+ and then ignored; this repo has already killed a check that way (33 findings, 22 of them live files).
199
+ 2. **A failed lookup is NOT a skip.** The first run printed *"PASS: no author-list disagreement"* while
200
+ **9 of 27 entries had never been examined** (DBLP answered 429). Failures now retry with backoff and land
201
+ in a separate bucket that downgrades the verdict to **PARTIAL** — never \`PASS\`.
202
+
203
+ **Tests:** \`node scripts/bib-authors.test.mjs\` — 11 assertions, offline, with the three real entries above
204
+ pinned as regressions. Mutation-checked: collapsing the name normalisation makes it fail.
205
+
206
+ **Pure/impure split + tests.** The verdict logic (\`reduceVerdict\` / \`classifyResolver\` / \`checkNvd\` /
207
+ \`checkCommit\` + the string helpers) is a pure function of \`(citation, evidence)\` — the live HTTP layer only
208
+ shapes raw API responses into that evidence. \`scripts/verify-cites.test.mjs\` exercises the reducer offline with
209
+ injected fixtures (\`node scripts/verify-cites.test.mjs\`); no test touches the network.
210
+
211
+ **Honest limits.** Semantic Scholar rate-limits (HTTP 429) without an API key, and arXiv's export API can be
212
+ unreachable behind some proxies — both degrade to \`unreachable\` (→ contribute nothing, never \`false\`). And,
213
+ by design, the gate **declines** in three situations rather than risk a false accusation:
214
+
215
+ - **A fabrication with no identifier (only a bogus title)** escapes this existence gate → it surfaces as
216
+ \`unresolvable\`, and is caught by the LLM claim-faithfulness check (§1) + human review, not here. Verifying
217
+ a work *exists* is not the same as verifying the paper's *claim about it* is faithful — that's §1's job.
218
+ - **A non-Latin / cross-script or otherwise uncomparable title** on a DOI/arXiv record: we **cannot** assert
219
+ the id landed on an unrelated paper (a Russian work's DOI may record an English title), so we do **not**
220
+ emit \`DOI_MISMATCH\` — the id counts as resolved (\`true\`) or, absent other confirmation, \`unresolvable\`.
221
+ Never \`false\`. The \`doi_mismatch → false\` verdict fires **only** for two confidently-comparable titles that
222
+ are genuinely different.
223
+ - **A DOI that resolves at doi.org but has no content-registry metadata** (DataCite/Zenodo, fresh 2026 DOIs)
224
+ → \`unresolvable\`, because the work exists but its metadata (title/year) cannot be cross-checked here. This
225
+ is the correct verdict for a paper's own artifact DOI; treat \`unresolvable\` as advisory, not a failure.
226
+
227
+ **Known narrow residue (rare, treat a lone \`DOI_MISMATCH → false\` as advisory, eyeball it).** Two edge cases
228
+ can still mis-fire: (a) a correct DOI whose *every* registry records junk metadata — e.g. the container /
229
+ proceedings title instead of the paper's — reads as "unrelated" (mitigated when any one registry has the real
230
+ title, since a match wins); (b) a translated-journal title in the *same script* (transliterated Latin vs
231
+ English) that shares no tokens. Both need semantics the gate doesn't have; both are near-zero frequency in an
232
+ English CS bib. Identifier-prefix / trailing-punctuation mangling (\`doi:\`, \`arXiv:\`, a bib-swallowed \`.\`) is
233
+ **fixed** — normalized at the verify boundary — so the common real-DOI-→-\`false\` path is closed.
234
+
235
+ ## 5b. The ATTRIBUTION gate — \`extract-ref-facts.mjs\` + the \`refs/*\` ESLint rules
236
+
237
+ §5 asks *does this identifier name a real work*. This one asks *is the work it names the one the entry
238
+ describes* — and those are different questions, which is why they are different tools and not one flag.
239
+ Run both; neither replaces the other.
240
+
241
+ 🔴 **Moved 2026-08-26 out of a script and into rules** (ladder step 3, the \`CLAUDE.md\` beside the papers).
242
+ It used to be one script, \`verify-refs.mjs\`; the measurement half stayed a script and the judgement half
243
+ became twelve ESLint rules over the facts it writes.
244
+
245
+ \`\`\`
246
+ # 1. measure: parse the bibliography, ask CrossRef/arXiv, write _build/refs.facts.json
247
+ node .claude/skills/paper-pipeline/scripts/extract-ref-facts.mjs <paper-dir>
248
+ node .claude/skills/paper-pipeline/scripts/extract-ref-facts.mjs <paper-dir> --offline # cached responses only
249
+
250
+ # 2. judge: rules over those facts — severity from the config, positions, disable-with-reason
251
+ npx eslint --no-config-lookup --config eslint.config.mjs "<paper-dir>/_build/refs.facts.json"
252
+ \`\`\`
253
+
254
+ **Why it exists, stated plainly: \`verify-cites.mjs\` never compares an author list.** It parses \`author\`
255
+ out of a \`.bib\` into the citation object and then does nothing with it — the string appears twice in 991
256
+ lines, once in a doc comment and once in the extractor. So of the nine broken references this project
257
+ shipped across two nights, the shapes it structurally cannot see are the ones about ATTRIBUTION: seven
258
+ wrong initials on correct surnames, a reversed author order, an invented award. This leg closes that,
259
+ the same one MedSci Skills (arXiv:2606.09500) closes with \`verify_refs.py\`.
260
+
261
+ | | \`verify-cites.mjs\` (§5) | the \`refs/*\` rules (§5b) |
262
+ |---|---|---|
263
+ | question | does the id resolve to *something* | is *that* the work the entry describes |
264
+ | registries | Crossref · OpenAlex · Semantic Scholar · arXiv | CrossRef · arXiv (the two that matter for CS) |
265
+ | authors | **never compared** | surname multiset **+ order-sensitive first author** |
266
+ | year | ±1 on a title search | exact, and only against the record that dates the cited version |
267
+ | preprint→published | not asked | arXiv \`journal_ref\`/\`doi\` present and no venue named → say so |
268
+ | what it could not check | folded into \`unresolvable\` | **enumerated, one rule per reason, never counted as verified** |
269
+ | tests | \`verify-cites.test.mjs\` — not a \`*.harness.mjs\`, so \`npx vigiles test\` never runs it | \`eslint-rules/ref-facts.harness.mjs\` + \`.claude/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs\`, plus \`eslint-rules/ref-facts.mutations.mjs\` |
270
+
271
+ **The uncovered set is the point.** A reference with no resolvable identifier is a FINDING here
272
+ (\`refs/no-identifier\`), and every partial comparison is another (\`refs/partial-check\`, one messageId per
273
+ reason). On this project's submitted bibliography that set is 17 entries of 67 — an npm package, a Supreme
274
+ Court dissent, an FAA circular, Dijkstra. None of them is a defect; all of them are things a model checker
275
+ would have reported as fine. Being able to hand a reviewer the list of what was NOT machine-verified is a
276
+ property no model-driven pass has.
277
+
278
+ 🔴 **\`.bib\` papers were never checked by the old script — two dead legs, both measured 2026-08-26.**
279
+ \`refs.bib\` was not in its source list (so \`agenticdev-2026\` and \`aisec-2026\` answered "nothing to check"),
280
+ and its \`.bib\` regex required a closing \`}\` on its own line, which neither real file has (\`parsed 0
281
+ references\`). The \`.bib\` half now goes through \`@retorquere/bibtex-parser\`. Two of the three papers are
282
+ therefore being checked for the first time.
283
+
284
+ **Every check is watched failing.** \`node eslint-rules/ref-facts.mutations.mjs\` neuters each rule in turn
285
+ and requires the harness to go red at the named case — 21 mutations, all killed, and three of them were
286
+ findings about the TEST rather than the rule. Run it after any edit to the rules.
287
+
288
+ ## 6. Record the verdict
289
+
290
+ 🔴 LAST step, once the deliverable exists:
291
+
292
+ \`\`\`
293
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record verify-citations <paper-dir> FINDING <count> <report-path>
294
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record verify-citations <paper-dir> ABSTAINED <reason> "<one line>"
295
+ \`\`\`
296
+
297
+ **FINDING** — \`<count>\` is the number of cites still \`% VERIFY\` or \`unresolvable\`; \`<report-path>\`
298
+ lists them. Add \`--blocking\` for a cite an authoritative source disproves, or a missing delta
299
+ sentence; either is a submit blocker.
300
+ **ABSTAINED** — \`no-witness\`: every cite resolved with correct metadata and the delta sentence is in
301
+ the prose. \`crashed\`: the registries were unreachable, so nothing was verified — which is emphatically
302
+ not the same as everything checking out, and under the old vocabulary both came back \`PASS\`.
303
+
304
+ 🔴 **There is no PASS.** \`no-witness\` here means every cite the paper makes was looked up and none
305
+ of them came back wrong. It does not mean the bibliography is complete: this check cannot see a work
306
+ that should have been cited and is not. That gap belongs to \`map-prior-work\`, and no row here covers it.
307
+
308
+ Because this check is CONTINUOUS, it writes a row per run and never a final one. That is the point:
309
+ the ledger compares the row against the paper's current bytes, so a pass that predates the last three
310
+ \`\\cite\` additions reports as STALE-PAPER instead of reading as green.
311
+
312
+ ## Rules
313
+ - **Re-run on every \`\\cite\` added or moved.** A \`cites\` row older than the paper's text is a stale pass,
314
+ not a green one — "we checked last cycle" is not a verification.
315
+ - No cite ships unverified. Exists + correct metadata + says-what-you-claim, or it's \`% VERIFY\`.
316
+ - Never fabricate to fill a gap — soften the claim instead.
317
+ - The delta over the nearest neighbor is prose, not an implication.
318
+ - Report honestly: a cite you can't confirm is a finding, not something to wave through.
319
+ - A title you can't find is \`unresolvable\`, not a fabrication — \`false\` needs an *authoritative* disproof
320
+ (doi.org \`responseCode 100\`, a reachable arXiv rejection, NVD-has-no-CVE) or a confidently-different title.
321
+ A registry-404, an uncomparable/non-Latin title, or any transport failure is \`unresolvable\`, never \`false\`.
322
+
323
+ ## Compose with
324
+ - **draft-paper** — related-work and the delta sentence are drafted there; this skill audits them.
325
+ - **map-prior-work** — fan-out prior-art search; use it to resolve hard-to-find cites and to surface
326
+ the expected-but-missing citation. ⚠️ **Was \`deep-research\` until 2026-08-31 — no such skill has
327
+ ever existed in this base** (0 matches on disk), and the name appeared BOTH here and in this
328
+ skill's own \`description\`. A pointer to a non-existent skill fails silently: the step is simply
329
+ not performed, and the compose line still reads as if coverage were arranged.
330
+ - **analyze-sibling-paper** — when a resolved cite turns out to be a close neighbor, that skill does
331
+ the deep overlap/scoop analysis this one is too shallow for.
332
+ - **pc-panel-review** — its novelty/related-work reviewer will probe the delta and hunt uncited neighbors;
333
+ clear this skill first so that lens finds nothing.
334
+
335
+ ## Provenance
336
+ Both papers grounded their novelty delta over the nearest prior work explicitly, and that framing is what
337
+ made them land:
338
+ - **AgenticDev 2026 — "Measuring the Wrong Number":** positioned against Kapoor et al. *"AI Agents That
339
+ Matter"* and Dehghani et al. *"The Efficiency Misnomer"* — the delta being a cost-aware,
340
+ correctness-gated *measurement* where those argued the problem.
341
+ - **AISec 2026 @ CCS — "Safety Theater":** positioned against Ptacek & Newsham (the classic
342
+ evasion-testing framing), **AgentDojo**, and **IsolateGPT** — the delta being a static, mutation-and-
343
+ ablation evaluation of real command-guards rather than a new defense. Each of these was verified real,
344
+ with correct venue/year, before submit.`,
345
+ });