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,336 @@
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: "harden-paper",
11
+ description:
12
+ 'Use when asking "is this paper actually ready to submit?" / "what\'s still missing before I upload?" / "run the pre-submission gate" on a DRAFTED paper. The multi-axis hardening orchestrator — it runs the review skills AND closes the axes they miss (structure via tighten-paper, threat-model + ethics/dual-use, reproducibility artifact, double-blind hygiene, page/word-fit, citability), and its verdict is a VECTOR of gates reported worst-gate-first — any failing gate (readability, structure, claims, citations, nearest-neighbor scoop, mechanical) caps "ready" regardless of a high accept-probability. NOT for grading how the prose reads (grade-paper-writing), a structural cut plan alone (tighten-paper), or a single hostile review (paper-adversarial-review) — this calls all of those and makes the submit/no-submit decision. Composes with pc-panel-review / verify-citations (it calls them) and submit-paper (downstream).',
13
+ tools: [
14
+ "Read",
15
+ "Write",
16
+ "Edit",
17
+ "Grep",
18
+ "Glob",
19
+ "Bash",
20
+ "WebSearch",
21
+ "WebFetch",
22
+ "Agent",
23
+ "Skill",
24
+ ],
25
+ body: `
26
+ # harden-paper — the multi-axis pre-submit gate
27
+
28
+ > **Which paper skill?** \`paper-adversarial-review\` / \`pc-panel-review\` (whose venue-fit mode covers the
29
+ > CFP-fit score) = the *reviewer's-eye* axis (defects, fit, accept-prob). \`verify-citations\` = the
30
+ > *citation* axis.
31
+ > **\`harden-paper\` (here) = the orchestrator** that runs those AND closes the axes a reviewer-sim
32
+ > doesn't systematically hit — the submission-readiness gate. Run it after the draft is written and
33
+ > before \`submit-paper\`. It does not re-implement the sub-skills; it calls them and checks the rest.
34
+
35
+ ## Run me
36
+
37
+ 🔴 FIRST, before any other step:
38
+
39
+ \`\`\`
40
+ node .claude/skills/paper-pipeline/scripts/announce.mjs harden-paper <paper-dir>
41
+ \`\`\`
42
+
43
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
44
+ state — so starting is an event, and events get written down.
45
+
46
+ **Principle:** a paper dies from any *one* unclosed axis. Reviewers only *read* — so every claim,
47
+ number, and omission must survive on the page. Go axis by axis; for each, **find → fix → re-verify**,
48
+ don't just list. Below, each axis says what to run / check and the specific traps that recur.
49
+
50
+ > Axes 1–10 are **soundness** gates (get it accepted / avoid desk-reject). Axis 11 (**citability**) is
51
+ > the *impact* gate — a correct-but-forgettable paper passes review and gets cited zero times. For a
52
+ > body of work, citability is not optional polish; run it as a gate too.
53
+
54
+ ## The axes (run all; each is a gate)
55
+
56
+ **Order matters: STRUCTURE before SENTENCES.** Run axis 0 FIRST. There is no point polishing prose (axis 8),
57
+ verifying claims, or scoring a section that a structural pass says to cut or fold to the artifact. The 2026-07
58
+ AISec session did this backwards — a full sentence-level polish, *then* the author said "it's too long and the
59
+ middle sags" — wasting the polish on possibly-cut sections.
60
+
61
+ 0. **Structure / editorial (run FIRST)** — run **\`tighten-paper\`**: is this the right paper, at the right length,
62
+ delivering its ONE point, skimmable, with no TMI that belongs in the artifact? Apply its cut/fold/merge/reorder
63
+ plan BEFORE any sentence-level work. On a paper that "feels long / overly complex / middle drags," this is the
64
+ highest-leverage pass. (Near a deadline, apply the SAFE cuts and hold big restructures for camera-ready — state
65
+ the tradeoff, don't silently gut a submitted paper.)
66
+
67
+ 1. **Reviewer defects** — run \`paper-adversarial-review\` (quick) and, as the final decision gate,
68
+ \`pc-panel-review\`. Use a *separate model* (e.g. Fable subagent) as the reviewer, and — critically —
69
+ **run it blind**: give it ONLY the submission text, no author, no sibling papers, no outside context.
70
+ A sighted review judges overlap; a blind review predicts what the real double-blind PC sees. Do both:
71
+ sighted for overlap/de-anon, blind for the true score.
72
+
73
+ 2. **Overclaims — suite-specific traps only (the general hunt is delegated).** The general
74
+ overclaim hunt — every sentence stronger than the evidence, causal-from-correlational, headline
75
+ numbers vs reported stats, title over-promise — is \`paper-adversarial-review\`'s job, and axis 1
76
+ already runs it; don't redo it here. This axis adds the traps that recur in THIS suite's papers
77
+ and that a generic hunt keeps missing:
78
+ - **Absolute "no / none / never / first / only."** These are almost always false or unprovable.
79
+ Soften to "no *established / adopted / install-time* X," or "*first to* [narrow, true scope]."
80
+ - **Self-contradiction with your OWN citations** — an absolute your own reference list refutes
81
+ (e.g. "no provenance controls exist" while you cite an emerging provenance registry — a self-own).
82
+ - **Rhetorical hooks that reality falsifies** (e.g. "you'd never install a library that runs
83
+ arbitrary code" — npm postinstall does exactly that). Reframe to the *true* differentiator.
84
+ - **The review-ratchet rule — how to FIX a caught overclaim.** Tighten → cut → move to Threats →
85
+ only then inline-hedge; review only ever ADDS, so run \`tighten-paper\` AFTER the round to strip
86
+ what it deposited. Full rule: \`paper-pipeline/references/review-ratchet.md\`.
87
+ - 🔴 **A bound that lives only in an appendix is still an overclaim.** Check every headline number
88
+ in the abstract and intro against the appendices: if a qualification narrowing it sits out
89
+ there with no pointer reaching it, the body is overclaiming and "it's in the appendix" is not
90
+ a defence — reviewers are not required to read appendices, and ARR says so in as many words.
91
+ Rule and the sorting test: \`paper-pipeline/references/body-vs-appendix.md\`.
92
+ Mechanical leg: the ESLint rule \`paper/uncited-assertion\` (axis 7) compiles part of this hunt.
93
+
94
+ 3. **Novelty vs the nearest neighbor** — the scoop check. Search for the paper that *already did your
95
+ thing* (\`verify-citations\` covers metadata; here, actively hunt the closest empirical/method twin).
96
+ For every genuine sibling found, run **\`analyze-sibling-paper\`** — deep-read the ACTUAL paper (not its
97
+ abstract), classify contribution type, date it prior-vs-concurrent, steelman the scoop, and judge the
98
+ delta with an adversarial model. If found: cite it, and **rewrite the delta honestly** — you are almost
99
+ never "first"; you are "first to [specific lens/surface/method]." Acknowledge a shared *concept*
100
+ head-on. A genuine scoop is an escalation (reframe / \`extend-paper\`), not a one-line patch. Missing the
101
+ neighbor = desk-reject. **Completeness check (the checkable part):** every close sibling must have a
102
+ saved analysis colocated in \`<paper-dir>/siblings/\` — a close competitor with no file there is an
103
+ unclosed axis, not a cleared one.
104
+
105
+ 4. **Citations** — run \`verify-citations\`: every \\cite is a real work with correct arXiv-id/DOI/venue;
106
+ no fabrication; the delta over the nearest neighbor is explicit; the one obviously-expected cite is
107
+ present. Drop any cite you cannot verify (never invent metadata).
108
+
109
+ 5. **Threat model (security/systems venues)** — reviewers dock a security paper with no explicit one.
110
+ State: **adversary** (who, what capability), **trust boundary**, **assets**, and what you **assume
111
+ not** compromised. One crisp paragraph. \`paper-adversarial-review\` does not force this — add it.
112
+
113
+ 6. **Ethics / responsible disclosure / dual-use (security venues)** — often a hard CFP requirement.
114
+ If you measured weaknesses in *named real systems*: (a) report aggregate + anonymized; (b) plan
115
+ **disclosure to affected maintainers before any public de-anonymized release** (log it as a to-do);
116
+ (c) add a **dual-use** line (the work is defensive; introduces no new exploitation technique).
117
+
118
+ 7. **Reproducibility artifact** — if the paper says "artifact / query set accompanies this submission,"
119
+ that file must actually exist. Build a \`REPRODUCE.md\`: **every headline number → its exact query /
120
+ command → the count/output → the date**. State that snapshot counts drift (lower bounds), so
121
+ re-running gives similar magnitudes, not identical integers.
122
+ - **Availability-promise gate (verify, don't assume):** every "we release X" / "the full repo will be linked
123
+ at camera-ready" / "available at \\url{...}" sentence must point to something that EXISTS or is concretely
124
+ deliverable NOW — actually fetch the repo/URL and confirm it holds what the sentence claims (the harness, the
125
+ task defs, the logs). A promise you can't cash is a camera-ready landmine. (This session: verified
126
+ \`zernie/vigiles/bench/ecosystem\` really contains the promised harness before trusting Paper 1's Availability
127
+ line.) If it's deferred to camera-ready, record the exact deliverable in the paper's camera-ready checklist so
128
+ it can't be dropped on accept.
129
+ - **Adversarial cold reproduction — run the protocol, don't restate it:**
130
+ **\`../build-benchmark/references/adversarial-cold-repro.md\`** (single home). It covers the cold
131
+ clean-checkout/clean-ENVIRONMENT re-run (incl. the \`MODULE_NOT_FOUND\` deps-in-release-script trap),
132
+ the three-way reconcile of every headline number, and robustness attacks under the paper's own
133
+ caveats. Default stance SKEPTIC; one honest REFUTED beats ten hand-wavy CONFIRMEDs.
134
+ - **Claim↔evidence reconciliation (mechanical — every number and every "we release X" must trace).**
135
+ The measurement gate above checks *headline* numbers; two things slip it. Run both enumerators:
136
+ - **\`check-release-claims.sh <paper-dir>\`** — greps release-verb prose and lists it beside the actual
137
+ \`artifact/\` tree. **Every "we release X" must be satisfied by a shipped file**; promised-but-absent
138
+ (claimed "raw runs" but shipped only aggregates) → soften to "(at camera-ready)" or add the file.
139
+ *(This session's exact miss: a paper about advertised-vs-delivered gaps claimed "we release the
140
+ harness and raw runs" while the artifact held only aggregates — the PC-panel caught it late.)*
141
+ - **\`check-numbers.sh <paper-dir>\`** — enumerates every quantitative token in the body so **each traces
142
+ to an artifact output or a \`\\cite\`; an untraceable number is treated as fabricated** (source or cut).
143
+ *(This session: "37% growth to 18% cut across independent runs" was in neither — only the artifact
144
+ evaluator caught it.)*
145
+ - **\`npx eslint --no-config-lookup --config eslint.config.mjs <paper-file.tex|.md>\`** — the *overclaim*
146
+ axis (axis 2), compiled. The rule is \`paper/uncited-assertion\` (\`eslint-rules/paper-claims.mjs\`); it
147
+ used to be a hand-run script \`check-uncited-assertions.{sh,mjs}\`, ported into the rule family on
148
+ 2026-08-27 because the script had to be REMEMBERED and the rule runs with the other 32 in one pass —
149
+ on all four paper bodies, \`.tex\` included, not just \`paper.md\`.
150
+ It flags any sentence making an empirical/quantitative claim about **prior work** — a number, a \`%\`, a
151
+ fuzzy quantifier (\`most\`/\`the majority\`/\`significantly\`), or an empirical verb
152
+ (\`shows\`/\`demonstrates\`/\`outperforms\`/\`reduces\`/\`improves\`/\`we find\`) — that carries **no citation**.
153
+ Citation forms recognized: **any \`\\…cite…\` macro** (\`\\cite\`/\`\\citep\`/\`\\citet\`/\`\\footcite\`/\`\\smartcite\`/
154
+ \`\\parencite\`/\`\\textcite\`/\`\\citeauthor\`/\`\\citeyearpar\`…), \`\\footnote\`, **numeric cites** \`[12]\`/\`[3,4]\`/
155
+ \`[1]\` (the dominant CS style), a URL, or a markdown \`[@key]\`/\`[^fn]\`/\`](link)\`. This is the exact thing a
156
+ reviewer pounces on ("[citation needed]"). *Complementary to \`check-numbers.sh\`, not a dup:* that one
157
+ traces **every** number; this one flags **empirical assertions lacking a cite** and stays quiet on the
158
+ paper's own results. **Guards** (so it doesn't false-alarm): years (\`2026\`), version numbers (\`v1.2\`,
159
+ \`Node 18\`), figure/table/section/equation refs — both literal (\`Table 2 shows …\`) and cross-ref macros
160
+ (\`Table~\\ref{tab:x} shows …\`, \`\\autoref\`/\`\\Cref\`), numbers inside math mode, **tabular/array bodies** and
161
+ **ordered-list markers** (\`2.\`), **definitions** (\`is defined as\`/\`refers to\`/\`we define\`), and the
162
+ paper's **OWN reported results**. The own-result guard is a **subject-proximity heuristic** (not a
163
+ parser): it exempts a sentence only when first person is the *subject* — it **starts** with
164
+ \`we\`/\`this paper\`/\`this work\`, or has \`we <verb>\` / \`our <contribution-noun>\` — so \`We find a 6% reduction\`
165
+ passes but a bare \`Transformers outperform RNNs by 12%\` flags, and, deliberately, \`US-based detectors
166
+ reject 40%\` (country "US", not "us") and \`Our reading of the literature shows X outperforms Y\` (a claim
167
+ about others) still **flag**. Fix each hit by attaching a cite, reframing honestly as your own result, by
168
+ cutting the claim — or, for a genuinely defensible one, an \`eslint-disable-next-line\` **with the reason
169
+ on the spot**. Contract fixtures live in \`fixtures/uncited-assertions-sample.{tex,md}\` (annotated
170
+ MUST/​MUST-NOT-flag cases, incl. the numeric-cite / \`\\footcite\` / \`\\ref\`-float / list-marker / own-result
171
+ regressions) and are still the rule's test — \`eslint-rules/paper-claims.harness.mjs\` runs them.
172
+ *(Severity is \`warn\` on purpose: both the own-result guard and sentence splitting are **heuristics** —
173
+ a fixed abbreviation set (\`vs.\`/\`e.g.\`/\`i.e.\`/\`et al.\`/\`cf.\`) is protected from false breaks, and on the
174
+ four committed papers the rule reports 374 findings. Treat volume as advisory, not a hard gate.)*
175
+ Enumeration is mechanical; the per-line trace/reconcile stays judgment (prose isn't policy — compile the list).
176
+
177
+ 8. **Writing craft (audience-appropriate language + how it reads)** — run **\`grade-paper-writing\`** (the
178
+ 9-dim rubric in \`../paper-pipeline/references/writing-craft.md\`).
179
+ 🔴 **Invoke it BY NAME with the Skill tool — do not describe the need and hope it fires.**
180
+ Selection of this skill is **not reliable, and not reliably bad either**: the same eight prompts,
181
+ the same description and the same 36 competitors measured **21%** in the morning and **50–54%**
182
+ hours later on 2026-08-08, across two independent implementations
183
+ (\`../paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-raw.log\`,
184
+ \`2026-08-08-parent-replication.log\`). Seven description rewrites — shorter, no negations, no
185
+ internal machinery, persona-only — moved it by nothing, so the instability is not in the text and
186
+ cannot be edited away. Meanwhile a closed-book reader given that same text picks it 7–8 times in 8.
187
+ An explicit call does not depend on selection at all. Without it this axis silently does not run,
188
+ and a hardening pass that skipped its readability axis reports the same "done" as one that ran it.
189
+ **Downstream of axis 0** (don't polish a
190
+ section slated to be cut). Two hard rules from the AISec session: (a) run the stall pass as a **persona
191
+ subagent** ("Sam", a non-expert reader), per-section for a dense paper — the rubric SCORE under-fires because a
192
+ frontier grader knows every term and never stalls (it scored a wall-heavy paper 44/60); the persona inventory,
193
+ not the number, is the gate. (b) **A wall / spec-sheet / coined-jargon-heading HARD-FAILS this axis — it is not
194
+ a "minor" note.** Strip jargon the *target venue's* reviewers won't know (register-calibration: keep field-native
195
+ terms, gloss methodology shorthand, rename coinages), and confirm the paper leads with its most visceral concrete
196
+ instance. **After any rewrite here, run the claim-preservation diff (\`claims\` —
197
+ \`../paper-pipeline/references/writing-craft.md\` → "The claim-preservation diff") — rewording silently
198
+ changes claims.**
199
+
200
+ 9. **Internal consistency — matching is not enough; every headline count must be RECONSTRUCTIBLE from
201
+ the object that presents it.** Two distinct checks:
202
+ - *(a) Matching:* every number agrees across abstract / intro / results / tables (86% = 19/22; the
203
+ "X trip nothing" complements the "Y have finding" count). One mismatch reads as sloppy.
204
+ - *(b) Countability:* for every "N categories / N rules / N repositories / N cases" in the abstract,
205
+ **open the table or figure it points to and count the rows.** If a reader cannot arrive at N from
206
+ that object alone, either the object is wrong or N needs its derivation stated in the caption.
207
+ Sub-items buried in a cell's prose are not rows. **Mechanical leg:** \`grep -c\` the table's row
208
+ marker and compare with the abstract's N — a mismatch is a finding, not a rounding difference.
209
+ Corollary: **never quote a count for an entity that has no row of its own.**
210
+
211
+ 10. **Honest scoping** — a threats-to-validity that pre-empts the obvious attacks (sample size,
212
+ selection bias, construct validity, "measured X not Y") earns trust. Turn limitations into stated
213
+ scope, not hidden holes.
214
+
215
+ 11. **Citability** — soundness gets you accepted; citability gets you *cited* (the axis that actually
216
+ moves an impact case). A correct-but-forgettable paper is a desk-accept and a dead end. Make the
217
+ work the thing people reach for when they discuss the problem. Levers, in order of payoff:
218
+ - **Coin a reusable handle for the phenomenon** and ride an *existing* citation pattern. One named
219
+ concept that fills a naming gap ("the *install surface*", riding "the lethal trifecta") becomes the
220
+ noun people cite. Rules: it must name something readers already feel but can't point to; short,
221
+ literal, goog-able, not cute; **defined in one sentence on first use** (abstract if possible);
222
+ used consistently (grep — no synonym drift). One coinage per paper, max.
223
+ - **Frame the contribution as "first *taxonomy / benchmark / measurement* of X,"** not "we found Y is
224
+ bad." A reusable framework (the four risk classes, the audit predicate) is what later work builds
225
+ on and cites; a one-off result is a blog post. (This is the same reframe as axis 3, aimed at
226
+ citability rather than novelty-defense.)
227
+ - **Ship a reusable artifact others can run against their own corpus** — a deterministic
228
+ benchmark/auditor + a listed query set turns readers into *users*, and users cite. State it's
229
+ open-source and reproducible (ties to axis 7).
230
+ - **Give one quotable, load-bearing statistic** — a single number a talk/blog will repeat ("<1% carry
231
+ any test"). Make it defensible and prominent; don't bury it.
232
+ - **Dry humour is a citability multiplier — but *framing only*.** One deadpan line that crystallizes
233
+ the absurdity ("comes with a README") makes the concept sticky and quotable. Strict scope: allowed
234
+ in intro/framing/section-openers; **never** in methodology, threat model, ethics, results, or
235
+ limitations (humour there reads as unrigorous and sinks trust). One or two lines total, deadpan not
236
+ jokey, load-bearing not decorative.
237
+ - **arXiv-first + plan the extended SoK.** A 2-page workshop paper is a flag-plant; the citations
238
+ accrue to the extended/arXiv version. Log the follow-on (fuller taxonomy, bigger corpus, the
239
+ dropped refs) so the citable artifact exists. Put a preprint where people can find and cite it.
240
+
241
+ ## Mechanical submission gates (do these yourself — don't punt to the author)
242
+
243
+ - **Double-blind hygiene.** Run the mechanical gate — it greps the deny-list across the PDF text +
244
+ every artifact file + inside any \`*.zip\`, so an identifier hiding in an artifact README (invisible to
245
+ a paper-only read) still trips it: \`bash .claude/skills/submit-paper/check-deanon.sh <paper-dir>\`
246
+ (must PASS/exit 0; deny-list at \`.claude/skills/submit-paper/deanon-denylist.txt\`). Beyond the
247
+ deny-list, also grep the *actual submission text* for author name, tool name, org, repo
248
+ URLs, self-authored issue links. For a tool you built that's publicly attributed: **anonymize its
249
+ name AND its distinctive output vocabulary** (a reviewer can fingerprint the tool by running it and
250
+ matching its exact strings → de-anon, and can *link* it to your other submissions). Anonymize the
251
+ artifact host too ("released on acceptance").
252
+ - **Word / page fit — verify, don't estimate.** Word caps: count them. Page cap: **render and count.**
253
+ When a LaTeX toolchain exists in the env, the primary route is **\`../render-paper/check-render.sh\`**
254
+ (compile the real \`.tex\`, count real pages). The Chromium proxy below is the FALLBACK only.
255
+ No LaTeX in-env? Build an HTML at the venue's density (single-column 10pt Letter, 1in margins is a
256
+ typical proxy) with the exact content + table + refs, and render with headless Chromium:
257
+ \`/opt/pw-browsers/chromium-*/chrome-linux/chrome --headless --no-pdf-header-footer
258
+ --print-to-pdf=fit.pdf fit.html\`, then read the page-tree \`/Count N\` from the PDF (\`grep -aoE
259
+ '/Count [0-9]+' fit.pdf | head -1\`). Trim the reference list to the essential subset if it spills —
260
+ the body text + a lean ~10 refs is what must fit; the rest go to the extended/journal version.
261
+ - **Format template.** Confirm the venue's actual template (ACM sigconf / Word / 2-part SiP). Match its
262
+ structure, not just your draft's.
263
+
264
+ ## Output — a VECTOR of gates, never one number
265
+
266
+ The verdict is a **vector of independent gates**, and **ANY failing gate caps the verdict at "not
267
+ ready"** — the gates are orthogonal axes and do not average out. **Ready ⇔ ALL of these pass:**
268
+
269
+ - **Science / defects** — \`pc-panel-review\` decision + accept-probability;
270
+ - **Readability** — \`grade-paper-writing\`'s PERSONA stall pass (the inventory + density caps, not the
271
+ rubric number);
272
+ - **Structure + length** — \`tighten-paper\`'s structural verdict (right length, no sag, no TMI);
273
+ - **Claims-honest** — the Hn claim-preservation diff clean after every rewrite;
274
+ - **Citations** — \`verify-citations\` clean: no \\cite that fails to resolve, nothing marked VERIFY
275
+ left unresolved;
276
+ - **Nearest-neighbor scoop** — axis 3 answered: the closest sibling found and either distinguished
277
+ or escalated (\`analyze-sibling-paper\`);
278
+ - **The mechanical gates** — de-anon hygiene, page/word-fit, format template.
279
+
280
+ > 🔴 **Citations and scoop were MISSING from this list until 2026-08-31, and the omission had
281
+ > teeth.** This same file calls axes 1–10 «soundness gates (get it accepted / **avoid
282
+ > desk-reject**)» and says outright that a missed neighbor «= desk-reject». But the \`--blocking\`
283
+ > rule below keys on *this list*: anything absent from it is «an axis **merely** being open», i.e.
284
+ > non-blocking. So the two axes the file names as fatal were the two that could not stop a submit.
285
+ > The list read as exhaustive because it is introduced by **«Ready ⇔ ALL of these pass»** — and a
286
+ > list in that position is read as the definition, not as examples.
287
+ > **Generalisable:** a rule stated as «not narrower than X», or a gate stated as «all of these»,
288
+ > narrows to exactly what its list contains. Same defect class found the same night in
289
+ > \`corporate-english-lead-search\` (geo list omitted Russia → a 357-employer scan with zero
290
+ > Russian companies, unnoticed for 11 days).
291
+
292
+ **A high pc-panel accept-probability does NOT mean "ready" if the readability or structure gate
293
+ fails. A single scalar (e.g. "88% accept") hides multi-dimensional failure — never report it as the
294
+ headline.** Report the verdict **WORST-GATE-FIRST**: lead with the failing gate and its concrete fix;
295
+ the flattering numbers come after. (Proven failure mode: "44/60 writing, ~88% accept" reported as
296
+ headlines on a paper whose readability + structure gates were failing — the human reader found it
297
+ exhausting while the scalars said ship.)
298
+
299
+ Then: the per-axis PASS / FIXED / OPEN report (each OPEN with the concrete fix), the **citability
300
+ levers landed** (coined handle + its one-sentence definition, the "first taxonomy/benchmark of X"
301
+ framing, the one quotable stat, the reusable artifact, any dry-humour line and where), and the short
302
+ list of items only the author can close (host artifact, click submit, disclose-before-public, post the
303
+ preprint). If every gate passes and every axis is PASS/FIXED → hand off to \`submit-paper\`.
304
+
305
+ ## Record the verdict
306
+
307
+ 🔴 LAST step, once the deliverable exists:
308
+
309
+ \`\`\`
310
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record harden-paper <paper-dir> FINDING <count> <report-path>
311
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record harden-paper <paper-dir> ABSTAINED <reason> "<one line>"
312
+ \`\`\`
313
+
314
+ **FINDING** — \`<count>\` is the number of failing gates plus still-OPEN axes and \`<report-path>\` the
315
+ worst-gate-first vector. Add \`--blocking\` when any gate in the vector fails, as opposed to an axis
316
+ merely being open.
317
+ **ABSTAINED** — \`no-witness\`: every gate answered and no axis is open, which is the state that hands
318
+ off to \`submit-paper\`. \`blocked\`: a gate in the vector has never been run, so the vector has a hole
319
+ in it and there is nothing to hand off.
320
+
321
+ 🔴 **There is no PASS, and this skill must not reinvent one.** Its whole design is that the verdict
322
+ is a VECTOR reported worst-gate-first, and a stored scalar acquittal was the single value that could
323
+ flatten it. \`no-witness\` here means every gate answered and none of them found anything — it is not
324
+ "ready", and the readiness call is a sentence a human writes in the report.
325
+
326
+ 🔴 **Never record the accept-probability as the count.** A single scalar hiding a multi-dimensional
327
+ failure is the exact thing this skill refuses to report in prose, and a ledger row is prose that
328
+ survives longer.
329
+
330
+ The artifact-coverage script files separately as \`harden-paper/artifact-coverage\`. One check, one row.
331
+
332
+ ## Composes with
333
+ \`tighten-paper\` (axis 0, run FIRST — structure before sentences), \`paper-adversarial-review\` +
334
+ \`pc-panel-review\` + \`verify-citations\` + \`grade-paper-writing\` (called by this), \`render-paper\` (if LaTeX
335
+ toolchain exists), \`submit-paper\` (downstream), \`extend-paper\` (the dropped refs / deferred axes live here).`,
336
+ });
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env bash
2
+ # check-numbers.sh — enumerate every quantitative token in the paper BODY so each can
3
+ # be traced to an artifact number or a \cite.
4
+ #
5
+ # WHY: a stray prose number that is in NEITHER the artifact NOR a citation slips every
6
+ # existing check (they scope to HEADLINE numbers only). This session: "the flagship's
7
+ # mean output change ranged from a 37% growth to an 18% cut across independent runs" —
8
+ # not in the artifact, uncited — was caught only by the PC-panel's artifact evaluator.
9
+ # Enumeration is mechanical; tracing each number stays judgment.
10
+ #
11
+ # Usage: check-numbers.sh <paper-dir> [texbasename=paper]
12
+ # Exit: always 0 (advisory — it lists, you trace).
13
+ set -uo pipefail
14
+ DIR="${1:?usage: check-numbers.sh <paper-dir> [tex=paper]}"
15
+ BASE="${2:-paper}"
16
+ cd "$DIR" || { echo "FAIL: cannot cd $DIR"; exit 2; }
17
+ [ -f "$BASE.tex" ] || { echo "FAIL: no $BASE.tex"; exit 2; }
18
+
19
+ echo "== number enumeration (body only): $DIR/$BASE.tex =="
20
+ echo " Trace each to an artifact output or a \\cite. An untraceable number = treat as fabricated (source it or cut it)."
21
+ # Drop the filecontents bib block, comment lines, and \cite/\bibliography lines; then
22
+ # list body lines that carry a quantitative token (%, a/b ratio, \$/x multiplier, or a 2+-digit number).
23
+ awk 'BEGIN{inbib=0}
24
+ /\\begin\{filecontents/{inbib=1}
25
+ /\\end\{filecontents/{inbib=0; next}
26
+ inbib{next}
27
+ /^[ \t]*%/{next}
28
+ /\\cite|\\bibliography/{next}
29
+ /[0-9]/{print NR": "$0}' "$BASE.tex" \
30
+ | grep -E '([0-9]+(\.[0-9]+)?[\\]?%|[0-9]+/[0-9]+|\$[0-9]|[0-9]+(\.[0-9]+)?[xX×]|[0-9][0-9,]{2,})' \
31
+ | sed 's/^/ /' | head -100
32
+ echo "-- review the list: every number above must appear in the artifact output or carry a citation --"
33
+ exit 0
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # check-release-claims.sh — reconcile "we release / provide X" PROSE claims against
3
+ # what the artifact ACTUALLY ships.
4
+ #
5
+ # WHY: this session a paper whose whole thesis was "advertised >> delivered" itself
6
+ # claimed "we release the harness and raw runs" while the artifact held only per-arm
7
+ # aggregates + an analysis script (harness at camera-ready). Only a late PC-panel
8
+ # caught it. Enumeration is mechanical; the reconcile (does file X satisfy claim Y?)
9
+ # stays human judgment. Spirit: prose isn't policy — compile the enumeration.
10
+ #
11
+ # Usage: check-release-claims.sh <paper-dir> [texbasename=paper] [artifact-subdir=artifact]
12
+ # Exit: always 0 (advisory — it lists, you reconcile).
13
+ set -uo pipefail
14
+ DIR="${1:?usage: check-release-claims.sh <paper-dir> [tex=paper] [artifact=artifact]}"
15
+ BASE="${2:-paper}"
16
+ ART="${3:-artifact}"
17
+ cd "$DIR" || { echo "FAIL: cannot cd $DIR"; exit 2; }
18
+ [ -f "$BASE.tex" ] || { echo "FAIL: no $BASE.tex"; exit 2; }
19
+
20
+ echo "== release-claim reconciliation: $DIR =="
21
+ echo "-- (1) PROSE claims (release verbs) — reconcile each against the artifact listing below --"
22
+ grep -nE 'we (release|provide|make available|ship|publish)|is (released|available)|available (at|:)|accompan|raw .*(runs|logs|data|rows)|the (harness|corpus|battery|dataset|artifact)( is| are|,| and| so)' "$BASE.tex" \
23
+ | grep -vE '^[0-9]+:[ \t]*%' | sed 's/^/ /' || echo " (no release-verb lines matched)"
24
+
25
+ echo "-- (2) what the artifact ACTUALLY contains ($DIR/$ART) --"
26
+ if [ -d "$ART" ]; then
27
+ find "$ART" -maxdepth 2 -type f 2>/dev/null | sed 's/^/ /' | head -40
28
+ else
29
+ echo " (no local $ART/ dir — hosted externally? then reconcile the claim against the HOSTED contents)"
30
+ fi
31
+
32
+ echo "-- CHECK: every 'we release X' in (1) must be satisfied by a file in (2)."
33
+ echo " Promised-but-absent (e.g. 'raw runs' but only aggregates shipped) -> soften to '(at camera-ready)' or add the file."
34
+ echo " Mirror the accurate Availability paragraph; do not let the abstract/conclusion over-promise the artifact."
35
+ exit 0
@@ -0,0 +1,43 @@
1
+ # Uncited-assertion fixture (markdown path)
2
+
3
+ Documents the `.md` behaviour of the uncited-assertion checker. Keep in the repo (it IS the contract).
4
+ <!-- Since 2026-08-27 the checker is the ESLint rule `paper/uncited-assertion`
5
+ (`eslint-rules/paper-claims.mjs`); this file is its test — see `eslint-rules/paper-claims.harness.mjs`. -->
6
+
7
+ Transformers outperform RNNs by 12%.
8
+ <!-- MUST FLAG: uncited empirical claim about prior work -->
9
+
10
+ Transformers outperform RNNs by 12% [@vaswani2017].
11
+ <!-- MUST NOT FLAG: pandoc [@key] citation attached -->
12
+
13
+ Prior work reports a large improvement over baselines.[^1]
14
+ <!-- MUST NOT FLAG: markdown footnote marker counts as a citation -->
15
+
16
+ The majority of detectors fail on adversarial inputs, per a recent survey ([link](https://example.org/survey)).
17
+ <!-- MUST NOT FLAG: markdown link/URL counts as a citation -->
18
+
19
+ Most prior detectors silently miss adversarial inputs.
20
+ <!-- MUST FLAG: bare fuzzy quantifier, no citation -->
21
+
22
+ We observe a 6% reduction in false positives.
23
+ <!-- MUST NOT FLAG: paper's own result (we-guard) -->
24
+
25
+ Transformers outperform RNNs by 12% [12].
26
+ <!-- MUST NOT FLAG (S6): numeric citation [12] counts as a cite -->
27
+
28
+ Prior detectors reduce error by 20% [3, 4].
29
+ <!-- MUST NOT FLAG (S6): citation list [3, 4] counts -->
30
+
31
+ US-based detectors reject 40% of benign inputs.
32
+ <!-- MUST FLAG (S5): bare country "US" is not the paper's own result -->
33
+
34
+ Our reading of the literature shows transformers outperform every prior baseline.
35
+ <!-- MUST FLAG (S5): claim about OTHERS, "our reading" is not an own result -->
36
+
37
+ Our method reduces false positives by 6% over the strongest baseline.
38
+ <!-- MUST NOT FLAG (S5): genuine own result, "our method" is the subject -->
39
+
40
+ 2. Prior detectors silently miss most adversarial inputs.
41
+ <!-- MUST FLAG (S10): ordered-list marker "2." must not be a false boundary / stray number; the claim itself still flags -->
42
+
43
+ [^1]: Some prior study, 2021.
@@ -0,0 +1,77 @@
1
+ % fixtures/uncited-assertions-sample.tex
2
+ % Contract fixture for the uncited-assertion checker — documents exactly what MUST and MUST NOT flag.
3
+ % Since 2026-08-27 that checker is the ESLint rule `paper/uncited-assertion` (eslint-rules/paper-claims.mjs);
4
+ % this file is its test, run by eslint-rules/paper-claims.harness.mjs.
5
+ % Each numbered case is annotated with the expected verdict. Keep in the repo (it IS the contract).
6
+ \documentclass{article}
7
+ \begin{document}
8
+
9
+ % (1) MUST FLAG — uncited empirical claim about prior work (percentage + verb, no cite, no "we").
10
+ Transformers outperform RNNs by 12\%.
11
+
12
+ % (2) MUST NOT FLAG — same claim, now carrying a citation.
13
+ Transformers outperform RNNs by 12\% \cite{vaswani2017}.
14
+
15
+ % (3) MUST NOT FLAG — float pointer; the verb refers to a Table, not to prior work.
16
+ Table 2 shows the aggregated results across all runs.
17
+
18
+ % (4) MUST NOT FLAG — the only number is a year (year guard).
19
+ In 2026, the field continued to attract new benchmarks.
20
+
21
+ % (5) MUST NOT FLAG — the paper's OWN reported result (we/our guard); numbers allowed uncited.
22
+ We find a 6\% reduction in false positives (p<0.05) over the baseline.
23
+
24
+ % (6) MUST NOT FLAG — a definition sentence, even though it contains a number.
25
+ A transformer block is defined as a stack of 6 attention sub-layers.
26
+
27
+ % (7) MUST NOT FLAG — version-number guard (v2.1) and a math-mode number ($n = 512$) both skipped;
28
+ % no "we", so this isolates the version + math guards (no empirical signal survives).
29
+ The baseline model ships as release v2.1 with a hidden size of $n = 512$.
30
+
31
+ % (8) MUST FLAG — bare fuzzy quantifier making a claim about prior work, no cite.
32
+ Most prior detectors silently miss adversarial inputs.
33
+
34
+ % ── regression cases for the adversarial-review fixes (S5–S10) ──────────────────
35
+
36
+ % (S6) MUST NOT FLAG — numeric-style citation [12] is a citation (dominant CS style).
37
+ Transformers outperform RNNs by 12\% [12].
38
+
39
+ % (S6b) MUST NOT FLAG — citation range/list [3, 4] and [1]--[3] both count.
40
+ Prior detectors reduce error by 20\% [3, 4].
41
+
42
+ % (S7) MUST NOT FLAG — biblatex \footcite is a citation macro.
43
+ Prior work improves accuracy by 15\% \footcite{smith2020}.
44
+
45
+ % (S7b) MUST NOT FLAG — \citeauthor / \parencite are citation macros too.
46
+ \citeauthor{jones2019} shows a 9\% reduction over the baseline \parencite{jones2019}.
47
+
48
+ % (S8) MUST NOT FLAG — "cf." must NOT sever the trailing \cite into its own segment.
49
+ RNN baselines underperform on long sequences, cf. \cite{vaswani2017}.
50
+
51
+ % (S8b) MUST NOT FLAG — "e.g." before a capital must not break the sentence off its cite.
52
+ Several detectors miss adversarial inputs, e.g. Gradient attacks \cite{goodfellow2015}.
53
+
54
+ % (S9) MUST NOT FLAG — float pointer via \ref-macro (no literal digit); verb refers to a Table.
55
+ Table~\ref{tab:results} shows the aggregated numbers across all runs.
56
+
57
+ % (S9b) MUST NOT FLAG — \autoref / \Cref float pointers, verb-only.
58
+ \Cref{fig:overview} demonstrates the pipeline end to end.
59
+
60
+ % (S10) MUST NOT FLAG — tabular body: numeric rows are data, not a prose claim.
61
+ The results appear below.
62
+ \begin{tabular}{lll}
63
+ Model & Acc & F1 \\
64
+ BERT & 0.91 & 0.89 \\
65
+ GPT & 0.94 & 0.93 \\
66
+ \end{tabular}
67
+
68
+ % (S5) MUST FLAG — bare country "US" must NOT be read as the paper's own result ("us").
69
+ US-based detectors reject 40\% of benign inputs.
70
+
71
+ % (S5b) MUST FLAG — "Our reading of the literature" is a claim about OTHERS, not an own result.
72
+ Our reading of the literature shows transformers outperform every prior baseline.
73
+
74
+ % (S5c) MUST NOT FLAG — genuine own result: "our method" is the subject.
75
+ Our method reduces false positives by 6\% over the strongest baseline.
76
+
77
+ \end{document}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * harden-paper — the PAID tier: does this skill's description actually fire?
3
+ *
4
+ * COLOCATED ON PURPOSE (vigiles decides coverage by placement as of 2026-08-11).
5
+ * The prompts live in `.claude/lib/skill-trigger-cases.mjs` so all 21 cases
6
+ * are reviewed as one table where collisions between siblings are visible;
7
+ * copying them here would recreate the drift that rule exists to prevent.
8
+ *
9
+ * Measures recall (fires on its own territory) AND precision (stays quiet on a
10
+ * colliding sibling's territory), against the REAL `.claude` harness so the skill
11
+ * competes with every other installed description — an isolated run overstates
12
+ * recall and understates false positives.
13
+ *
14
+ * Costs money; not CI.
15
+ * node .claude/skills/harden-paper/harden-paper.eval.mjs [trials]
16
+ */
17
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
18
+
19
+ await runSkillTriggerEval("harden-paper");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * harden-paper — the free, deterministic tier. No model, no network.
3
+ *
4
+ * COLOCATED ON PURPOSE. vigiles decides coverage by PLACEMENT as of 2026-08-11:
5
+ * a test that merely names a surface no longer counts, because that tier was
6
+ * crediting surfaces nothing touched. So each skill needs a file inside its own
7
+ * directory — this one.
8
+ *
9
+ * The assertions live in `.claude/lib/skill-checks.mjs` and are CALLED here with
10
+ * this skill's name. They are not copied: 22 copies of the same checks is the drift that
11
+ * module exists to avoid. (Until 2026-08-11 this was an env-var side channel into a
12
+ * 614-line file named after no surface; it is a function call now.)
13
+ *
14
+ * What this proves: this skill's frontmatter parses as strict YAML, its declared
15
+ * tool contract is sane, its pipeline wiring points at scripts that exist, and it
16
+ * announces/records under ITS OWN identity rather than a sibling's.
17
+ *
18
+ * What it does NOT prove: that the skill fires, or that its guidance produces a
19
+ * good result. Those need a real model — see `harden-paper.eval.mjs`.
20
+ */
21
+ import { checkSkill } from "../../lib/skill-checks.mjs";
22
+
23
+ await checkSkill("harden-paper");