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,182 @@
1
+ ---
2
+ name: submit-paper
3
+ description: End-to-end playbook for submitting a peer-reviewed paper to a double-blind venue (HotCRP workshops/conferences) — from a hardened draft to "ready for review." Covers building and anonymously hosting a reproduction artifact, HotCRP profile + form mechanics, double-blind hygiene, and the authorship/credential angles for an independent researcher. Use when the paper is drafted and reviewed and it's time to actually submit. Compose with pc-panel-review / paper-adversarial-review (harden first), and with the venue data card (references/venues/<venue>.md) for venue specifics.
4
+ allowed-tools: [Read, Write, Edit, Grep, Glob, Bash, WebSearch, WebFetch, Skill]
5
+ ---
6
+
7
+ <!-- vigiles:sha256:6befc6c0f3e910bd compiled from skills/submit-paper/SKILL.md.spec.ts -->
8
+
9
+ # submit-paper — get a reviewed paper from "done" to "ready for review"
10
+
11
+ ## Run me
12
+
13
+ 🔴 FIRST, before any other step:
14
+
15
+ ```
16
+ node .claude/skills/paper-pipeline/scripts/announce.mjs submit-paper <paper-dir>
17
+ ```
18
+
19
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
20
+ state — so starting is an event, and events get written down.
21
+
22
+ Assumes the paper is already hardened (run `pc-panel-review` — incl. its venue-fit mode — +
23
+ `paper-adversarial-review` first). This skill is the submission mechanics — the part that bit us with
24
+ avoidable friction the first time. Distilled from the AgenticDev 2026 submission.
25
+
26
+ ## Venue specifics — a DATA card, not a skill
27
+ The venue-specific facts (deadline, page limits, tracks, PC-member conflict list, blind model, format
28
+ quirks, whether a supplementary-upload field exists, the extension target) live as **plain reference
29
+ data files** under `references/venues/<venue>.md`:
30
+ - `references/venues/agenticdev.md` — AgenticDev @ ASE (workshop; ACM DL/IEEE Xplore).
31
+ - `references/venues/aisec.md` — AISec @ ACM CCS (security workshop; ACM DL; harder bar).
32
+
33
+ **The pattern (follow it for every new venue):** when you fetch a venue's exact submission instructions,
34
+ save them as a new **data file** `references/venues/<venue>.md` (short `title:` frontmatter only — NOT a
35
+ skill with `name:`/`description:`). This preserves the "save the exact venue instructions" rule while
36
+ keeping the skill namespace from proliferating one card per venue. The *mechanics* stay here; the venue
37
+ file is only the facts.
38
+
39
+ ## Publisher specifics — one level ABOVE the venue
40
+ Camera-ready mechanics belong to the **publisher**, not the venue: ACM eRights, the submit-vs-final
41
+ preamble swap, the copyright block, CCS 2012 codes and the mandatory Source-files upload are identical
42
+ for every ACM venue. They live in `references/publishers/<publisher>.md`:
43
+ - `references/publishers/acm.md` — ACM (AgenticDev @ ASE, AISec @ CCS, and every future ACM venue).
44
+
45
+ The venue card keeps only what is genuinely its own: dates, page limits, its DOI/ISBN, its copyright
46
+ line, its blind model. 🔴 **Filing publisher mechanics under one venue is the mistake this split exists
47
+ to prevent** — it was written into `agenticdev-2026/CAMERA-READY-FORM.md` first, where AISec could
48
+ never find it.
49
+
50
+ ## 0. Pre-flight
51
+ - PDF compiles clean (`pdflatex; bibtex; pdflatex; pdflatex`), ≤ page limit, 0 undefined refs.
52
+ - **De-anon scan the PDF text AND every shipped file** before submitting — author-identifying strings
53
+ must return zero; identifying the *studied* artifact is fine, identifying *you* is a desk-reject.
54
+ **MECHANICAL GATE (run it, don't eyeball) — greps the PDF text + every artifact file + inside any
55
+ `*.zip` for the identity deny-list, exit non-zero on a hit:**
56
+ ```
57
+ bash .claude/skills/submit-paper/check-deanon.sh <paper-dir> [pdf=paper.pdf]
58
+ ```
59
+ Must PASS (exit 0) for a double-blind submission. Deny-list: `.claude/skills/submit-paper/deanon-denylist.txt`
60
+ (edit as handles/repos change). This is the sibling of `render-paper/check-render.sh` and guards the
61
+ single highest reject-vector (an artifact README naming real maintainers/repos is invisible to a
62
+ paper-only read). Only run it on *double-blind* papers — a de-anonymized single-blind PDF is supposed
63
+ to carry your name and will (correctly) fail. Canonical deny-list rationale → `paper-pipeline/references/anonymization.md`.
64
+
65
+ ## 1. Build a reproduction artifact (empirical papers)
66
+ The single biggest accept-probability lever for a measurement paper — reviewers reward one they can run.
67
+ In short: a stdlib-only script that *recomputes* every headline number from raw data and **exits
68
+ non-zero on drift**; honest badge/scope (don't claim "raw N runs" for per-arm aggregates); a README
69
+ "what reproduces which number" table + LICENSE; scrubbed of `__pycache__` and fingerprints before it
70
+ ships. Canonical build checklist → `paper-pipeline/references/artifact-checklist.md`.
71
+
72
+ ## 2. Host the artifact ANONYMOUSLY (double-blind)
73
+ Many workshop HotCRPs have **no supplementary-upload field** — check first; if none, host externally and
74
+ `\url{}` the link in the paper's Availability.
75
+ - **OSF (osf.io) — best; self-upload, no repo needed.** Create a **Private** project (title = paper
76
+ title, no name), upload the files/zip, then **Contributors → View-only Links → Add → check
77
+ "Anonymize" → Create**. Keep the project private; the anonymized view-only link is what reviewers get.
78
+ OSF has a REST API + `osfclient` (`OSF_TOKEN`) → **automatable**: with a personal access token you can
79
+ create the project, upload, and mint the link programmatically. See `osf-artifact-upload` for the API calls; whatever uploader you use must read the token
80
+ from the `OSF_TOKEN` environment variable and never from a file in the repository. Record each
81
+ minted view-only link in your own notes and REUSE it — a second link for the same paper is a
82
+ second thing reviewers can be handed, and only one of them is the one you cited.
83
+ - Alternatives: `anonymous.4open.science` (anonymizes a **GitHub repo** — needs a repo, not file upload;
84
+ use a *private* source repo so the original isn't Google-findable); a throwaway identity-free account.
85
+ Avoid Google Drive / Zenodo / Figshare for blind review — they leak the owner name.
86
+ - **VERIFY in an incognito window** (logged out): the link must show the files with contributors =
87
+ "Anonymous" and your name nowhere. Then put the URL in Availability via `\url{}` and rebuild.
88
+
89
+ ## 3. HotCRP profile (do this once, before the form)
90
+ - **Name = your canonical / passport legal name**, identical on every paper you submit. (For
91
+ a dossier, name consistency across papers/LinkedIn/letters is load-bearing — see §6.)
92
+ - **Affiliation**: `None` (or `Unaffiliated`) if independent.
93
+ - **Country/region = where you actually reside**, not citizenship — this sidesteps ACM/IEEE
94
+ sanctions/payment friction for authors from sanctioned countries.
95
+ - **ORCID**: create one (free, 2 min) and reuse it on every paper. It's a permanent ID that ties all
96
+ your work to one identity *regardless of name spelling* — the fix for any name-variant problem.
97
+ - **Collaborators / other affiliations (COI)**: `None` if you have no recent coauthors/advisors.
98
+
99
+ ## 4. The submission form
100
+ - **Title**: exactly as it should appear in the proceedings (ACM DL) — plain text, no markup.
101
+ - **Submission**: upload **PDF only**. NEVER upload a source zip of the paper directory — sibling files
102
+ (drafts, READMEs, internal notes) leak identity. Only a scrubbed bundle is safe.
103
+ - **Abstract**: HotCRP makes you paste it into its own box even though it's in the PDF (it indexes it
104
+ separately). Paste plain text; convert LaTeX math to unicode (`~0.6%`, `≈`).
105
+ - **Authors (anonymous)**: enter your **real name + email** here — this metadata is hidden from
106
+ reviewers; the *PDF* is what's anonymized. That's how double-blind works; it's correct, not a leak.
107
+ - **ACM corresponding author**: default (first author).
108
+ - **PC conflicts**: check only genuine COIs (past advisor/student, same affiliation, ≤2-yr coauthor).
109
+ An independent researcher with no ties usually checks **none** — that's honest.
110
+
111
+ ## 5. Submit
112
+ - **Save and submit**, then **mark it "ready for review."** A saved draft alone is NOT evaluated — this
113
+ is the step people miss.
114
+ - You can edit until the deadline: use **Replace** on the Submission field to swap the PDF for a late
115
+ fix (e.g. adding the artifact link after you host it). Submit early, upgrade before the deadline.
116
+
117
+ ## 6. Independent-researcher / dossier notes
118
+ - **Name consistency** is the quiet risk: publications, LinkedIn, passport, letters must resolve to one
119
+ person. ORCID is the tool; pick one surname and use it everywhere from paper #1.
120
+ - Keep the **organizer review-offer email** + any PC/reviewer confirmation — that's the *judging*
121
+ criterion evidence (separate from authorship).
122
+ - **Space submissions out** — don't cluster all papers in the month before an external
123
+ filing — the FILING-SPACING rule `plan-paper-timeline` applies. A burst right before a filing reads
124
+ as manufactured rather than sustained, and that is an observed, documented refusal ground.
125
+ - After acceptance: plan the **camera-ready de-anonymization** and an **extension to a higher-prestige
126
+ venue** (workshop → conference, ≥30% new) as a second, stronger publication.
127
+
128
+ ## 7. Freeze the version you actually uploaded
129
+
130
+ 🔴 **The moment the portal accepts the file, download it back and commit it.** The rendered PDF is the
131
+ only artifact git cannot reconstruct — it was built outside the repo and lived on the portal.
132
+
133
+ ```
134
+ <paper-dir>/versions/<ISO-date>-submitted.pdf
135
+ ```
136
+
137
+ and in `PIPELINE-STATUS.md`, on the Submit row, the source that produced it: the literal word
138
+ **`commit <hash>`**. Stages are `submitted` / `camera-ready` / `arxiv`; each one you *declare* in
139
+ PIPELINE-STATUS needs its own frozen file.
140
+
141
+ **This is enforced, not advised** — `checkFrozenVersions()` in `.claude/hooks/paper-lint.mjs` reads the
142
+ declared stages and reports a paper that declared one without freezing it. The convention itself is
143
+ documented per-paper in `versions/README.md`.
144
+
145
+ **Why it is a step and not hygiene:** `agenticdev-2026` kept a folder for exactly this for a month and
146
+ the file inside was the wrong build (340 952 B vs the real 352 357 B). It surfaced only when a reviewer
147
+ cited `L. 166` and there was nothing to resolve the line against. A folder without a checker is a
148
+ convention with no reader.
149
+
150
+ ## 8. Record the verdict
151
+
152
+ 🔴 LAST step, once the deliverable exists:
153
+
154
+ ```
155
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record submit-paper <paper-dir> FINDING <count> <report-path>
156
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record submit-paper <paper-dir> ABSTAINED <reason> "<one line>"
157
+ ```
158
+
159
+ **FINDING** — `check-deanon.sh` exited non-zero, `access` is not green, the PDF is over the limit, or
160
+ the ready-for-review click never happened; `<count>` is the number of blocking items and
161
+ `<report-path>` names them. Always `--blocking` — every item here stops the submission.
162
+ **ABSTAINED** — `no-witness`: uploaded **and** marked ready for review, with the venue card or the
163
+ submission id in the note. `blocked`: the portal account is not through moderation yet.
164
+
165
+ 🔴 **A saved draft must never be recorded as done — and it now cannot be.** A saved-but-not-submitted
166
+ paper is the one failure this skill's provenance names by hand, and it was invisible to every other
167
+ check in the pipeline. There is no constructor for "submitted"; there is only the absence of blocking
168
+ items, plus a submission id in the note that a human can go and look up. The id IS the witness, and
169
+ recording `no-witness` without one is the same lie in a new vocabulary.
170
+
171
+ ## Compose with
172
+ - Harden first: `pc-panel-review` (incl. its venue-fit mode), `paper-adversarial-review`, `render-paper`.
173
+ - Publisher mechanics (camera-ready): `references/publishers/<publisher>.md`.
174
+ - Venue specifics: the matching data card `references/venues/<venue>.md` (e.g.
175
+ `references/venues/agenticdev.md`) for deadlines, page limits, PC-member conflict lists, whether
176
+ supplementary upload exists, and the extension target.
177
+
178
+ ## Provenance
179
+ Written from the AgenticDev 2026 @ ASE submission (2026-07-13): PC-panel-reviewed, self-checking
180
+ artifact hosted on an OSF anonymized view-only link (no supplementary field at the venue), submitted #20
181
+ ready-for-review. The friction points here — no supplementary slot, 4open needing a repo, the abstract
182
+ re-paste, "ready for review" being a separate step, the PDF-only rule — are the ones that cost time.
@@ -0,0 +1,199 @@
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: "submit-paper",
11
+ description:
12
+ 'End-to-end playbook for submitting a peer-reviewed paper to a double-blind venue (HotCRP workshops/conferences) — from a hardened draft to "ready for review." Covers building and anonymously hosting a reproduction artifact, HotCRP profile + form mechanics, double-blind hygiene, and the authorship/credential angles for an independent researcher. Use when the paper is drafted and reviewed and it\'s time to actually submit. Compose with pc-panel-review / paper-adversarial-review (harden first), and with the venue data card (references/venues/<venue>.md) for venue specifics.',
13
+ tools: [
14
+ "Read",
15
+ "Write",
16
+ "Edit",
17
+ "Grep",
18
+ "Glob",
19
+ "Bash",
20
+ "WebSearch",
21
+ "WebFetch",
22
+ "Skill",
23
+ ],
24
+ body: `
25
+ # submit-paper — get a reviewed paper from "done" to "ready for review"
26
+
27
+ ## Run me
28
+
29
+ 🔴 FIRST, before any other step:
30
+
31
+ \`\`\`
32
+ node .claude/skills/paper-pipeline/scripts/announce.mjs submit-paper <paper-dir>
33
+ \`\`\`
34
+
35
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
36
+ state — so starting is an event, and events get written down.
37
+
38
+ Assumes the paper is already hardened (run \`pc-panel-review\` — incl. its venue-fit mode — +
39
+ \`paper-adversarial-review\` first). This skill is the submission mechanics — the part that bit us with
40
+ avoidable friction the first time. Distilled from the AgenticDev 2026 submission.
41
+
42
+ ## Venue specifics — a DATA card, not a skill
43
+ The venue-specific facts (deadline, page limits, tracks, PC-member conflict list, blind model, format
44
+ quirks, whether a supplementary-upload field exists, the extension target) live as **plain reference
45
+ data files** under \`references/venues/<venue>.md\`:
46
+ - \`references/venues/agenticdev.md\` — AgenticDev @ ASE (workshop; ACM DL/IEEE Xplore).
47
+ - \`references/venues/aisec.md\` — AISec @ ACM CCS (security workshop; ACM DL; harder bar).
48
+
49
+ **The pattern (follow it for every new venue):** when you fetch a venue's exact submission instructions,
50
+ save them as a new **data file** \`references/venues/<venue>.md\` (short \`title:\` frontmatter only — NOT a
51
+ skill with \`name:\`/\`description:\`). This preserves the "save the exact venue instructions" rule while
52
+ keeping the skill namespace from proliferating one card per venue. The *mechanics* stay here; the venue
53
+ file is only the facts.
54
+
55
+ ## Publisher specifics — one level ABOVE the venue
56
+ Camera-ready mechanics belong to the **publisher**, not the venue: ACM eRights, the submit-vs-final
57
+ preamble swap, the copyright block, CCS 2012 codes and the mandatory Source-files upload are identical
58
+ for every ACM venue. They live in \`references/publishers/<publisher>.md\`:
59
+ - \`references/publishers/acm.md\` — ACM (AgenticDev @ ASE, AISec @ CCS, and every future ACM venue).
60
+
61
+ The venue card keeps only what is genuinely its own: dates, page limits, its DOI/ISBN, its copyright
62
+ line, its blind model. 🔴 **Filing publisher mechanics under one venue is the mistake this split exists
63
+ to prevent** — it was written into \`agenticdev-2026/CAMERA-READY-FORM.md\` first, where AISec could
64
+ never find it.
65
+
66
+ ## 0. Pre-flight
67
+ - PDF compiles clean (\`pdflatex; bibtex; pdflatex; pdflatex\`), ≤ page limit, 0 undefined refs.
68
+ - **De-anon scan the PDF text AND every shipped file** before submitting — author-identifying strings
69
+ must return zero; identifying the *studied* artifact is fine, identifying *you* is a desk-reject.
70
+ **MECHANICAL GATE (run it, don't eyeball) — greps the PDF text + every artifact file + inside any
71
+ \`*.zip\` for the identity deny-list, exit non-zero on a hit:**
72
+ \`\`\`
73
+ bash .claude/skills/submit-paper/check-deanon.sh <paper-dir> [pdf=paper.pdf]
74
+ \`\`\`
75
+ Must PASS (exit 0) for a double-blind submission. Deny-list: \`.claude/skills/submit-paper/deanon-denylist.txt\`
76
+ (edit as handles/repos change). This is the sibling of \`render-paper/check-render.sh\` and guards the
77
+ single highest reject-vector (an artifact README naming real maintainers/repos is invisible to a
78
+ paper-only read). Only run it on *double-blind* papers — a de-anonymized single-blind PDF is supposed
79
+ to carry your name and will (correctly) fail. Canonical deny-list rationale → \`paper-pipeline/references/anonymization.md\`.
80
+
81
+ ## 1. Build a reproduction artifact (empirical papers)
82
+ The single biggest accept-probability lever for a measurement paper — reviewers reward one they can run.
83
+ In short: a stdlib-only script that *recomputes* every headline number from raw data and **exits
84
+ non-zero on drift**; honest badge/scope (don't claim "raw N runs" for per-arm aggregates); a README
85
+ "what reproduces which number" table + LICENSE; scrubbed of \`__pycache__\` and fingerprints before it
86
+ ships. Canonical build checklist → \`paper-pipeline/references/artifact-checklist.md\`.
87
+
88
+ ## 2. Host the artifact ANONYMOUSLY (double-blind)
89
+ Many workshop HotCRPs have **no supplementary-upload field** — check first; if none, host externally and
90
+ \`\\url{}\` the link in the paper's Availability.
91
+ - **OSF (osf.io) — best; self-upload, no repo needed.** Create a **Private** project (title = paper
92
+ title, no name), upload the files/zip, then **Contributors → View-only Links → Add → check
93
+ "Anonymize" → Create**. Keep the project private; the anonymized view-only link is what reviewers get.
94
+ OSF has a REST API + \`osfclient\` (\`OSF_TOKEN\`) → **automatable**: with a personal access token you can
95
+ create the project, upload, and mint the link programmatically. See \`osf-artifact-upload\` for the API calls; whatever uploader you use must read the token
96
+ from the \`OSF_TOKEN\` environment variable and never from a file in the repository. Record each
97
+ minted view-only link in your own notes and REUSE it — a second link for the same paper is a
98
+ second thing reviewers can be handed, and only one of them is the one you cited.
99
+ - Alternatives: \`anonymous.4open.science\` (anonymizes a **GitHub repo** — needs a repo, not file upload;
100
+ use a *private* source repo so the original isn't Google-findable); a throwaway identity-free account.
101
+ Avoid Google Drive / Zenodo / Figshare for blind review — they leak the owner name.
102
+ - **VERIFY in an incognito window** (logged out): the link must show the files with contributors =
103
+ "Anonymous" and your name nowhere. Then put the URL in Availability via \`\\url{}\` and rebuild.
104
+
105
+ ## 3. HotCRP profile (do this once, before the form)
106
+ - **Name = your canonical / passport legal name**, identical on every paper you submit. (For
107
+ a dossier, name consistency across papers/LinkedIn/letters is load-bearing — see §6.)
108
+ - **Affiliation**: \`None\` (or \`Unaffiliated\`) if independent.
109
+ - **Country/region = where you actually reside**, not citizenship — this sidesteps ACM/IEEE
110
+ sanctions/payment friction for authors from sanctioned countries.
111
+ - **ORCID**: create one (free, 2 min) and reuse it on every paper. It's a permanent ID that ties all
112
+ your work to one identity *regardless of name spelling* — the fix for any name-variant problem.
113
+ - **Collaborators / other affiliations (COI)**: \`None\` if you have no recent coauthors/advisors.
114
+
115
+ ## 4. The submission form
116
+ - **Title**: exactly as it should appear in the proceedings (ACM DL) — plain text, no markup.
117
+ - **Submission**: upload **PDF only**. NEVER upload a source zip of the paper directory — sibling files
118
+ (drafts, READMEs, internal notes) leak identity. Only a scrubbed bundle is safe.
119
+ - **Abstract**: HotCRP makes you paste it into its own box even though it's in the PDF (it indexes it
120
+ separately). Paste plain text; convert LaTeX math to unicode (\`~0.6%\`, \`≈\`).
121
+ - **Authors (anonymous)**: enter your **real name + email** here — this metadata is hidden from
122
+ reviewers; the *PDF* is what's anonymized. That's how double-blind works; it's correct, not a leak.
123
+ - **ACM corresponding author**: default (first author).
124
+ - **PC conflicts**: check only genuine COIs (past advisor/student, same affiliation, ≤2-yr coauthor).
125
+ An independent researcher with no ties usually checks **none** — that's honest.
126
+
127
+ ## 5. Submit
128
+ - **Save and submit**, then **mark it "ready for review."** A saved draft alone is NOT evaluated — this
129
+ is the step people miss.
130
+ - You can edit until the deadline: use **Replace** on the Submission field to swap the PDF for a late
131
+ fix (e.g. adding the artifact link after you host it). Submit early, upgrade before the deadline.
132
+
133
+ ## 6. Independent-researcher / dossier notes
134
+ - **Name consistency** is the quiet risk: publications, LinkedIn, passport, letters must resolve to one
135
+ person. ORCID is the tool; pick one surname and use it everywhere from paper #1.
136
+ - Keep the **organizer review-offer email** + any PC/reviewer confirmation — that's the *judging*
137
+ criterion evidence (separate from authorship).
138
+ - **Space submissions out** — don't cluster all papers in the month before an external
139
+ filing — the FILING-SPACING rule \`plan-paper-timeline\` applies. A burst right before a filing reads
140
+ as manufactured rather than sustained, and that is an observed, documented refusal ground.
141
+ - After acceptance: plan the **camera-ready de-anonymization** and an **extension to a higher-prestige
142
+ venue** (workshop → conference, ≥30% new) as a second, stronger publication.
143
+
144
+ ## 7. Freeze the version you actually uploaded
145
+
146
+ 🔴 **The moment the portal accepts the file, download it back and commit it.** The rendered PDF is the
147
+ only artifact git cannot reconstruct — it was built outside the repo and lived on the portal.
148
+
149
+ \`\`\`
150
+ <paper-dir>/versions/<ISO-date>-submitted.pdf
151
+ \`\`\`
152
+
153
+ and in \`PIPELINE-STATUS.md\`, on the Submit row, the source that produced it: the literal word
154
+ **\`commit <hash>\`**. Stages are \`submitted\` / \`camera-ready\` / \`arxiv\`; each one you *declare* in
155
+ PIPELINE-STATUS needs its own frozen file.
156
+
157
+ **This is enforced, not advised** — \`checkFrozenVersions()\` in \`.claude/hooks/paper-lint.mjs\` reads the
158
+ declared stages and reports a paper that declared one without freezing it. The convention itself is
159
+ documented per-paper in \`versions/README.md\`.
160
+
161
+ **Why it is a step and not hygiene:** \`agenticdev-2026\` kept a folder for exactly this for a month and
162
+ the file inside was the wrong build (340 952 B vs the real 352 357 B). It surfaced only when a reviewer
163
+ cited \`L. 166\` and there was nothing to resolve the line against. A folder without a checker is a
164
+ convention with no reader.
165
+
166
+ ## 8. Record the verdict
167
+
168
+ 🔴 LAST step, once the deliverable exists:
169
+
170
+ \`\`\`
171
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record submit-paper <paper-dir> FINDING <count> <report-path>
172
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record submit-paper <paper-dir> ABSTAINED <reason> "<one line>"
173
+ \`\`\`
174
+
175
+ **FINDING** — \`check-deanon.sh\` exited non-zero, \`access\` is not green, the PDF is over the limit, or
176
+ the ready-for-review click never happened; \`<count>\` is the number of blocking items and
177
+ \`<report-path>\` names them. Always \`--blocking\` — every item here stops the submission.
178
+ **ABSTAINED** — \`no-witness\`: uploaded **and** marked ready for review, with the venue card or the
179
+ submission id in the note. \`blocked\`: the portal account is not through moderation yet.
180
+
181
+ 🔴 **A saved draft must never be recorded as done — and it now cannot be.** A saved-but-not-submitted
182
+ paper is the one failure this skill's provenance names by hand, and it was invisible to every other
183
+ check in the pipeline. There is no constructor for "submitted"; there is only the absence of blocking
184
+ items, plus a submission id in the note that a human can go and look up. The id IS the witness, and
185
+ recording \`no-witness\` without one is the same lie in a new vocabulary.
186
+
187
+ ## Compose with
188
+ - Harden first: \`pc-panel-review\` (incl. its venue-fit mode), \`paper-adversarial-review\`, \`render-paper\`.
189
+ - Publisher mechanics (camera-ready): \`references/publishers/<publisher>.md\`.
190
+ - Venue specifics: the matching data card \`references/venues/<venue>.md\` (e.g.
191
+ \`references/venues/agenticdev.md\`) for deadlines, page limits, PC-member conflict lists, whether
192
+ supplementary upload exists, and the extension target.
193
+
194
+ ## Provenance
195
+ Written from the AgenticDev 2026 @ ASE submission (2026-07-13): PC-panel-reviewed, self-checking
196
+ artifact hosted on an OSF anonymized view-only link (no supplementary field at the venue), submitted #20
197
+ ready-for-review. The friction points here — no supplementary slot, 4open needing a repo, the abstract
198
+ re-paste, "ready for review" being a separate step, the PDF-only rule — are the ones that cost time.`,
199
+ });
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env bash
2
+ # check-deanon.sh — mechanical double-blind de-anonymization gate.
3
+ #
4
+ # WHY: for a double-blind submission, an author-identifying string leaking into
5
+ # the PDF *or any shipped artifact file* is the single highest reject-vector, and
6
+ # it's invisible to a paper-only read (e.g. an artifact README that names real
7
+ # maintainers/repos). This greps a deny-list across the compiled PDF's TEXT and
8
+ # every artifact file (including inside artifact.zip) so "anonymized" is a checked
9
+ # fact. Sibling to render-paper/check-render.sh. Spirit: prose isn't policy.
10
+ #
11
+ # Usage: check-deanon.sh <paper-dir> [pdf=paper.pdf] [denylist=<skill>/deanon-denylist.txt]
12
+ # It auto-scans, in <paper-dir>: the PDF text, everything under artifact/ (if present),
13
+ # and the contents of any *.zip (artifact bundles). Pass extra paths after the
14
+ # denylist arg to scan additional dirs/zips.
15
+ #
16
+ # Exit: 0 = clean (no identifiers found); 1 = leak(s) found; 2 = usage/tool error.
17
+ # NOTE: run this ONLY on double-blind submissions. A single-blind/de-anonymized
18
+ # paper is SUPPOSED to carry the author name — this gate would (correctly) fail it.
19
+
20
+ set -uo pipefail
21
+
22
+ DIR="${1:?usage: check-deanon.sh <paper-dir> [pdf=paper.pdf] [denylist=...] [extra-paths...]}"
23
+ PDF="${2:-paper.pdf}"
24
+ SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25
+ DENY="${3:-$SKILL_DIR/deanon-denylist.txt}"
26
+ shift $(( $# >= 3 ? 3 : $# ))
27
+ EXTRA=("$@")
28
+
29
+ [ -d "$DIR" ] || { echo "FAIL: no dir $DIR"; exit 2; }
30
+ [ -f "$DENY" ] || { echo "FAIL: no deny-list $DENY"; exit 2; }
31
+
32
+ # Build the active pattern (strip comments/blanks).
33
+ PAT="$(grep -vE '^\s*(#|$)' "$DENY" || true)"
34
+ [ -n "$PAT" ] || { echo "FAIL: deny-list $DENY has no patterns"; exit 2; }
35
+
36
+ TMP="$(mktemp -d)"
37
+ trap 'rm -rf "$TMP"' EXIT
38
+
39
+ echo "== check-deanon: $DIR (pdf=$PDF, $(printf '%s\n' "$PAT" | wc -l | tr -d ' ') patterns) =="
40
+
41
+ hits=0
42
+
43
+ scan() { # scan <label> <file-or-textfile>
44
+ local label="$1" file="$2"
45
+ [ -f "$file" ] || return 0
46
+ local m
47
+ # -I skips binary files. REQUIRED since 2026-08-07, when the artifact branch stopped
48
+ # filtering by extension: without it, grep prints "Binary file X matches" for any .so,
49
+ # .map or image whose bytes happen to contain the pattern, and that line would be counted
50
+ # as a LEAK. A gate that cries wolf on a shared object gets muted, and a muted deanon
51
+ # gate is the same as no deanon gate.
52
+ m="$(grep -inEI "$PAT" "$file" 2>/dev/null || true)"
53
+ if [ -n "$m" ]; then
54
+ while IFS= read -r line; do
55
+ echo " LEAK $label:$line"
56
+ hits=$((hits+1))
57
+ done <<< "$m"
58
+ fi
59
+ }
60
+
61
+ # 1. PDF text (via pymupdf — same dep render-paper uses)
62
+ if [ -f "$DIR/$PDF" ]; then
63
+ if python3 - "$DIR/$PDF" "$TMP/pdf.txt" <<'PY' 2>/dev/null
64
+ import sys
65
+ try:
66
+ import fitz
67
+ except Exception:
68
+ sys.exit(3)
69
+ d = fitz.open(sys.argv[1])
70
+ open(sys.argv[2], "w").write("".join(p.get_text() for p in d))
71
+ PY
72
+ then scan "PDF[$PDF]" "$TMP/pdf.txt"
73
+ else echo " WARN: could not extract PDF text (pymupdf missing?) — PDF not scanned"; fi
74
+ else
75
+ echo " WARN: $DIR/$PDF not found — PDF not scanned"
76
+ fi
77
+
78
+ # 2. Every file under artifact/ (README, scripts, data) — text files only
79
+ if [ -d "$DIR/artifact" ]; then
80
+ while IFS= read -r f; do
81
+ scan "artifact/${f#"$DIR"/artifact/}" "$f"
82
+ # 🔴 NO EXTENSION FILTER, and that is the fix, not an oversight. Until 2026-08-07 this
83
+ # branch carried an allow-list (*.md *.py *.txt *.json *.js *.ts *.sh *.cfg *.csv *.tex
84
+ # LICENSE README*) and SILENTLY SKIPPED everything else — while printing "PASS: no
85
+ # author-identifying strings found. Safe for double-blind." about files it never opened.
86
+ #
87
+ # Measured, one fixture, identical bytes, three placements:
88
+ # artifact/config.yml (loose) -> exit 0, the affirmative safety sentence
89
+ # config.yml inside artifact.zip -> exit 1, LEAK reported
90
+ # config.yml via an extra path -> exit 1, LEAK reported
91
+ #
92
+ # The other two branches never filtered — the zip branch decodes every member, the
93
+ # extra-path branch is a bare `find -type f` — so the allow-list was an oversight, and
94
+ # the header's own contract says "every artifact file". Unlisted extensions that are
95
+ # ordinary in a real artifact: .yml/.yaml, .toml, Dockerfile, Makefile, .ipynb,
96
+ # .env.example, and .bib — a BibTeX file under artifact/ carrying the author's own name
97
+ # is the sharpest version of the miss.
98
+ #
99
+ # `grep -I` in scan() skips binary files, which is what the zip branch already relies on,
100
+ # so dropping the filter costs a little time and no correctness.
101
+ done < <(find "$DIR/artifact" -type f 2>/dev/null)
102
+ fi
103
+
104
+ # 3. Contents of any *.zip in the paper dir (and any extra zip paths) — the sneaky one
105
+ scan_zip() { # scan_zip <zip>
106
+ local zip="$1"
107
+ [ -f "$zip" ] || return 0
108
+ python3 - "$zip" "$TMP/zipdump" <<'PY' 2>/dev/null || return 0
109
+ import sys, zipfile, os
110
+ z, out = sys.argv[1], sys.argv[2]
111
+ os.makedirs(out, exist_ok=True)
112
+ zf = zipfile.ZipFile(z)
113
+ for n in zf.namelist():
114
+ if n.endswith("/"): continue
115
+ try:
116
+ data = zf.read(n)
117
+ text = data.decode("utf-8", "ignore")
118
+ except Exception:
119
+ continue
120
+ safe = n.replace("/", "__")
121
+ open(os.path.join(out, safe), "w").write(text)
122
+ PY
123
+ if [ -d "$TMP/zipdump" ]; then
124
+ for f in "$TMP/zipdump"/*; do
125
+ [ -f "$f" ] || continue
126
+ scan "$(basename "$zip")!$(basename "$f" | sed 's/__/\//g')" "$f"
127
+ done
128
+ rm -rf "$TMP/zipdump"
129
+ fi
130
+ }
131
+ while IFS= read -r z; do scan_zip "$z"; done < <(find "$DIR" -maxdepth 2 -name '*.zip' -type f 2>/dev/null)
132
+
133
+ # 4. Extra caller-supplied paths (dirs or zips)
134
+ for p in "${EXTRA[@]:-}"; do
135
+ [ -z "$p" ] && continue
136
+ if [ -d "$p" ]; then
137
+ while IFS= read -r f; do scan "extra:${f}" "$f"; done < <(find "$p" -type f 2>/dev/null)
138
+ elif [[ "$p" == *.zip ]]; then scan_zip "$p"
139
+ elif [ -f "$p" ]; then scan "extra:$p" "$p"; fi
140
+ done
141
+
142
+ echo "-- summary: $hits identifier hit(s) across PDF + artifact + zip"
143
+ if [ "$hits" -eq 0 ]; then
144
+ echo "PASS: no author-identifying strings found. Safe for double-blind."
145
+ exit 0
146
+ else
147
+ echo "FAIL: de-anonymization leak(s) above — scrub before submitting double-blind."
148
+ exit 1
149
+ fi
@@ -0,0 +1,92 @@
1
+ ---
2
+ title: "ACM — camera-ready mechanics, shared across ALL ACM venues"
3
+ created: 2026-08-24
4
+ updated: 2026-08-24
5
+ tags: [publisher, acm, camera-ready, erights, ccs]
6
+ ---
7
+
8
+ # ACM: what camera-ready requires
9
+
10
+ > This is the **publisher** level, not the venue level. Identical for AgenticDev@ASE, AISec@CCS,
11
+ > and any other ACM conference. The venue card (`../venues/<venue>.md`) holds only what's its own:
12
+ > dates, page limit, its own DOI/ISBN, blind model.
13
+ >
14
+ > Captured 2026-08-24 from the live AgenticDev #20 HotCRP form — field by field, not from memory.
15
+
16
+ ## 🔴 Order is mandatory, and the first step breaks everything else
17
+
18
+ **eRights is filled in FIRST and requires the FINAL title and author list.** So any decision about
19
+ a title change has to be made **before** it — otherwise the copyright block gets issued under the
20
+ old name.
21
+
22
+ 1. **ACM eRights** — a form from ACM, arrives as a link in HotCRP. The final version isn't
23
+ accepted without it.
24
+ 2. Update **Title** on the portal if it changed (it still holds the submission version).
25
+ 3. Convert the preamble to camera-ready (table below).
26
+ 4. Insert the copyright block that eRights returned.
27
+ 5. Build the PDF → run the portal's format checker.
28
+ 6. Upload the **Final version** (PDF) **and Source files** — both are mandatory.
29
+ 7. References: easiest is uploading `.bbl` + `.aux`.
30
+ 8. Fill in **ACM keywords** and **CCS codes**.
31
+ 9. `Save and resubmit`.
32
+
33
+ ## Preamble: submission mode ≠ camera-ready
34
+
35
+ The typical submission preamble is **wrong** for the final. What to change:
36
+
37
+ | in the submission | in camera-ready | why |
38
+ | --------------------------------------- | ---------------------- | ---------------------------------------------------------- |
39
+ | `\settopmatter{printacmref=false}` | remove | the ACM reference line has to print |
40
+ | `\setcopyright{none}` | the value from eRights | otherwise the block is wrong |
41
+ | `\pagestyle{plain}` | remove | the form explicitly says **"Do not include page numbers"** |
42
+ | the `review` option on `\documentclass` | remove | it adds line numbers |
43
+
44
+ Plus: **all fonts must be embedded** in the PDF.
45
+
46
+ The **copyright block** goes in the **bottom-left corner of the first page**, its exact form
47
+ depends on the choice made in eRights:
48
+
49
+ ```
50
+ <Venue> '<YY>, <dates>, <city>, <country>
51
+ © <year>
52
+ ACM ISBN <ISBN>
53
+ https://doi.org/<DOI>
54
+ ```
55
+
56
+ ⚠️ **DOI and ISBN are assigned in advance** and are visible on the form before upload — there's no
57
+ need to wait for them or make them up.
58
+
59
+ ## Portal fields
60
+
61
+ | Field | Req. | What matters |
62
+ | ---------------------- | ---- | --------------------------------------------------------------------------------------------------------------------- |
63
+ | **ACM eRights** | ✱ | before everything else; final title + authors |
64
+ | **Title** | ✱ | "exactly as it should appear in the ACM Digital Library" |
65
+ | **Final version** | ✱ | PDF, up to 600 MB |
66
+ | **Abstract** | ✱ | markdown + LaTeX math, has a Preview |
67
+ | **Source files** | ✱ | **ALL** build files: `.tex`, `.bib`, figures. Best as a single `.zip` |
68
+ | **ACM keywords** | — | one **per line** |
69
+ | **CCS** | — | terms from **2012 CCS** via the CCS Browser: Assign concepts → View your CCS Concept → Generate Code → paste the XML |
70
+ | **References** | — | upload `.bbl` + `.aux`, or as text one per line |
71
+ | **Supplements** | — | an **integral** part of the work (proof, online appendix) |
72
+ | **Auxiliary material** | — | NOT integral, but still lands in ACM DL: **dataset/code**. ACM does not claim copyright, but gets distribution rights |
73
+
74
+ ## What to decide deliberately
75
+
76
+ - **Auxiliary material.** Whether to also put the artifact in ACM DL alongside OSF/GitHub. Upside —
77
+ permanence and an extra findability point; downside — ACM gets distribution rights. Decide per
78
+ paper, not per venue.
79
+ - **APC.** If the venue charges one — pay only **after** ACM's author kit, which has the amount and
80
+ the process.
81
+
82
+ ## The frozen version
83
+
84
+ Camera-ready is a separate **stage** in the sense of `versions/` (see `checkFrozenVersions()` in
85
+ `paper-lint.mjs`): the uploaded PDF is stored as `versions/<date>-camera-ready.pdf`, and the commit
86
+ of its source is recorded in `PIPELINE-STATUS.md` as `commit <hash>`.
87
+
88
+ **Why this isn't a formality:** the arXiv posting and the extension paper get diffed against
89
+ camera-ready later, and reviewer references to line numbers only resolve against the exact render
90
+ a human read. 🔴 The failure that made this rule exist: `agenticdev-2026` had the wrong submission
91
+ PDF sitting there for a month (340,952 B vs 352,357 B), and when a reviewer cited `L. 166`, there
92
+ was nothing to check it against.