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,517 @@
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: "paper-pipeline",
11
+ description:
12
+ "The orchestrator for writing a research paper end-to-end, from idea to accepted-and-extended, with every stage graded for the credit it earns a body of work. START HERE when writing/hardening a paper (AgenticDev, AISec, and future ones) and want the whole lifecycle driven, not one step. Routes to the stage skills — research-ideate, find-venue, plan-paper-timeline, build-benchmark, draft-paper, render-paper, verify-citations, the review skills, submit-paper (+ venue cards), camera-ready, extend-paper — and owns the shared references.",
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
+ # paper-pipeline — the conductor for the whole organism
27
+
28
+ This is the entry point. Each lifecycle stage is its own skill; this routes through them in order and
29
+ owns the shared reference docs the others cite. **These papers are written to COUNT as credentials** —
30
+ every stage is graded against \`references/credit-criteria.md\`, not abstract "impact." The personal half
31
+ of that — who is filing what, and when — stays in the author's own private notes, never in a public repo.
32
+
33
+ ## Shared references (single source of truth — all skills cite these)
34
+ - \`references/credit-criteria.md\` — which criteria a paper feeds; where venue quality bites; the
35
+ decisions credit value forces on the pipeline.
36
+ - \`references/artifact-checklist.md\` — the self-checking reproduction artifact.
37
+ - \`references/anonymization.md\` — the double-blind deny-list + hygiene (and its reverse at camera-ready).
38
+ - \`references/writing-craft.md\` — how well-written papers read (craft rules + exemplar lessons + the
39
+ gradeable 9-dim writing rubric); cited by \`draft-paper\`, \`grade-paper-writing\`, and \`harden-paper\`.
40
+ - \`references/review-ratchet.md\` — how to fix a caught overclaim (tighten → cut → Threats → hedge)
41
+ and why every review round must be paid back with a \`tighten-paper\` pass; cited by
42
+ \`paper-adversarial-review\`, \`pc-panel-review\`, \`harden-paper\`.
43
+ - \`references/pipeline-status-template.md\` — the per-paper **readiness scorecard** (which stages ran,
44
+ grades, open findings, submit-ready verdict). Copied into \`<paper-dir>/PIPELINE-STATUS.md\`.
45
+ - \`references/acl-venue-rules.md\` — what holds at **every** ACL-family venue and workshop: the
46
+ page-limit map, the appendix rule and the trap inside it, Limitations/Ethics as free-but-restricted
47
+ space, anonymity, OpenReview mechanics. Fetch once, not per paper. Venue-specific facts stay in
48
+ \`submit-paper/references/venues/<venue>.md\`. (No equivalent yet for ACM or IEEE — write one when
49
+ the next paper goes there.)
50
+
51
+ ## The readiness scorecard (which boxes are checked)
52
+ Stages run in subagents and report into chat, which evaporates — so "did everything run?" becomes
53
+ unanswerable. Fix: every paper carries a **\`<paper-dir>/PIPELINE-STATUS.md\`** (template in
54
+ \`references/pipeline-status-template.md\`), the durable colocated source-of-truth for *which stages ran,
55
+ their grade/result, what's open,* and a one-line **submit-ready verdict**. Rules:
56
+ - **When any stage runs (here or in a subagent), update its row in the same commit** — status, date,
57
+ result, open findings, artifact link. The scorecard is only trustworthy if it's kept live.
58
+ - **Never inflate:** a stage not run *this* cycle is \`☐\`, even if a prior submission ran it — don't
59
+ borrow credit you can't point to. Approximate/from-memory grades get \`≈\`.
60
+ - **"Is paper X ready / what's checked?"** = read this file (verdict + any \`☐\`/\`◐\`/\`⚠\` rows), don't
61
+ reconstruct from chat.
62
+ - Distinct from \`SUBMIT-CHECKLIST.md\` (venue-format compliance); both must be green before upload.
63
+ - 🔴 **Enforcement leg (prose-isn't-policy), and it is a script, not a paragraph.**
64
+ \`scripts/pipeline-check.mjs\` reads this file on every paper edit and reports the failures that
65
+ actually happened on real papers: a CONTINUOUS check whose last run predates the current text, a GATE
66
+ that ran without its required input, **a \`Requires\` cell that omits an edge the pipeline declares**
67
+ (the canonical set is \`scripts/pipeline-edges.mjs\`, with the admitting sentence per edge), a study
68
+ that ran with no stated claim, the \`access\` row not green inside the moderation window, and a verdict
69
+ line that is just an accept probability. Run it directly
70
+ with \`node .claude/skills/paper-pipeline/scripts/pipeline-check.mjs <paper-dir>\`; it is wired into
71
+ \`.claude/hooks/paper-status-gates.sh\` and asserted in \`.claude/hooks/hooks.harness.mjs\`.
72
+ **The grading itself stays judgment** (that is the skills' job) — only the mechanically checkable
73
+ parts are compiled. *Added 2026-08-03, the day three hooks in this repo were found to have been dead
74
+ for weeks: an advisory that is never exercised is indistinguishable from one that works.*
75
+
76
+ 🔴 **As of 2026-08-26, this file is read by TWO things.** Sixteen checks over it live as
77
+ \`@eslint/markdown\` rules in \`eslint-rules/pipeline-status.mjs\` (run:
78
+ \`npx eslint <paper-dir>/PIPELINE-STATUS.md\`; five of them are \`error\`), while
79
+ \`scripts/pipeline-check.mjs\` holds six whose input lies OUTSIDE the file — git, the clock, the
80
+ \`reviews/\` directory, \`process.env\`. The classification of all 22 lives in the
81
+ author's private notes (\`<papers-root>/research/2026-08-26-klassifikatsiya-pipeline-check.md\`).
82
+
83
+ ⚠️ The paragraph above lived for a day NOT HERE but directly in \`SKILL.md\` — i.e. in the
84
+ generated file. The very first \`vigiles compile\` (27.08) ate it, and it was not a human who
85
+ noticed but an agent whose compile had just erased someone else's edit. **An edit to \`SKILL.md\`
86
+ without \`.spec.ts\` is an edit with an expiration date: the next compile.**
87
+
88
+ ## 🗺️ Where every check actually runs — and where it can be walked around
89
+
90
+ \`\`\`
91
+ YOU EDIT YOU COMMIT YOU BUILD YOU PUSH
92
+ │ │ │ │
93
+ ▼ ▼ ▼ ▼
94
+ ┌──────────────┐ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐
95
+ │ PostToolUse │ │ .githooks/ │ │ build- │ │ GitHub Actions │
96
+ │ paper-lint │ BLOCKS │ pre-commit │REFUSES│ submission.sh │ │ paper-gates │
97
+ │ pre >55 wds │ │ │ │ │ │ │
98
+ │ paper-lint │ nudges │ numbers gate │ │ numbers gate │REFUSES numbers+self│
99
+ │ post │ │ │ │ │ │ │
100
+ │ prose-lint │ │ prose-lint │ nudge │ page count │ │ prose-lint │
101
+ │ SHAVE │ │ self-test if │ │ overfull │ │ check-anon │
102
+ │ numbers │ │ you touched │ │ unresolved │ │ verify-cites │
103
+ │ paper-edit- │ BLOCKS │ a gate │ │ refs │ │ provenance │
104
+ │ guard │ bash │ harness if │ │ dropped glyphs│ │ scorecard │
105
+ └──────────────┘ │ you touched │ │ anon grep │ │ harness │
106
+ │ │ a hook │ └────────────────┘ │ LaTeX build │
107
+ │ │ RAW DNA │REFUSES │ └────────────────┘
108
+ │ └────────────────┘ │ │
109
+ │ │ │ │
110
+ watches EVENTS watches STATE watches OUTPUT watches EVERYTHING
111
+ (Edit/Write fired) (what is staged) (the actual PDF) (after the fact)
112
+ │ │
113
+ │ │
114
+ 🕳 BYPASSABLE: 🛡 NOT bypassable by that route: it does not care
115
+ write from Bash and HOW the bytes got there. However you wrote the
116
+ no event fires, so file, you still have to commit it.
117
+ every PostToolUse
118
+ check silently
119
+ does not run.
120
+ \`\`\`
121
+
122
+ **Read the bottom row, it is the whole point.** Each column watches a different KIND of thing, and
123
+ that is why they are not three copies of one check:
124
+
125
+ - **Editor hooks watch events.** Fast, and the only layer that can stop a bad edit *before* it lands.
126
+ Bypassable by construction — an event that never fires cannot be checked, and writing the file from
127
+ Bash produces no event. Documented in \`papers/CLAUDE.md\`, open since 2026-08-04.
128
+ - **The git hook watches state.** Immune to that whole class, because it reads what is staged and has
129
+ no opinion about how it got staged. This is the layer that was missing, and the one to reach for
130
+ when an editor check turns out to be walkable-around.
131
+ - **The build watches output.** Only it can see page count, overfull boxes, and glyphs pdflatex
132
+ silently dropped — none of which exist until the PDF does.
133
+ - **CI watches everything, but after the fact.** Its real job is the slow checks nobody will wait for
134
+ locally (the anonymity self-test copies a 24 MB bundle per leak category) and the self-tests, which
135
+ are what catch a gate that has quietly stopped catching things.
136
+
137
+ 🔴 **A fifth kind, and none of the four columns can see it: does the MODEL call these skills at all?**
138
+ Every column above watches something the repository produced — an event, staged bytes, a PDF, a commit.
139
+ None watches *selection*: whether a real model, reading 37 competing descriptions, picks \`tighten-paper\`
140
+ over \`grade-paper-writing\` when the draft is bloated. A harness test proves a skill works once invoked;
141
+ it cannot prove it gets invoked. That needs the real CLI and it costs money, so it is a measurement, not
142
+ a gate — \`.claude/skills/paper-pipeline/pipeline-firing.eval.mjs\`, run manually or by the weekly
143
+ \`skill-firing\` job (\`workflow_dispatch\` + \`schedule\`, deliberately NOT on push). It installs every skill
144
+ in this repo natively so selection is *competitive*, feeds each skill 4 prompts it should fire on plus 4
145
+ its colliding sibling owns, and reports recall / false-positive / precision per skill against a committed
146
+ baseline. **What it measures drifts without a commit here** — a model update can change routing while
147
+ every file stays byte-identical, which is exactly the regression no check in the diagram can see.
148
+ Prior art is named in the file header (\`adewale/skill-eval-harness\` does this too); the idea is not ours.
149
+
150
+ 🔴 **Still manual, and no mechanism has been found for it:** the **cold read** — a reader with no
151
+ context restating each sentence — is the only check that catches a sentence that is short, true,
152
+ threshold-passing and meaningless. It needs a fresh subagent, so no hook can run it. What IS
153
+ mechanised is noticing that it is *overdue*: \`pipeline-check.mjs\` reports \`stale-cold-read\` when the
154
+ prose changed after the last one.
155
+
156
+ Install the git hook once per clone: \`git config core.hooksPath .githooks\`.
157
+
158
+ ## 🔴 There is no stage 7. Four kinds of work, four shapes.
159
+
160
+ **This section replaced a single numbered list running 0 → 12, on 2026-08-03.** That list had a
161
+ paragraph on top explaining that the numbers were dependencies rather than turns — and underneath it,
162
+ a table numbered straight through, which every reader (including this pipeline's own author) read as a
163
+ waterfall. The paragraph was the tell: a document that needs a disclaimer explaining how not to read
164
+ it is mis-shaped, and the fix is to change the shape, not to add a second disclaimer. That is the
165
+ argument \`compile-rules-2026\` makes about instruction files, applied here.
166
+
167
+ Three concrete errors the numbering produced, all real:
168
+
169
+ - **\`verify-citations\` sat at 7**, looking like a one-shot step, while the project rule is that it runs
170
+ every cycle — an edit on the last day adds a \`\\cite\` that "we checked last cycle" does not cover.
171
+ - **\`render-paper\` sat at 6**, as a stage. It is a command you run twenty times a day.
172
+ - **\`map-prior-work\` sat at 1.5** and its own description told you to re-run it as a cheap delta before
173
+ submit — so it was simultaneously a stage and a continuous check, and the table could only show one.
174
+
175
+ Work is now grouped by **how it runs**, and only the groups that are genuinely ordered carry an order.
176
+
177
+ | kind | shape | how to read it |
178
+ |---|---|---|
179
+ | **SETUP** | ordered | Each genuinely gates the next. Runs once, before the study is malleable. |
180
+ | **LOOP** | unordered cycle | Draft ↔ study ↔ arc ↔ review. No numbers, because there are no turns. |
181
+ | **CONTINUOUS** | trigger table | Fires when the thing it checks changes. Never "done". |
182
+ | **GATES** | ordered by input | Late, expensive, each hard-blocked on a named input. |
183
+
184
+ ---
185
+
186
+ ## SETUP — once, before anything is expensive to change
187
+
188
+ Ordered, because each really does gate the next. Two pairs run in parallel; that is marked.
189
+
190
+ | Step | Skill | What it settles |
191
+ |---|---|---|
192
+ | **Orient** | — | Read \`<papers-root>/HANDOFF.md\` + \`<papers-root>/research/README.md\`. Never restart from scratch. |
193
+ | **Validate the idea** | **\`research-ideate\`** | Is it a reusable method (survives review) in your lane, and does it feed the credit criteria? Go/no-go + the MVP finding. |
194
+ | **Map the competition** ‖ | **\`map-prior-work\`** | 🔴 **Who already did this?** Multi-angle sweep; date each hit against your submission (5 months = prior, not concurrent); triage by which layer of your claim it threatens; deep-read the dangerous ones. Output: **what you can still claim** + a related-work skeleton. *Added 2026-07-27 after a five-month-older paper surfaced at T−10 days on a finished draft.* |
195
+ | **Pick the venue** ‖ | **\`find-venue\`** | Rank by credit-weight (peer-reviewed + indexed) × fit × accept-odds × deadline × remote. |
196
+ | **Learn the venue's bar** | **\`study-accepted-papers\`** | 🔴 **What does an ACCEPTED paper look like HERE?** Measure the venue's whole accepted volume, deep-read 8–12 of your contribution type, and extract what made them strong: evidence scale, figures, artifact release, how the abstract is built. File the venue card (\`submit-paper/references/venues/<venue>.md\`) and confirm family rules (\`references/acl-venue-rules.md\`). *Promoted to its own step 2026-08-03: on \`compile-rules-2026\` every judgement of the paper's quality — rubric, persona, simulated panel, accept probability — came from instruments this pipeline itself generated, with no external grounding, and the author had to say so at T−3 days. A closed loop optimises against its own model of a reviewer.* |
197
+ | 🔴 **Can you physically submit?** | **\`plan-paper-timeline\`** | **The step that owns the question no stage used to own.** Create the portal account NOW; drive the profile to **ACTIVE**, not "pending moderation"; confirm the form's fields and the artifact-hosting requirement. OpenReview moderation runs **up to two weeks**, and an author with no institutional email has no expedite route. Scorecard row \`access\`. *Added 2026-08-03, when this was the sole critical-path item on a finished paper at T−4 days: the science was done and there was nowhere to put it.* |
198
+ | **Schedule it** | **\`plan-paper-timeline\`** | Deadlines → calendar with buffers, in the author's own zone (AoE − 12h ≠ your clock). Space papers apart. |
199
+ | 🔴 **State the claim** | **\`argument-arc\`** (frame mode) | **One paragraph: what will this paper claim, and what would have to be true?** Before any run. The frame decides which results matter, and reframing after the data is collected is how experiments get thrown away — observed on \`compile-rules-2026\`, and the reason \`argument-arc\` has a rebuild mode at all. Costs a paragraph; saves a study. Scorecard row \`frame\`. |
200
+
201
+ ## LOOP — iterates until it settles
202
+
203
+ No numbers. Nothing here happens once, and nothing here is "next".
204
+
205
+ \`\`\`
206
+ study ──────────► draft
207
+ build-benchmark draft-paper
208
+ ▲ │
209
+ │ ▼
210
+ argument-arc ◄──── the arc
211
+ (rebuild mode) 5.5 verdict
212
+ \`\`\`
213
+
214
+ - **\`build-benchmark\`** — a design that inverts the pitfall; honest stats; a self-checking artifact
215
+ (\`references/artifact-checklist.md\`).
216
+ - **\`draft-paper\`** — section skeleton + the accept-and-get-cited properties
217
+ (\`references/writing-craft.md\`).
218
+ - **\`argument-arc\`** — 🔴 **does the draft carry the reader to ONE conclusion?** One sentence per
219
+ section (*what does the reader now believe*), then a bottom-up pass asking whether each section makes
220
+ the conclusion harder to escape. Owns **rebuild mode**: the only protocol here for *the frame is
221
+ wrong, start the arc over*. Every other gate assumes a settled draft and patches it. *Added
222
+ 2026-07-30 after a full-day rewrite in which the author said five times that the paper threw ideas at
223
+ him and got five local edits back.*
224
+
225
+ **Leaving the loop** means the arc holds and the numbers are in. Not that the prose is pretty — that
226
+ is what the gates are for.
227
+
228
+ ## CONTINUOUS — fires when its input changes, never "done"
229
+
230
+ These have no position, because a position is what made them look finished. Each is a trigger.
231
+
232
+ | When this changes | Run | Why it cannot be a stage |
233
+ |---|---|---|
234
+ | any \`\\cite\` added or moved | **\`verify-citations\`** | An edit on the last day adds a citation the last run never saw. "We checked last cycle" does not count — the project rule, and it was numbered as a one-shot anyway. |
235
+ | a genuine sibling surfaces | **\`analyze-sibling-paper\`** | Deep-read, scoop/delta, saved in \`<paper-dir>/siblings/\`. |
236
+ | the contribution's framing moves | **\`map-prior-work\`** (delta mode) | A cheap re-sweep. ⚠️ If a rival first surfaces during citation checking, the SETUP sweep was skipped and you are reshaping the contribution under deadline. |
237
+ | any \`.tex\` / \`paper.md\` edit | **\`render-paper\`** + page count | **Not a stage — a command.** Render, then eyeball pages 1–2 before believing anything about the paper. 🔴 **Rendering is continuous; ACTING on the page count is not** — see the rule below. |
238
+ | the deadline approaches | the \`access\` row | Re-check that the profile is still ACTIVE and the portal still opens. External state rots without telling you. |
239
+
240
+ ## GATES — late, expensive, each blocked on a named input
241
+
242
+ Ordered, and the order is real: every one refuses to run without the output of the one before it.
243
+
244
+ | Gate | Skill | Requires (hard) |
245
+ |---|---|---|
246
+ | **Structure** | **\`tighten-paper\`** | A rendered PDF and a page count. Produces the cut plan + structural verdict. *Before 2026-07-30 this appeared only INSIDE the harden stage — i.e. after the gate that requires it — so a literal reading sent you into a hard-blocked gate.* |
247
+ | **Writing craft** | **\`grade-paper-writing\`** | The current draft. Produces the **persona stall inventory**, which the panel cannot run without. |
248
+ | **Review decision** | **\`pc-panel-review\`** | 🔴 **Both of the above.** N independent lenses (incl. an artifact-runner that executes the artifact) + a chair meta-review — predicts the PC's accept/reject. Its venue-fit mode is the one-reviewer CFP-fit spot-check. |
249
+ | **Claim preservation** | Fable diff (\`claims\`) | The pre-pass baseline. Run after **every** aggressive rewrite, before committing. |
250
+ | **Harden** | **\`harden-paper\`** | The panel's verdict. Closes the desk-reject axes a reviewer-sim misses: threat-model, ethics/dual-use, page-fit, citability, double-blind hygiene, artifact-runs-clean. Its structure and writing axes are the **re-run/confirm** pass, not the first invocation. |
251
+ | **Submit** | **\`submit-paper\`** (+ the venue card) | 🔴 **The \`access\` row green.** Portal mechanics, PDF-only, artifact hosted anonymously, "ready for review" marked. |
252
+
253
+ ## AFTER — only reachable by acceptance
254
+
255
+ **\`camera-ready\`** — de-anonymize; public repo + archival DOI; complete disclosure. Then
256
+ **\`extend-paper\`** — extend (≥30% new) to a higher-prestige venue, the "second, stronger publication."
257
+
258
+ **Which review skill?** \`paper-adversarial-review\` = one hostile reviewer, fast defect hunt;
259
+ \`pc-panel-review\` = the full panel + meta-review that makes the accept/reject **decision** (its
260
+ **venue-fit mode** is the one-reviewer CFP-fit spot-check — formerly the standalone \`venue-review-sim\`).
261
+ Use an atom for a quick spot-check; **run the panel for the decision.**
262
+
263
+ **Four grading axes — don't confuse them.** A draft is judged on four independent axes, each its own
264
+ skill: 🔴 **argument architecture** — does the whole thing carry the reader to one conclusion
265
+ (\`argument-arc\`, in the LOOP; the axis that failed on \`compile-rules-2026\` precisely because it was
266
+ nobody's) · **content strength** — does the contribution clear *this venue's* bar (\`study-accepted-papers\`,
267
+ mines the accepted corpus for Accept→Strong levers; in SETUP, before the prose is set) ·
268
+ **scientific defects** — what a hostile reviewer attacks (\`paper-adversarial-review\` / \`pc-panel-review\`)
269
+ · **writing craft** — does it read like a human wrote it (\`grade-paper-writing\`, the 9-dim rubric in
270
+ \`references/writing-craft.md\`; called by \`harden-paper\`). A paper can ace one and fail another — grade all four.
271
+ **The arc axis comes first**, because tightening length and polishing sentences inside a broken arc is
272
+ how a day disappears and the same paper ships.
273
+
274
+ **Panel vs harden — not rival gates, they're sequential.** \`pc-panel-review\` is the review DECISION
275
+ gate: it predicts what the PC does. \`harden-paper\` is the pre-submit ORCHESTRATOR: it *calls* the review
276
+ skills and then closes the desk-reject axes a reviewer-sim doesn't systematically hit (threat-model,
277
+ ethics/dual-use, page-fit, citability, double-blind hygiene). Order is **review (decide) → harden (close
278
+ every other axis) → submit** — neither is "the one final gate" alone.
279
+
280
+ ## The review round (a cycle inside GATES)
281
+ Review → **apply the consensus fixes → re-run the panel to confirm**. The artifact-runner re-executes
282
+ the artifact each round. Stop when the panel converges to accept and the artifact reproduces clean —
283
+ **don't loop past one confirming round**, and don't chase the last notch into the deadline. A defensible
284
+ **Accept shipped on time beats a risky Strong that misses it**.
285
+
286
+ ## 📝 Text pass vs evidence pass — two independent axes, ask which one you want
287
+
288
+ The author, 2026-08-05 (translated from Russian): *"can we just run the gate on the text? we just
289
+ checked the numbers, and now I want to grade the text — assume the numbers are fine."* He is right that these are separable, and
290
+ running both when only one is wanted burns an hour for nothing.
291
+
292
+ Every gate belongs to exactly one axis. **Sort by what invalidates it**, not by what it reads:
293
+
294
+ | axis | invalidated by | gates |
295
+ |---|---|---|
296
+ | **TEXT** — does the argument land? | a change to the **prose**: any edit, cut, reorder | \`structure\` tighten-paper · \`writing\` grade-paper-writing · \`arc\` argument-arc · the prose lenses of \`panel\` pc-panel-review |
297
+ | **EVIDENCE** — is it true? | a change to the **data, code, or artifact** | \`claims\` claim-preservation · \`cites\` verify-citations · \`artifact\` the artifact-runner lens · the numeric half of \`harden\` harden-paper |
298
+
299
+ **Why this matters more than it looks.** The two axes expire on completely different clocks. Rewriting
300
+ a paragraph invalidates every TEXT gate and no EVIDENCE gate. Re-running an experiment does the exact
301
+ reverse. Conflating them produces both classic wastes: re-verifying numbers nobody touched, and — worse
302
+ — trusting a readability verdict on prose that has since been rewritten.
303
+
304
+ **Text-only pass** (the common request, and the right default after a cut, a reorder, or a rewrite where
305
+ the numbers did not move): run \`structure\` and \`writing\` in parallel, then \`panel\` with its artifact lens **explicitly
306
+ disabled**, and hand each agent the sentence *"assume every number is correct and already verified — do
307
+ not re-derive anything; judge the writing, the structure and the argument."* Roughly halves the wall
308
+ clock and removes the single most expensive stage.
309
+
310
+ **Evidence-only pass** is the mirror: a new experiment landed, the prose around it is stable. Run \`claims\`
311
+ and the artifact-runner; skip readability entirely.
312
+
313
+ 🔴 **State which pass you ran, in the scorecard row and in the reply.** A gate row that does not say
314
+ which axis it covered will be read as covering both — which is how a paper ends up believed to be
315
+ checked on a dimension nobody looked at.
316
+
317
+ ### 🔢 The one defect neither axis can see: a number correct on both axes and wrong anyway
318
+
319
+ **Observed 2026-08-05, on page 1, 29 hours before a deadline.** The abstract read *"147 real rules
320
+ files exactly as their projects committed them, 22 fail admission"*. The data has two arms over the
321
+ same 147 files: **strict** (files byte-for-byte as committed — nothing fails) and **annotated** (the
322
+ same files with the tool's proposed pointers written in — 22 fail). The 22 was from the annotated arm
323
+ and was described in the strict arm's words. Five more numbers had the same defect; a sixth was found
324
+ later in an appendix by machine, after two people had searched by hand.
325
+
326
+ **Every gate passed, and each for a good reason.** \`cites\` checks the reference is real. \`claims\` checks the
327
+ claim did not grow — and it did not, 22 was always 22. The artifact-runner recomputes the number from
328
+ the data and it reconciles, *because the number is correct*. The reading panel takes "unmodified" as a
329
+ fact about the world, which is what a reader does. **The defect lives only in the join between a
330
+ sentence and a field path, and nothing was holding both.** It is not a TEXT defect and not an EVIDENCE
331
+ defect; it is a defect of the edge between them, so no pass on either axis can be made to see it.
332
+
333
+ **The construction, not another pass.** A registered quantity is not written as digits at all:
334
+
335
+ \`\`\`
336
+ Over {{corpus.n}} real rules files, with the extractor's proposed mapping
337
+ taken as if an author had written it, {{annotated.failedContradicted}} fail admission.
338
+ \`\`\`
339
+
340
+ \`<paper>/repro/numbers.tsv\` gives each name its value, the JSON path or **formula** that recomputes
341
+ it, and two guards. The build refuses a PDF unless: the name resolves · the value still matches the
342
+ data · the **paragraph** names the arm (\`requires\`) · the **sentence** does not claim a different one
343
+ (\`forbids\`). Requires and forbids are separate on purpose — the pairing is auditing's, where a control
344
+ is tested once for *design* and once for *operating effectiveness*.
345
+
346
+ **Why paragraph for one and sentence for the other.** *"Every figure in this paragraph is the
347
+ counterfactual arm"* is good writing, and a sentence-scoped \`requires\` would forbid it. But *"exactly
348
+ as committed"* nine words from the number is the defect itself, so \`forbids\` has to be tight.
349
+
350
+ **Coverage without a migration.** \`numbers-grandfathered.txt\` lists every quantity that predates the
351
+ gate; adding a new raw one fails the build. This is \`ADD CONSTRAINT ... NOT VALID\` — the constraint
352
+ binds every row from now on, and the existing rows are *enumerated rather than exempted*, so the file
353
+ says out loud how many figures still have no machine-checked path to data. On the paper that has it:
354
+ 7 guarded, 248 grandfathered. That ratio is a finding, not a score.
355
+
356
+ **Adopting it in another paper:** copy \`repro/paper_numbers.py\`, \`repro/paper_numbers.selftest.py\` and
357
+ the three lines in \`md2submission.py\` that call \`expand()\`; generate the grandfather list from the
358
+ current draft; register the numbers a reviewer will actually check first. \`check-provenance.mjs\`
359
+ reports \`no-numbers-gate\` for any paper that has not.
360
+
361
+ 🔴 **Do not write the substitution half — it is \`jinja2\`, and \`{{name}}\` is already its syntax.**
362
+ Eleven candidates were installed and run on a real markdown-source ACL paper on 2026-08-05. The
363
+ result is not a matter of taste:
364
+
365
+ | candidate | verdict, from an actual run |
366
+ |---|---|
367
+ | **jinja2** | **adopt.** Our \`{{annotated.failRate}}\` was already valid Jinja2; dotted names are attribute access. Zero characters changed in the paper, byte-identical \`.tex\`. This is Manubot's mechanism, taken without Manubot. Use \`StrictUndefined\`, and move the block/comment delimiters off \`{%\`/\`{#\` if the paper might ever quote a config file |
368
+ | **knitr** | equally proven, also byte-identical. Rejected only for putting an R runtime into an artifact that otherwise needs \`python3\` + \`pdflatex\` |
369
+ | \`\\newcommand\` + \`numbers.tex\` | works (1 line in the converter); the folk convention, ~12 GitHub hits, all hand-rolled. No package exists |
370
+ | **Quarto**, **pandoc lua filters** | ❌ **destroy the paper.** Markdown→markdown is a pandoc AST round-trip: HTML comments become raw blocks and \`[58]\` becomes \`\\[58\\]\`, so every citation renders as literal \`\\textbackslash{}[58]\`. 3,120 diff lines on the real source. No ACL format exists for Quarto either |
371
+ | **cog.py** | ❌ line-oriented; cannot substitute mid-sentence |
372
+ | **pythontex** | ❌ not in Ubuntu TeX Live at any level, not on PyPI; CTAN zip + \`.ins\` build |
373
+ | **showyourwork** | ❌ LaTeX-only, and it manages *figures*, not in-text numbers |
374
+ | **Pweave** | ❌ dead — the one candidate with a markdown native format, broken against modern IPython |
375
+ | DVC · datalad · papermill | orthogonal and **worth adding**: they pin the data file to the pipeline that made it, a layer below anything here |
376
+
377
+ **🔴 Computing the value DISSOLVES the freshness problem — do not build a checker for it.** With no
378
+ recorded value there is nothing that can go stale, so there is nothing to verify. Adopting jinja2
379
+ deleted 137 lines of ours outright: a hand-rolled expression language with an \`eval()\` sandbox, a
380
+ renderer guessing which of six formattings the paper meant, a JSON-path walker and the comparison.
381
+ Recording-plus-verifying is the trap; computing is the wheel.
382
+
383
+ **Binding a number to its CONDITION is genuinely unoccupied**, and the reason is structural rather
384
+ than an accident of packaging: **every literate-programming tool models the paper as a program that
385
+ prints text**, so the prose is opaque *output*, not an input to a check. None of them has a hook
386
+ where you could say "and the sentence around this must say *counterfactual* and must not say *as
387
+ committed*". The near-misses read the manuscript but never the data — \`statcheck\` recomputes
388
+ p-values from statistics printed in the same sentence; \`RegCheck\` compares a paper to a study
389
+ registration with an LLM and reports to a human instead of failing a build. Searched and empty:
390
+ GitHub repo search (0 results), the Actions marketplace, the pre-commit hook ecosystem, PyPI, and
391
+ the Claude skill marketplaces.
392
+
393
+ 🔴 **And it is not a number-keyed table**: the first version keyed rules on the digits, and a paper
394
+ printing two unrelated 22s broke it the same hour. Key on the occurrence.
395
+
396
+ 🔴 **Hand the gate to a red team the same day you build it.** This one was, and seven holes came
397
+ back, the worst being that the original defect could simply be **retyped as digits** — its value was
398
+ grandfathered, so the guard applied to the macro and not to the claim. Every hole is now a case in
399
+ \`repro/paper_numbers.selftest.py\` (18/18, including three that must stay **quiet** — a gate that
400
+ fires on ordinary writing gets muted, and then its silence reads as coverage).
401
+
402
+ ## 🔴 The page limit is a SUBMISSION gate, not an EDIT gate
403
+
404
+ **Observed failure, \`compile-rules-2026\`, 2026-08-02/03.** The body oscillated 8 ↔ 9 pages for roughly
405
+ fifty iterations. Each time content went in, the page count read 9, and prose came out to get back to
406
+ 8 — sixty characters at a time. Every individual cut looked harmless. Their sum is the unanimous 2/5
407
+ for clarity: the first compression took real repetition, the second had none left and took
408
+ transitions, antecedents and the conclusion's honest half. The structural pass named the arithmetic —
409
+ 780 words of genuine repetition removed, then 880 words in and 480 out, leaving the paper 51 words
410
+ *heavier* than before the pass that cut 780.
411
+
412
+ **The rule.** Content work runs OVER the limit on purpose. Compression is **one pass, at the end**,
413
+ when the content has settled — with a whole-draft view, so it can move a section instead of shaving a
414
+ clause. Going over during drafting is not a problem to fix; it is the normal state of a paper that is
415
+ still growing.
416
+
417
+ **The trigger to catch yourself:** you just added something, ran the page count, saw it over, and
418
+ started looking for words to remove **in the section you were just editing**. That is the failure, in
419
+ progress. The page count is information for the end of the work, not an alarm during it. (The author's
420
+ own words on catching it, translated from Russian: *"you're cutting the text right away — dunno if that really needs doing immediately."*)
421
+
422
+ **What is still continuous:** rendering, and looking at pages 1–2. Seeing the number is fine. Acting
423
+ on it is what waits.
424
+
425
+ 🔴 **Every round adds text; pay it back — in ONE pass.** Review is a ratchet — fixes are additive, so a
426
+ paper that survives three rounds is longer and denser than the one that entered them. On \`compile-rules-2026\` the
427
+ body oscillated 8 ↔ 9 pages for ~50 iterations, and the squeezing is what produced the unanimous 2/5 on
428
+ clarity: the first compression took real repetition, the second had none left and took transitions,
429
+ antecedents and the conclusion's honest half. After each round's fixes, run \`tighten-paper\` — and if the
430
+ page limit is binding, **move** rather than delete (Limitations and Ethics do not count toward ACL page
431
+ limits). The trap in that move is real and named in \`references/acl-venue-rules.md\`: relocating a caveat
432
+ while its flattering number stays in the body is exactly the asymmetry reviewers punish.
433
+
434
+ **Anti-churn ≠ skipping unrun gates.** "Don't loop past one confirming round" forbids *re-polishing prose
435
+ that already passed a gate* — it does NOT license *skipping a gate that never ran*. A \`☐\` row in
436
+ \`PIPELINE-STATUS.md\` for **study-accepted-papers, pc-panel-review, or full harden-paper** is an unrun
437
+ quality gate, not churn: **if capacity exists, run it before calling the paper done.** (This session
438
+ skipped those three under an "anti-churn" rationalization on a submitted paper; when the user forced them,
439
+ the pc-panel caught real must-fixes — a release overclaim and an unsupported number — that the skip would
440
+ have shipped.) Churn is re-touching FINE prose; a never-run gate is a hole. If a real
441
+ objection is out of scope, name it in Threats to Validity (adversarial reviewers read Threats first; an
442
+ honest limitation reads as strength).
443
+
444
+ **A \`☐\` in GATES is a hole. A \`☐\` in CONTINUOUS is worse** — it means the check exists, ran once, and
445
+ has been silently stale ever since. That is the shape of every failure this pipeline has actually had.
446
+
447
+ ## ⏱️ What each stage actually costs — MEASURED, not estimated
448
+
449
+ The author, 2026-08-05, watching a run he could not size (translated from Russian): *"is it worth
450
+ writing the timing problem into the pipeline skill?"*. Yes — because the project already forbids guessing here. The rule in the papers tree's own \`CLAUDE.md\`
451
+ says an estimate must be decomposed into labour / calendar / result-risk / access and **spiked
452
+ rather than guessed**, and the same session it was written I still launched an experiment with no
453
+ upper bound and had to cut it four hours later.
454
+
455
+ Every number below is subagent **wall clock, measured on 2026-08-04/05** while finishing
456
+ \`compile-rules-2026\`. They are one machine, one paper, one day — treat them as an order of
457
+ magnitude, not a promise. Re-measure rather than inherit.
458
+
459
+ | stage | measured | note |
460
+ |---|--:|---|
461
+ | \`verify-citations\`, one reference | **3 min** | sonnet; a fetch and a comparison |
462
+ | \`verify-citations\`, eight references | **3 min** | the fetches parallelise; count barely matters |
463
+ | a single reconciliation ("do these two numbers agree?") | **4 min** | sonnet, over committed data |
464
+ | a second-rater pass over ~20 rows | **8 min** | opens every cited file |
465
+ | a process/mechanism research pass (docs + source + issue tracker) | **10 min** | |
466
+ | \`pc-panel-review\`, full panel + chair | **17 min** | unchanged for the confirming round |
467
+ | \`grade-paper-writing\` incl. the persona cold read | **20 min** | |
468
+ | bundling an experiment into the artifact + gate + re-zip | **24–39 min** | scales with directories, not bytes |
469
+ | a design/measurement **spike** (feasibility, a handful of cells) | **27 min** | |
470
+ | \`tighten-paper\` applied, with a loss letter | **34 min** | includes several build round-trips |
471
+ | \`harden-paper\` | **36 min** | the widest gate; it runs the artifact |
472
+ | **an experiment with real checkouts and installed dependencies** | **≈4 h for 143 cells** | median cell **76 s**; the outlier by an order of magnitude |
473
+
474
+ **What the shape tells you, which matters more than the rows.**
475
+
476
+ - **A full gate cycle — \`tighten\` → \`grade\` → \`panel\` — is about 1.2 hours.** That is cheap enough
477
+ to run after any substantial edit, and there is no excuse for a stale gate on a paper you are
478
+ still touching.
479
+ - **Reading, checking and reviewing are all minutes.** Anything whose cost is dominated by fetching,
480
+ parsing or judging text lands in the 3–40 minute band regardless of how important it feels.
481
+ - 🔴 **Anything that installs dependencies and runs an agent inside a real checkout is hours, and
482
+ that is the only class that is.** Its cost is *per cell*: rows × arms × seeds × ~76 s. Compute
483
+ that product **before launching**, and say it out loud. 6 rows × 5 arms × 4 seeds = 120 cells ≈
484
+ 2.5 h; carrying the same design to 21 rows would have been ≈ 9 h.
485
+ - **Therefore: bound experiments by a cell budget, never by "run it and see".** Pick the number of
486
+ rows from the time available, decide up front what a complete balanced design is, and stop at the
487
+ last complete row. A design closed at six rows is a result; a design abandoned at eleven is a mess.
488
+
489
+ ## Model policy (which model runs which stage)
490
+ Single home for the whole suite — stage skills point here instead of each re-deciding. Default:
491
+ - **Adversarial / red-team / verify a claim** → **Fable** (a separate model; never the author grading
492
+ itself): \`paper-adversarial-review\`, \`pc-panel-review\` reviewers, \`harden-paper\` threat-model +
493
+ citability red-team, disputed \`verify-citations\` verdicts.
494
+ - **Heavy generation / synthesis** → the session's main model (**Opus**): \`draft-paper\`,
495
+ \`build-benchmark\` design, \`extend-paper\`, \`research-ideate\`.
496
+ - **Cheap bulk fetch / extraction** → **Haiku** (or Sonnet): \`study-accepted-papers\` corpus pull,
497
+ \`plan-paper-timeline\`.
498
+ - **No model at all (mechanical)** → \`verify-citations\`'s \`../verify-citations/scripts/verify-cites.mjs\` reducer,
499
+ \`harden-paper\`'s \`check-*.sh\` linters, \`render-paper\` toolchain.
500
+ - **Judge panels use DIVERSE models, not N copies of one** → \`grade-paper-writing\`, \`pc-panel-review\`:
501
+ mix Opus + Fable + Sonnet so independent lenses catch what redundancy can't.
502
+
503
+ Override per call when a stage clearly needs otherwise; this is the default, not a straitjacket.
504
+
505
+ ## Rules
506
+ - **Fable (a separate model) is always the reviewer** — never let the author grade itself.
507
+ - **Never fabricate** a citation, number, or result. Mark \`% VERIFY\` and check (\`verify-citations\`).
508
+ - **Commit + push after each stage**, keep the tree clean (resume-safe across \`/compact\`); update
509
+ \`<papers-root>/research/README.md\` in the same commit as any new research file (its CLAUDE.md enforces this).
510
+ - **Two roles, never double-counted:** authoring = the *authorship* criterion; reviewing others at the
511
+ venue (the organizer review-offer email) = the *judging* criterion — a separate credential.
512
+
513
+ ## Provenance
514
+ Two real papers this session ran this pipeline end-to-end: **AgenticDev 2026 @ ASE** ("Measuring the
515
+ Wrong Number," ~90%, submitted #20) and **AISec 2026 @ ACM CCS** ("Safety Theater," Weak-Accept→~87–88%
516
+ after a panel round + confirm). The stage skills and shared refs are distilled from exactly those runs.`,
517
+ });