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,220 @@
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: "build-benchmark",
11
+ description:
12
+ "Design and run the empirical study behind a measurement paper, and ship a reviewer-proof reproduction artifact. Covers the study design (invert the pitfall you're critiquing), honest statistics (paired/Welch t, CIs, Bonferroni, small-n spread as a result, not noise), a structural bound that outlives the specific artifacts tested, and a self-checking artifact that recomputes every headline number and exits non-zero on drift. Use when the paper's contribution is a way to MEASURE something and you're building the evidence + the thing reviewers will run. Compose with research-ideate (upstream), draft-paper, pc-panel-review (its artifact-runner executes this), submit-paper.",
13
+ context: "fork",
14
+ tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash", "Agent"],
15
+ body: `
16
+ # build-benchmark β€” the study + the artifact reviewers can run
17
+
18
+ ## Run me
19
+
20
+ πŸ”΄ FIRST, before any other step:
21
+
22
+ \`\`\`
23
+ node .claude/skills/paper-pipeline/scripts/announce.mjs build-benchmark <paper-dir>
24
+ \`\`\`
25
+
26
+ An advisory pass cannot be observed failing β€” silence is both its error state and its normal
27
+ state β€” so starting is an event, and events get written down.
28
+
29
+ A measurement paper is only as strong as the artifact a reviewer can \`cd\` into and re-run. This skill
30
+ covers both halves: the study design that makes the finding true, and the self-checking artifact that
31
+ makes it *verifiable*. The contribution is the **method**, not the one tool you happened to test β€” build
32
+ so both survive review.
33
+
34
+ ## 0. πŸ”΄ READ THE STATED CLAIM FIRST β€” and refuse to design without it
35
+
36
+ **Before designing anything, open \`<paper-dir>/PIPELINE-STATUS.md\` and read row \`frame\`** β€” the one
37
+ paragraph saying what this paper will claim (written by \`argument-arc\` in **frame mode**, in SETUP).
38
+
39
+ πŸ”΄ **If \`frame\` is empty, stop. Do not design the study.** Go run \`argument-arc\` frame mode, get the
40
+ paragraph, then come back. This is a refusal, not a recommendation:
41
+
42
+ - **The frame decides which results matter.** A study designed without a stated claim measures
43
+ whatever the available harness can already see, and the claim gets fitted afterwards to whatever
44
+ came out. That is backwards, and it is expensive in exactly one direction β€” **reframing after the
45
+ data is collected is how runs get thrown away**, observed on \`compile-rules-2026\`.
46
+ - **The claim is what makes Β§1 answerable.** "What would make the critiqued pitfall impossible here?"
47
+ has no answer until you have written down what you are claiming.
48
+ - **It costs a paragraph and it saves a study.** There is no version of this trade that favours
49
+ starting the runs first.
50
+
51
+ Cross-check the claim against the prevention rule in the \`CLAUDE.md\` beside the papers: if the claim is
52
+ about *preventing* something, write the one sentence saying **what physically stops the bad outcome in
53
+ the experimental arm**. "There is different text in it" means you are measuring persuasion, not
54
+ prevention, and the design is wrong before a single run.
55
+
56
+ ## 1. Design that inverts the pitfall you're critiquing
57
+
58
+ The strongest measurement papers are a corrected version of the mistake they name. Pick the design that
59
+ is the *inverse* of the flaw:
60
+
61
+ - **Critiquing a proxy metric?** Measure the real thing, gated on correctness. The cost study is a
62
+ **cost-aware, correctness-gated A/B**: two arms Γ— two tools, every run scored pass/fail first, then
63
+ the *dollar* bill compared β€” because the whole point was that the token-proxy and the dollar disagree.
64
+ Never let a cheaper-but-broken run count as a win; correctness is the gate before cost is even read.
65
+ - **Measuring something that runs untrusted/destructive code?** **Parse, don't execute.** The guard eval
66
+ is a **SAFE STATIC evaluation**: transcribe each guard's predicate by hand and reason over it against a
67
+ disaster battery β€” never run the guard or the attack. See Safety below; this is non-negotiable.
68
+
69
+ Write the design as the answer to "what would make the critiqued pitfall impossible here?"
70
+
71
+ ## 2. Honest statistics β€” the part reviewers attack first
72
+
73
+ - **Paired where the design is paired; Welch where variances differ.** Use a **paired-t** when the same
74
+ task is run under both arms (blocks task difficulty); use **Welch's t** for unequal-variance unpaired
75
+ comparisons. Do NOT label a test "paired" unless the pairing is real β€” a mislabeled test is a blocker.
76
+ - **Report CIs and k/n, never bare percentages over tiny n.** "2/10 guards covered" beats "20% coverage";
77
+ "median 2/10 (range 0–5)" beats a single mean. A percentage over n=10 hides the n.
78
+ - **Report the SOURCE CONCENTRATION of a mined corpus β€” the single-source share is a number, not a
79
+ caveat.** For any corpus mined from several repositories / trackers / vendors, compute and print
80
+ **n per source and the max single-source share**, and put it in the paper (a table row or one
81
+ sentence), not only in Threats. A corpus advertised as covering *k* sources but dominated by one is
82
+ a top reason a mined-corpus paper gets rejected, and it is invisible to every other check β€” the
83
+ totals, the percentages and the internal consistency all pass, because the cut was simply never
84
+ made. **Mechanical leg:** the artifact emits \`source, n, share\` for the corpus and the top share
85
+ appears in the paper. If the top source exceeds ~50%, say so in the abstract's scope or narrow the
86
+ claimed population to what you actually sampled.
87
+ - **Inter-rater agreement is void if the rater was trained by, and scored against, the codebook's
88
+ author.** Agreement with the person who wrote the scheme measures *trainability*, not construct
89
+ reliability β€” it is the human form of the failure this suite already names in code (a checker and
90
+ its self-test written in one pass by one model). Requirements, all mechanical: (i) reference labels
91
+ come from a rater who did **not** author the codebook and did **not** see the hypothesis; (ii)
92
+ report the agreement **denominator as a share of the full corpus** β€” "ΞΊ=0.93 on 69 of 547 (12.6%)",
93
+ never a bare ΞΊ; (iii) use a coefficient that matches the design β€” Cohen's ΞΊ is single-label, so
94
+ multi-label coding needs per-label ΞΊ or Krippendorff's Ξ±; (iv) treat **ΞΊ = 1.00 as a red flag to
95
+ investigate, not a result to report** β€” perfect agreement on a many-category scheme usually means
96
+ the validation set was easy or calibration was de-facto joint coding.
97
+ - **Correct for the family.** Multiple comparisons across a family of tasks/tools β†’ **Bonferroni** (or
98
+ state the correction you used). Report it; don't p-hack the one significant cell.
99
+ - **Small-n spread is a first-class result, not noise.** If five trials of the same task swing wildly,
100
+ that variance IS the finding (the thing under test is unstable) β€” report it, don't average it away.
101
+ - Repeated trials: fix trial count up front (e.g. per-task Γ— trials Γ— arms Γ— tools), report the full n,
102
+ and treat every run β€” including failures β€” as data.
103
+
104
+ ## 3. A structural bound that outlives the artifacts
105
+
106
+ Numbers about today's tools rot. A **mechanism or structural bound** doesn't. Give the paper one claim
107
+ that holds regardless of which specific tool/version you measured:
108
+
109
+ - the cost study's bound: token-efficiency and dollar cost are decoupled by pricing structure, so a
110
+ token-optimizing tool *cannot* be assumed to cut the bill β€” a property of the pricing, not the tool.
111
+ - the guard eval's axes: **mutation-evasion** (does a trivial rephrase of the attack slip the guard?),
112
+ **held-out generalization** (does coverage transfer to commands the guard wasn't written for?), and
113
+ **per-step causal ablation** (remove one guard step, measure the coverage delta β€” which step actually
114
+ does the work). These are properties of the *defense class*, reusable against the next guard set.
115
+
116
+ State the bound explicitly; it's what makes the paper a benchmark and not a product review.
117
+
118
+ ## 4. Build a SELF-CHECKING artifact
119
+
120
+ This is the single biggest accept-probability lever, and pc-panel-review's artifact-runner WILL execute
121
+ it. Do **not** restate the requirements here β€” build to the canonical checklist:
122
+
123
+ β†’ **\`paper-pipeline/references/artifact-checklist.md\`** (self-recompute from raw data, exit non-zero on
124
+ drift, stdlib-only, no network, a README that maps each paper-number to where it prints, LICENSE, honest
125
+ badge scope, de-anon scanned).
126
+
127
+ The load-bearing property: each script **recomputes** every headline number from raw data and
128
+ **self-asserts** β€” exit non-zero the moment a cell drifts from the paper (\`reproduce.py\` on the cost
129
+ study; \`evaluate.py\`/\`mutate.py\`/\`reproduce.mjs\`/\`ablation.mjs\` on the guard eval). Derive from base
130
+ fields, never echo a stored/precomputed field β€” a reviewer calls that circular and they're right. For
131
+ de-anonymization before hosting, follow **\`paper-pipeline/references/anonymization.md\`**; host per
132
+ \`submit-paper\` (OSF anonymized view-only link; automation at \`papers/osf_upload.py\`).
133
+
134
+ ## Safety β€” never execute untrusted or destructive commands to measure them
135
+
136
+ If the object of study is code that could delete, exfiltrate, or run attacker-controlled input, you
137
+ **transcribe and parse its predicate** β€” you never execute it, and you never run the attack against it.
138
+ The guard eval scores 46 real command-guards by reading each guard's logic against a 10-command disaster
139
+ battery statically; nothing in the battery is ever run. A benchmark that has to detonate the payload to
140
+ score it is a liability, not evidence. Same rule inside the artifact: no network, no shelling out to the
141
+ thing under test.
142
+
143
+ ## Validate the transcription against real-code execution, not just a blind re-derivation
144
+
145
+ When you score third-party code by **transcribing its logic** (e.g. a guard's regexes) into your own
146
+ evaluator, a *blind re-derivation* (a second person re-reads the code and re-transcribes it) only checks
147
+ transcription-vs-human-reading β€” it does **not** check transcription-vs-real-behavior. There's a cheap,
148
+ zero-execution-risk way to close that gap: **run the actual scraped code against its REAL agent input
149
+ contract** and reconcile its live verdict with your static prediction.
150
+
151
+ - **Feed the real contract, not a bare string.** For Claude Code PreToolUse hooks, the command arrives as
152
+ a **JSON envelope on stdin** with the command at \`.tool_input.command\`. Feed each battery/benign command
153
+ as a **string inside that envelope** to the real guard's stdin and read its verdict (exit 2 = block; or
154
+ stdout JSON \`permissionDecision\` deny/ask/block). The command is **never executed** β€” the guard only
155
+ inspects the string.
156
+ - **SAFETY: sandbox + stub-PATH first.** Run inside a throwaway sandbox with a **stub PATH** (fake
157
+ \`rm\`/\`dd\`/\`git\`/\`curl\`/… β†’ \`exit 0\`) as defense-in-depth, so even a guard that shells out can't do
158
+ damage. Invoke the real interpreters by absolute path.
159
+ - **Reconcile per codeΓ—input pair.** Every mismatch between live verdict and static prediction is a
160
+ **finding** β€” either a transcription nit to fix, or a real behavior your static model structurally
161
+ cannot capture.
162
+
163
+ **Concrete payoff (the motivating example):** this method surfaced a **"whole-stdin confound"** β€” a
164
+ widely-copied guard that greps its **entire raw stdin** rather than the extracted command. The JSON
165
+ envelope's trailing bytes defeated its anchored \`rm …/$\` rule, so it **FAILED TO BLOCK \`rm -rf /\`** live,
166
+ even though it "blocked" the bare string. A pure transcription/static model can't see this; only
167
+ real-code-through-real-contract execution reveals it.
168
+
169
+ Before submitting, verify the artifact you built with the reviewer-side reproduction protocol:
170
+ **\`references/adversarial-cold-repro.md\`** (cold re-run, three-way reconcile, robustness attacks).
171
+
172
+ ## Record the verdict
173
+
174
+ πŸ”΄ LAST step, once the deliverable exists:
175
+
176
+ \`\`\`
177
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record build-benchmark <paper-dir> FINDING <count> <report-path>
178
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record build-benchmark <paper-dir> ABSTAINED <reason> "<one line>"
179
+ \`\`\`
180
+
181
+ πŸ”΄ **There is no PASS.** An artifact that recomputes every headline number and exits 0 has produced
182
+ no finding; it has not certified the study. Record the absence, do not name it a success.
183
+
184
+ **FINDING** β€” \`<count>\` numbers did not reproduce, or reproduce only with caveats; \`<report-path>\`
185
+ is the artifact output. Add \`--blocking\` for the Β§0 refusal: \`frame\` is empty, so the study was not
186
+ designed.
187
+ **ABSTAINED** β€” \`no-witness\`: the artifact ran and every number reproduced. \`input-missing\`: the
188
+ raw data is not in the repo. \`crashed\`: the harness itself died.
189
+
190
+ πŸ”΄ That Β§0 refusal is a **finding, not an aborted run** β€” it is a fact about the work, so it is a
191
+ FINDING and not an abstention. Record it and stop. A study that was never designed leaves exactly
192
+ the same silence as one that is still running, and the difference costs a week to rediscover.
193
+
194
+ πŸ”΄ **THREE MECHANICAL CHECKS FILE UNDER THIS SKILL** and each has its own ledger row:
195
+ \`build-benchmark/check-provenance\`, \`build-benchmark/arm-permutation\`,
196
+ \`build-benchmark/delivered-pdf\` (see \`.claude/skills/paper-pipeline/scripts/run-mechanical.mjs\`). Until 2026-08-10 the
197
+ ledger keyed on the SKILL, so a clean run of one erased a finding of another from every derived
198
+ view β€” which is why two of the three sat unwired. This block records the JUDGEMENT pass, under the
199
+ bare key \`build-benchmark\`; never file a mechanical result here.
200
+
201
+ ## Compose with
202
+ - **argument-arc (frame mode)** β€” πŸ”΄ **hard input.** Owns row \`frame\`, the stated claim. No \`frame\`, no study.
203
+ - **research-ideate** (upstream) β€” supplies the contribution and the pitfall to invert; this skill turns
204
+ it into evidence.
205
+ - **draft-paper** β€” the study's stats, bound, and artifact-number table feed Methods/Results/Availability.
206
+ - **pc-panel-review** β€” its artifact-runner reviewer \`cd\`s in and re-executes every harness; build so
207
+ that pass is deterministic.
208
+ - **submit-paper** β€” hosts the scrubbed artifact anonymously and links it in Availability.
209
+
210
+ ## Provenance
211
+ - **AgenticDev 2026 @ ASE β€” "Measuring the Wrong Number":** a cost-aware, correctness-gated A/B harness
212
+ over 140 runs (7 tasks Γ— 5 trials Γ— 2 arms Γ— 2 tools); Welch t + paired-t CIs + Bonferroni; the finding
213
+ that token-efficiency tools don't cut the dollar bill. Artifact = a stdlib-only \`reproduce.py\` that
214
+ recomputes every headline number from raw data and exits non-zero on drift.
215
+ - **AISec 2026 @ ACM CCS β€” "Safety Theater":** a 10-command disaster battery against 46 real
216
+ command-guards, SAFE STATIC evaluation (transcribe each predicate, never execute), median coverage
217
+ 2/10, plus mutation-evasion, held-out generalization, and per-step causal ablation axes. Artifact =
218
+ \`evaluate.py\`/\`mutate.py\`/\`reproduce.mjs\`/\`ablation.mjs\`, each self-asserting on run. Both artifacts
219
+ are hosted anonymized on OSF.`,
220
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * build-benchmark β€” the PAID tier: does this skill's description actually fire?
3
+ *
4
+ * COLOCATED ON PURPOSE (vigiles decides coverage by placement as of 2026-08-11).
5
+ * The prompts live in `.claude/lib/skill-trigger-cases.mjs` so all 21 cases
6
+ * are reviewed as one table where collisions between siblings are visible;
7
+ * copying them here would recreate the drift that rule exists to prevent.
8
+ *
9
+ * Measures recall (fires on its own territory) AND precision (stays quiet on a
10
+ * colliding sibling's territory), against the REAL `.claude` harness so the skill
11
+ * competes with every other installed description β€” an isolated run overstates
12
+ * recall and understates false positives.
13
+ *
14
+ * Costs money; not CI.
15
+ * node .claude/skills/build-benchmark/build-benchmark.eval.mjs [trials]
16
+ */
17
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
18
+
19
+ await runSkillTriggerEval("build-benchmark");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * build-benchmark β€” the free, deterministic tier. No model, no network.
3
+ *
4
+ * COLOCATED ON PURPOSE. vigiles decides coverage by PLACEMENT as of 2026-08-11:
5
+ * a test that merely names a surface no longer counts, because that tier was
6
+ * crediting surfaces nothing touched. So each skill needs a file inside its own
7
+ * directory β€” this one.
8
+ *
9
+ * The assertions live in `.claude/lib/skill-checks.mjs` and are CALLED here with
10
+ * this skill's name. They are not copied: 22 copies of the same checks is the drift that
11
+ * module exists to avoid. (Until 2026-08-11 this was an env-var side channel into a
12
+ * 614-line file named after no surface; it is a function call now.)
13
+ *
14
+ * What this proves: this skill's frontmatter parses as strict YAML, its declared
15
+ * tool contract is sane, its pipeline wiring points at scripts that exist, and it
16
+ * announces/records under ITS OWN identity rather than a sibling's.
17
+ *
18
+ * What it does NOT prove: that the skill fires, or that its guidance produces a
19
+ * good result. Those need a real model β€” see `build-benchmark.eval.mjs`.
20
+ */
21
+ import { checkSkill } from "../../lib/skill-checks.mjs";
22
+
23
+ await checkSkill("build-benchmark");
@@ -0,0 +1,68 @@
1
+ # Adversarial cold-repro protocol β€” reviewer-side reproduction of a measurement paper
2
+
3
+ **Purpose.** Before submitting a measurement paper that ships an artifact, reproduce it _as a hostile
4
+ evaluator_. Default stance is **SKEPTIC**: your job is to **refute** the paper, not to confirm it. Rate a
5
+ claim **CONFIRMED** only if a cold reproduction _forces_ you to. "The prose says so" and "results.json says
6
+ so" are **not** sufficient evidence β€” both were written by the author you're trying to catch.
7
+
8
+ Run this once the paper + artifact are drafted, before `submit-paper`. One honest **REFUTED** beats ten
9
+ hand-wavy **CONFIRMED**s.
10
+
11
+ ## Protocol
12
+
13
+ 1. **Reproduce cold.** Run the evaluator(s) from a _clean checkout_, capturing output **without reading the
14
+ committed results first**. THEN diff your fresh output against the committed JSON. Never overwrite the
15
+ committed outputs β€” always run to stdout or a temp file. (Reading the committed numbers first biases you
16
+ into pattern-matching them instead of independently deriving them.)
17
+
18
+ **Clean checkout means clean ENVIRONMENT β€” a self-checking artifact you never ran clean is
19
+ UNVERIFIED.** Unzip the exact `artifact.zip` (or `git clone` fresh) into a scratch dir and follow the
20
+ artifact's own README step-by-step; every self-check must exit 0 and print numbers matching the paper.
21
+ The trap that hides until a reviewer hits it: **missing/uninstalled dependencies** β€” a harness that
22
+ needs `npm install` / `pip install` / a build step the _release script_ doesn't run, so it crashes with
23
+ `MODULE_NOT_FOUND` on a fresh unzip even though it "passes" in the author's dirty tree (where
24
+ `node_modules` lingers). Fix: make the release/self-check script install deps itself, and make the
25
+ README's quick-start the exact commands you just ran clean. A "functional artifact" that isn't
26
+ functional out of the box is a benchmark-track reject. (Real catch: GateBench's `check-release.sh` ran
27
+ the Node harnesses without `npm install` β€” green in the dirty tree, `ERR_MODULE_NOT_FOUND` on a clean
28
+ one.)
29
+
30
+ 2. **Three-way reconcile EVERY headline number.** For each number the paper leans on, line up:
31
+ (a) the value in the **paper source** (abstract/intro/results/table),
32
+ (b) the value in **results.json** (or whatever the artifact commits),
33
+ (c) your **fresh re-run**.
34
+ Any drift, off-by-one, or stale number left over from an earlier corpus size is a **finding**. These
35
+ three must agree exactly; if they don't, the paper is inconsistent until fixed.
36
+
37
+ 3. **Attack robustness, not just arithmetic.** Recompute under stress:
38
+ - **The paper's OWN stated caveats, taken STRICTLY** β€” if it says "excluding X," actually exclude X and
39
+ see if the headline survives.
40
+ - **Dedup / weighting sensitivity** β€” does the headline move under a plausible alternative aggregation
41
+ (per-item vs per-source, weighted vs unweighted, dedup vs raw)? If a different-but-defensible rollup
42
+ flips the story, the story is fragile.
43
+ - **Convenience-sample sensitivity** β€” drop the strongest / outlier item(s). Does the narrative hold, or
44
+ was it carried by one datapoint?
45
+
46
+ 4. **Attack the arms reviewers hit hardest.**
47
+ - **Nondeterministic / LLM components** β€” is any claimed instability _real_, and is the paper careful to
48
+ claim only the _shape_ (e.g. "unstable," "median 2/10, range 0–5") rather than exact per-cell values a
49
+ re-run can't reproduce?
50
+ - **By-construction / "always/never" claims** β€” are they scoped to a _declared scope_, not stated as
51
+ unconditional absolutes?
52
+
53
+ 5. **Transcription integrity.** If the evaluator transcribes third-party logic (regexes, predicates, rules)
54
+ into your own scorer, spot-check a few items against their **real source**. If there's a validation set
55
+ of corrections, confirm every correction runs in the **claimed direction** (a validation set whose
56
+ "fixes" cut both ways is a red flag). See the live-contract execution method in `SKILL.md` β€” a blind
57
+ re-derivation only validates transcription-vs-human-reading, not transcription-vs-real-behavior.
58
+
59
+ ## Output β€” one verdict per claim
60
+
61
+ For each headline claim, emit:
62
+
63
+ - **VERDICT: CONFIRMED | REFUTED | NEEDS-FIX**
64
+ - The **three numbers** (paper source / results.json / fresh re-run).
65
+ - The **single command** that reproduces it from a clean checkout.
66
+ - If not CONFIRMED: the **minimal fix** + the exact **source file:line** to change.
67
+
68
+ Keep it terse and adversarial. The deliverable is the list of findings, not reassurance.
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: camera-ready
3
+ description: On acceptance, turn the anonymized-for-review paper into the de-anonymized camera-ready that actually enters the proceedings (ACM DL / IEEE Xplore). Reverses double-blind anonymization, swaps the OSF view-only artifact for a real public repo + an archival DOI, and β€” for security papers β€” completes responsible disclosure BEFORE any de-anonymized public release. Use after a notification email says Accept and the venue gives a camera-ready deadline. Compose with submit-paper (upstream) and extend-paper (next).
4
+ allowed-tools: [Read, Write, Edit, Grep, Glob, Bash, WebSearch, WebFetch]
5
+ ---
6
+
7
+ <!-- vigiles:sha256:8fa0190054cc5314 compiled from skills/camera-ready/SKILL.md.spec.ts -->
8
+
9
+ # camera-ready β€” de-anonymize an accepted paper into the final proceedings version
10
+
11
+ ## Run me
12
+
13
+ πŸ”΄ FIRST, before any other step:
14
+
15
+ ```
16
+ node .claude/skills/paper-pipeline/scripts/announce.mjs camera-ready <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
+ The reviewed PDF was anonymized on purpose. Acceptance flips that: the camera-ready carries your
23
+ real name, your real repo, and an archival DOI β€” and it's the version that gets indexed, so it's the
24
+ actual authorship evidence. This skill is the reverse of the anonymization you did at
25
+ submission. Work from `paper-pipeline/references/anonymization.md` and undo each move it lists.
26
+
27
+ ## 0. Pre-flight
28
+ - Confirm the **camera-ready deadline** and the **format instructions** in the acceptance email
29
+ (some venues ship a specific `acmart` template version or a copyright block to paste β€” use theirs).
30
+ - Read the reviews once more: camera-ready is your one cheap chance to fold in the must-fix comments
31
+ the meta-review flagged. Do those edits now, not "later."
32
+ - **Security papers only**: do not start the public de-anonymized release until Β§3 (disclosure) is
33
+ logged as complete. The de-anon repo is public and Google-findable the moment you push it.
34
+
35
+ ## 1. Reverse the anonymization
36
+ Undo, one by one, everything `../paper-pipeline/references/anonymization.md` told you to hide:
37
+ - **Class options**: `\documentclass[sigconf,review,anonymous]{acmart}` β†’ `\documentclass[sigconf]{acmart}`.
38
+ Dropping `review` also drops line numbers and the review-mode banner; dropping `anonymous` un-hides
39
+ the author block.
40
+
41
+ πŸ”΄ **Dropping `review` ARMS a gate that was exempt until this second β€” run it NOW, in the same
42
+ pass, not at push time:**
43
+
44
+ ```bash
45
+ npx eslint --no-config-lookup --config eslint.config.mjs <paper.tex>
46
+ ```
47
+
48
+ `tex/future-promise` exempts review builds deliberately: while a paper is under review, "the
49
+ harness will be released at camera-ready" is true and expected. The moment `review` comes off,
50
+ the same sentence becomes a contradiction with the Availability paragraph β€” and that is exactly
51
+ the defect this rule was created for, on a real submitted paper, where a reviewer had already
52
+ listed the missing artifact as a weakness and the printed camera-ready went on asserting it.
53
+
54
+ ⚠️ **Why it must run HERE and not be left to CI** (measured 2026-09-11): the check lives in
55
+ ESLint, and no local hook runs ESLint on `.tex` β€” `paper-lint.mjs` stopped carrying it on
56
+ 2026-09-07. CI does run it, but CI runs *after a push*, while a camera-ready gets built and
57
+ uploaded to HotCRP before that. Between "dropped `review`" and "pushed" the gate does not
58
+ exist. Measured on a fixture: in review mode 0 findings, with `review` removed 1 finding β€”
59
+ the rule flips instantly, so the only question is whether anyone looks.
60
+
61
+ ⚠️ And re-run it after the LAST edit to `paper.tex`, not once at the start. The original
62
+ defect survived because the promise was swept out of the artifact (`README`, `reproduce.py`)
63
+ the same day and nobody made the same pass over `paper.tex`: one class of defect, two
64
+ carriers, one cleaned.
65
+ - **Author block**: replace `Anonymous Author(s)` with your real name, affiliation (`None` /
66
+ `Unaffiliated` if independent β€” that's honest, not a weakness), city/country, email, and
67
+ `\orcid{...}`. Keep the **ORCID identical** to your prior papers β€” it's the permanent thread that
68
+ ties every version to one identity regardless of name spelling.
69
+ - **Un-blind self-citations**: the "[anonymized for review]" / "our prior work [redacted]" placeholders
70
+ become the real citations. Grep the `.tex` for `anonym`, `redact`, `blinded`.
71
+ - **"Our tool" naming**: the studied artifact and your own tool get their real names back everywhere β€”
72
+ title, abstract, figures, captions, artifact README. (For AISec: the anonymized hook names get their
73
+ real names back **only after** disclosure, Β§3.)
74
+ - **Acknowledgements / funding**: add the section that was omitted for blind review (thanks, grant
75
+ numbers, compute credits). None to declare is fine β€” say nothing rather than invent a funder.
76
+
77
+ ## 2. Swap the artifact: real repo + ARCHIVAL DOI
78
+ The review artifact was an OSF anonymized view-only link. The camera-ready needs two things:
79
+ - **A real public repo** (your GitHub, de-anonymized, with the generation layer / de-anon code that you
80
+ promised "lands at camera-ready" in the submission README).
81
+ - **An archival DOI** — mint it on **Zenodo or Figshare** (GitHub→Zenodo release integration is the
82
+ easy path). A zip sitting in a repo does **not** earn the ACM "Artifacts Available" badge; a DOI'd,
83
+ immutable deposit does. Put the DOI (not just the repo URL) in the Availability section via `\url{}`
84
+ or `\doi{}`.
85
+ - Keep the artifact **self-checking** (it still recomputes every headline number and exits non-zero on
86
+ drift) β€” de-anonymizing it doesn't excuse it from reproducing the paper.
87
+
88
+ ## 3. Responsible disclosure (security papers β€” BEFORE public release)
89
+ For the AISec "Safety Theater" paper the studied hooks are named-but-anonymized, and disclosure to the
90
+ maintainers is **owed before** any de-anonymized public release. Do this, in order:
91
+ - Identify the named parties (maintainers of each studied hook / tool).
92
+ - Send a private disclosure (email / security advisory) with the finding, repro, and a fix suggestion.
93
+ Give a reasonable remediation window (the venue or a 90-day norm).
94
+ - **Log it**: who, when, via what channel, and their response β€” keep the thread. This log is both
95
+ ethics evidence and "impact" material.
96
+ - Only after disclosure is sent (and ideally acknowledged) do you push the de-anonymized repo and
97
+ restore real hook names in the camera-ready. If a maintainer needs more time, hold the public release
98
+ and coordinate β€” the indexed paper can go out with names still generalized if disclosure is pending.
99
+
100
+ ## 4. Re-check the page limit
101
+ De-anonymizing **adds lines** β€” the author block, acknowledgements, un-abbreviated self-cites, real
102
+ URLs all grow the paper. Camera-ready page limits are often the same as (or one page more than) review,
103
+ and going over is a hard reject at the proceedings stage. Recompile
104
+ (`pdflatex; bibtex; pdflatex; pdflatex`), confirm 0 undefined refs, and check you're within the limit.
105
+ If tight, ACM allows references to spill into the reference-only extra pages.
106
+
107
+ ## 5. Ship
108
+ - Rebuild the final PDF, upload to the camera-ready system (often the same HotCRP, or an ACM eRights /
109
+ TAPS pipeline β€” follow the copyright email).
110
+ - Complete the **ACM/IEEE eRights** copyright form β†’ paste the returned copyright block + DOI into the
111
+ `.tex` before the final build (ACM validates this).
112
+ - Verify the public artifact link resolves and the DOI is live before you submit the final PDF.
113
+ - Record the paper's DOI, the artifact DOI, and the ORCID in the paper's HANDOFF β€” those three IDs are
114
+ the authorship evidence and the anchor the extension (`extend-paper`) builds on.
115
+
116
+ ## 6. Record the verdict
117
+
118
+ πŸ”΄ LAST step, once the deliverable exists:
119
+
120
+ ```
121
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record camera-ready <paper-dir> FINDING <count> <report-path>
122
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record camera-ready <paper-dir> ABSTAINED <reason> "<one line>"
123
+ ```
124
+
125
+ **FINDING** β€” `<count>` residual items still open; `<report-path>` names them. Add `--blocking` for
126
+ anything that must not be pushed past: anonymization residue, a dead artifact link, or β€” on a
127
+ security paper β€” disclosure not yet complete.
128
+ **ABSTAINED** β€” `no-witness`: shipped, de-anonymized, DOI live, page limit re-checked, with the DOI
129
+ in the note. `blocked`: the acceptance notice has not arrived, so there is nothing to make ready.
130
+
131
+ πŸ”΄ That blocking finding is the only one in this pipeline whose consequence is **irreversible**. The
132
+ public de-anonymized repo is Google-findable the moment it is pushed, so record it before, not after.
133
+
134
+ πŸ”΄ **There is no PASS**, and on this skill that is not a formality: a stored "shipped" would have
135
+ been the one row in the pipeline that could be true of a repo nobody had looked at. The DOI in the
136
+ note is the witness. Without it there is nothing to check the row against.
137
+
138
+ ## Compose with
139
+ - **submit-paper** (upstream β€” this reverses what it anonymized).
140
+ - **paper-pipeline/references/anonymization.md** β€” the canonical list of anonymization moves; undo each.
141
+ - **extend-paper** (next β€” the accepted+indexed paper is the base for a second, stronger publication).
142
+
143
+ ## Provenance
144
+ Both portfolio papers are anonymized-for-review and **defer de-anonymization + the public artifact to
145
+ camera-ready by design**: AgenticDev "Measuring the Wrong Number" (submitted, camera-ready 28 Aug if
146
+ accepted) and AISec "Safety Theater" (ships an anonymized artifact; hook names anonymized; responsible
147
+ disclosure to named maintainers owed before any de-anonymized public release). ORCID is identical
148
+ across both so every indexed version resolves to one researcher.
@@ -0,0 +1,164 @@
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: "camera-ready",
11
+ description:
12
+ "On acceptance, turn the anonymized-for-review paper into the de-anonymized camera-ready that actually enters the proceedings (ACM DL / IEEE Xplore). Reverses double-blind anonymization, swaps the OSF view-only artifact for a real public repo + an archival DOI, and β€” for security papers β€” completes responsible disclosure BEFORE any de-anonymized public release. Use after a notification email says Accept and the venue gives a camera-ready deadline. Compose with submit-paper (upstream) and extend-paper (next).",
13
+ tools: [
14
+ "Read",
15
+ "Write",
16
+ "Edit",
17
+ "Grep",
18
+ "Glob",
19
+ "Bash",
20
+ "WebSearch",
21
+ "WebFetch",
22
+ ],
23
+ body: `
24
+ # camera-ready β€” de-anonymize an accepted paper into the final proceedings version
25
+
26
+ ## Run me
27
+
28
+ πŸ”΄ FIRST, before any other step:
29
+
30
+ \`\`\`
31
+ node .claude/skills/paper-pipeline/scripts/announce.mjs camera-ready <paper-dir>
32
+ \`\`\`
33
+
34
+ An advisory pass cannot be observed failing β€” silence is both its error state and its normal
35
+ state β€” so starting is an event, and events get written down.
36
+
37
+ The reviewed PDF was anonymized on purpose. Acceptance flips that: the camera-ready carries your
38
+ real name, your real repo, and an archival DOI β€” and it's the version that gets indexed, so it's the
39
+ actual authorship evidence. This skill is the reverse of the anonymization you did at
40
+ submission. Work from \`paper-pipeline/references/anonymization.md\` and undo each move it lists.
41
+
42
+ ## 0. Pre-flight
43
+ - Confirm the **camera-ready deadline** and the **format instructions** in the acceptance email
44
+ (some venues ship a specific \`acmart\` template version or a copyright block to paste β€” use theirs).
45
+ - Read the reviews once more: camera-ready is your one cheap chance to fold in the must-fix comments
46
+ the meta-review flagged. Do those edits now, not "later."
47
+ - **Security papers only**: do not start the public de-anonymized release until Β§3 (disclosure) is
48
+ logged as complete. The de-anon repo is public and Google-findable the moment you push it.
49
+
50
+ ## 1. Reverse the anonymization
51
+ Undo, one by one, everything \`../paper-pipeline/references/anonymization.md\` told you to hide:
52
+ - **Class options**: \`\\documentclass[sigconf,review,anonymous]{acmart}\` β†’ \`\\documentclass[sigconf]{acmart}\`.
53
+ Dropping \`review\` also drops line numbers and the review-mode banner; dropping \`anonymous\` un-hides
54
+ the author block.
55
+
56
+ πŸ”΄ **Dropping \`review\` ARMS a gate that was exempt until this second β€” run it NOW, in the same
57
+ pass, not at push time:**
58
+
59
+ \`\`\`bash
60
+ npx eslint --no-config-lookup --config eslint.config.mjs <paper.tex>
61
+ \`\`\`
62
+
63
+ \`tex/future-promise\` exempts review builds deliberately: while a paper is under review, "the
64
+ harness will be released at camera-ready" is true and expected. The moment \`review\` comes off,
65
+ the same sentence becomes a contradiction with the Availability paragraph β€” and that is exactly
66
+ the defect this rule was created for, on a real submitted paper, where a reviewer had already
67
+ listed the missing artifact as a weakness and the printed camera-ready went on asserting it.
68
+
69
+ ⚠️ **Why it must run HERE and not be left to CI** (measured 2026-09-11): the check lives in
70
+ ESLint, and no local hook runs ESLint on \`.tex\` β€” \`paper-lint.mjs\` stopped carrying it on
71
+ 2026-09-07. CI does run it, but CI runs *after a push*, while a camera-ready gets built and
72
+ uploaded to HotCRP before that. Between "dropped \`review\`" and "pushed" the gate does not
73
+ exist. Measured on a fixture: in review mode 0 findings, with \`review\` removed 1 finding β€”
74
+ the rule flips instantly, so the only question is whether anyone looks.
75
+
76
+ ⚠️ And re-run it after the LAST edit to \`paper.tex\`, not once at the start. The original
77
+ defect survived because the promise was swept out of the artifact (\`README\`, \`reproduce.py\`)
78
+ the same day and nobody made the same pass over \`paper.tex\`: one class of defect, two
79
+ carriers, one cleaned.
80
+ - **Author block**: replace \`Anonymous Author(s)\` with your real name, affiliation (\`None\` /
81
+ \`Unaffiliated\` if independent β€” that's honest, not a weakness), city/country, email, and
82
+ \`\\orcid{...}\`. Keep the **ORCID identical** to your prior papers β€” it's the permanent thread that
83
+ ties every version to one identity regardless of name spelling.
84
+ - **Un-blind self-citations**: the "[anonymized for review]" / "our prior work [redacted]" placeholders
85
+ become the real citations. Grep the \`.tex\` for \`anonym\`, \`redact\`, \`blinded\`.
86
+ - **"Our tool" naming**: the studied artifact and your own tool get their real names back everywhere β€”
87
+ title, abstract, figures, captions, artifact README. (For AISec: the anonymized hook names get their
88
+ real names back **only after** disclosure, Β§3.)
89
+ - **Acknowledgements / funding**: add the section that was omitted for blind review (thanks, grant
90
+ numbers, compute credits). None to declare is fine β€” say nothing rather than invent a funder.
91
+
92
+ ## 2. Swap the artifact: real repo + ARCHIVAL DOI
93
+ The review artifact was an OSF anonymized view-only link. The camera-ready needs two things:
94
+ - **A real public repo** (your GitHub, de-anonymized, with the generation layer / de-anon code that you
95
+ promised "lands at camera-ready" in the submission README).
96
+ - **An archival DOI** — mint it on **Zenodo or Figshare** (GitHub→Zenodo release integration is the
97
+ easy path). A zip sitting in a repo does **not** earn the ACM "Artifacts Available" badge; a DOI'd,
98
+ immutable deposit does. Put the DOI (not just the repo URL) in the Availability section via \`\\url{}\`
99
+ or \`\\doi{}\`.
100
+ - Keep the artifact **self-checking** (it still recomputes every headline number and exits non-zero on
101
+ drift) β€” de-anonymizing it doesn't excuse it from reproducing the paper.
102
+
103
+ ## 3. Responsible disclosure (security papers β€” BEFORE public release)
104
+ For the AISec "Safety Theater" paper the studied hooks are named-but-anonymized, and disclosure to the
105
+ maintainers is **owed before** any de-anonymized public release. Do this, in order:
106
+ - Identify the named parties (maintainers of each studied hook / tool).
107
+ - Send a private disclosure (email / security advisory) with the finding, repro, and a fix suggestion.
108
+ Give a reasonable remediation window (the venue or a 90-day norm).
109
+ - **Log it**: who, when, via what channel, and their response β€” keep the thread. This log is both
110
+ ethics evidence and "impact" material.
111
+ - Only after disclosure is sent (and ideally acknowledged) do you push the de-anonymized repo and
112
+ restore real hook names in the camera-ready. If a maintainer needs more time, hold the public release
113
+ and coordinate β€” the indexed paper can go out with names still generalized if disclosure is pending.
114
+
115
+ ## 4. Re-check the page limit
116
+ De-anonymizing **adds lines** β€” the author block, acknowledgements, un-abbreviated self-cites, real
117
+ URLs all grow the paper. Camera-ready page limits are often the same as (or one page more than) review,
118
+ and going over is a hard reject at the proceedings stage. Recompile
119
+ (\`pdflatex; bibtex; pdflatex; pdflatex\`), confirm 0 undefined refs, and check you're within the limit.
120
+ If tight, ACM allows references to spill into the reference-only extra pages.
121
+
122
+ ## 5. Ship
123
+ - Rebuild the final PDF, upload to the camera-ready system (often the same HotCRP, or an ACM eRights /
124
+ TAPS pipeline β€” follow the copyright email).
125
+ - Complete the **ACM/IEEE eRights** copyright form β†’ paste the returned copyright block + DOI into the
126
+ \`.tex\` before the final build (ACM validates this).
127
+ - Verify the public artifact link resolves and the DOI is live before you submit the final PDF.
128
+ - Record the paper's DOI, the artifact DOI, and the ORCID in the paper's HANDOFF β€” those three IDs are
129
+ the authorship evidence and the anchor the extension (\`extend-paper\`) builds on.
130
+
131
+ ## 6. Record the verdict
132
+
133
+ πŸ”΄ LAST step, once the deliverable exists:
134
+
135
+ \`\`\`
136
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record camera-ready <paper-dir> FINDING <count> <report-path>
137
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record camera-ready <paper-dir> ABSTAINED <reason> "<one line>"
138
+ \`\`\`
139
+
140
+ **FINDING** β€” \`<count>\` residual items still open; \`<report-path>\` names them. Add \`--blocking\` for
141
+ anything that must not be pushed past: anonymization residue, a dead artifact link, or β€” on a
142
+ security paper β€” disclosure not yet complete.
143
+ **ABSTAINED** β€” \`no-witness\`: shipped, de-anonymized, DOI live, page limit re-checked, with the DOI
144
+ in the note. \`blocked\`: the acceptance notice has not arrived, so there is nothing to make ready.
145
+
146
+ πŸ”΄ That blocking finding is the only one in this pipeline whose consequence is **irreversible**. The
147
+ public de-anonymized repo is Google-findable the moment it is pushed, so record it before, not after.
148
+
149
+ πŸ”΄ **There is no PASS**, and on this skill that is not a formality: a stored "shipped" would have
150
+ been the one row in the pipeline that could be true of a repo nobody had looked at. The DOI in the
151
+ note is the witness. Without it there is nothing to check the row against.
152
+
153
+ ## Compose with
154
+ - **submit-paper** (upstream β€” this reverses what it anonymized).
155
+ - **paper-pipeline/references/anonymization.md** β€” the canonical list of anonymization moves; undo each.
156
+ - **extend-paper** (next β€” the accepted+indexed paper is the base for a second, stronger publication).
157
+
158
+ ## Provenance
159
+ Both portfolio papers are anonymized-for-review and **defer de-anonymization + the public artifact to
160
+ camera-ready by design**: AgenticDev "Measuring the Wrong Number" (submitted, camera-ready 28 Aug if
161
+ accepted) and AISec "Safety Theater" (ships an anonymized artifact; hook names anonymized; responsible
162
+ disclosure to named maintainers owed before any de-anonymized public release). ORCID is identical
163
+ across both so every indexed version resolves to one researcher.`,
164
+ });