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,155 @@
1
+ # REALM @ EMNLP — venue card
2
+
3
+ **Family: ACL.** Everything ACL-wide (appendix rule, Limitations/Ethics not counting, anonymity,
4
+ OpenReview mechanics) lives in `paper-pipeline/references/acl-venue-rules.md`. Only REALM-specific
5
+ facts are here.
6
+
7
+ Verified by direct fetch of `realm-workshop.github.io/call_for_papers` **2026-08-02 and 2026-08-03**
8
+ (twice, independently), plus a live pull of the OpenReview invitation schema.
9
+ 🔴 **Re-verify every cycle** — dates, limits and tracks move year to year.
10
+
11
+ ## The 2026 edition (2nd edition)
12
+
13
+ | field | value |
14
+ | -------------------------- | ------------------------------------------------------------------------------------------------------------- |
15
+ | full name | REALM — workshop at EMNLP 2026 |
16
+ | edition | **2nd** (a 1st-edition accepted corpus exists — mine it with `study-accepted-papers`, in SETUP) |
17
+ | direct submission deadline | **Wednesday 5 August 2026**, 23:59 **AoE** |
18
+ | → in the author's zone | at UTC+5: **6 August 2026, 16:59** (AoE = UTC−12; 5 Aug 23:59 AoE = 6 Aug 11:59 UTC) |
19
+ | ARR commitment deadline | 31 August 2026, same AoE convention |
20
+ | long paper | **8 pages of content** |
21
+ | short paper | 4 pages of content |
22
+ | refs + appendices | **unlimited** |
23
+ | camera-ready | **+1 page** (9 long / 5 short) |
24
+ | archival | optional at submission; archival → **ACL Anthology proceedings** |
25
+ | blind | **double-blind** — names and affiliations omitted |
26
+ | preprints | explicitly allowed, any time, provided the PDF does not link to de-anonymised info |
27
+ | portal | `openreview.net/group?id=EMNLP/2026/Workshop/REALM` |
28
+ | format | **PDF only** |
29
+ | mandatory sections | none beyond ACL's Limitations; _"authors are expected to attest to the ethical considerations in their work"_ |
30
+ | venue mode | hybrid; held Thursday 29 October, 9:00–17:30, Room P1 |
31
+
32
+ ## 🔴 The submission form has NO supplementary field
33
+
34
+ Pulled live from `api2.openreview.net/invitations?id=EMNLP/2026/Workshop/REALM/-/Submission`. The
35
+ form's **complete** field list:
36
+
37
+ ```
38
+ title · authors · authorids · keywords · TLDR · abstract · pdf ·
39
+ archival · cross_submission_to · serve_as_reviewer · venue · venueid
40
+ ```
41
+
42
+ There is **no Responsible NLP Checklist and no supplementary upload**. Two consequences:
43
+
44
+ 1. **The artifact must be hosted externally and anonymously**, with the URL inside the PDF. Budget
45
+ time for this — it is a submission blocker, and an artifact reviewer will refuse the Available
46
+ badge without a resolving URL.
47
+ 2. Do not confuse this route with **ARR**, whose portal _does_ have the checklist and separate
48
+ software/data uploads. Different portal, different process. A previous version of this project's
49
+ checklist conflated them.
50
+ 3. **No checklist field means no LLM-disclosure gate here**, and therefore no required placement for
51
+ it — put the disclosure in Limitations or Ethical considerations, both outside the page limit,
52
+ and keep it out of the reader's first contact with a measurement. Full rule, with the policy text
53
+ and the failure it was written from: `paper-pipeline/references/acl-venue-rules.md`, §GenAI / LLM
54
+ disclosure.
55
+
56
+ Note `keywords` is a form field, so the keyword line does **not** belong in the typeset PDF.
57
+
58
+ ## The submission form, field by field (filled 2026-08-06, ~15 min before deadline)
59
+
60
+ Transcribed from the live form while filling it. The API schema above lists field _names_; this is
61
+ what the form actually shows, in order, with what each one wants. A field's help text is quoted.
62
+
63
+ | # | field | required | type | what goes in |
64
+ | --- | ----------------------- | -------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
65
+ | 1 | **Title** | ✱ | one line | _"Add TeX formulas using $In-line$ or $$Block$$"_ — plain text otherwise. **Must match the PDF's title exactly**; a late title edit in the paper means re-uploading the PDF _and_ retyping this |
66
+ | 2 | **Authors** | ✱ | profile search | pre-filled with the submitting author. _"All authors must have an OpenReview profile prior to submitting"_ — a co-author without an active profile blocks the whole submission |
67
+ | 3 | **Keywords** | ✱ | comma-separated | free text, no controlled vocabulary. 🔴 **Because this is a form field, the keyword line does NOT belong in the typeset PDF** |
68
+ | 4 | **TL;DR** | — | one sentence, 🔴 **hard max 250 characters** | _"a short sentence describing your paper"_. The limit is **not in the help text** — it rejects on submit. Optional, but it is the first thing a bidding reviewer reads: name the mechanism, not the topic. Count the characters before pasting |
69
+ | 5 | **Abstract** | ✱ | markdown + TeX, Write/Preview tabs | paste the paper's abstract. Markdown emphasis renders; `**bold**` survives. Backticks render as code |
70
+ | 6 | **PDF** | ✱ | file upload | _"Upload a PDF file that ends with .pdf"_. No supplementary field anywhere on the form — see above |
71
+ | 7 | **Archival** | ✱ | radio: Archival / Non-archival | Archival → **ACL Anthology**. _"If your paper is a cross-submission (currently under review or already published at another venue), it cannot be archival, per ACL policies."_ Changeable at camera-ready |
72
+ | 8 | **Cross Submission To** | — | one line | leave **empty** unless the paper is genuinely under review elsewhere. Filling it forfeits archival |
73
+ | 9 | **Serve As Reviewer** | ✱ | profile search | _"reciprocal reviewing practice… nominate at least one author to serve as a reviewer using their OpenReview profile ID (e.g. ~First_Last1)"_. **A solo author nominates themself** — the field is required and there is nobody else |
74
+ | 10 | License | ✱ | fixed chip | **CC BY 4.0**, not editable |
75
+ | 11 | Readers | ✱ | fixed chips | `EMNLP 2026 Workshop REALM` + `authorids` |
76
+ | 12 | Signatures | ✱ | fixed chip | the submitting author |
77
+
78
+ Then **Submit** / Cancel. An Edit History block below repeats Readers + Signatures — informational.
79
+
80
+ 🔴 **The displayed deadline is NOT when writes stop.** An OpenReview invitation carries two dates
81
+ and the interface shows only the first:
82
+
83
+ | field | 2026 edition, UTC | at UTC+5 |
84
+ | -------------------------------------------------------------- | ----------------- | --------- |
85
+ | `duedate` — printed everywhere as the deadline | 2026-08-06 11:59 | **16:59** |
86
+ | `expdate` — when the invitation actually stops accepting edits | 2026-08-06 12:29 | **17:29** |
87
+
88
+ A **30-minute grace window**, undocumented in the CFP and invisible on the form. Read it before the
89
+ last hour, not after — it is the difference between shipping a fix and abandoning it:
90
+
91
+ ```
92
+ curl -sS "https://api2.openreview.net/invitations?id=<VENUE-PATH>/-/Submission" \
93
+ | python3 -c "import json,sys,datetime;[print(k, datetime.datetime.utcfromtimestamp(i[k]/1000)) \
94
+ for i in json.load(sys.stdin)['invitations'] for k in ('duedate','expdate') if i.get(k)]"
95
+ ```
96
+
97
+ Do **not** plan around it — a venue may set `expdate == duedate`, and 30 minutes is not a schedule.
98
+ Treat it as recovery room for a defect found at the buzzer. Re-read it every cycle.
99
+
100
+ **Traps hit for real:**
101
+
102
+ - 🔴 **The title lives in two places and they silently diverge.** A title change at T−14 min meant a
103
+ fresh PDF _and_ a retyped Title field. Change the paper first, rebuild, then fill the form — never
104
+ the other way round.
105
+ - 🔴 **"Serve As Reviewer" surprises solo authors, and it is not a formality — it enrols you.** It reads
106
+ as though it wants a colleague. It is required, and the answer for a one-author paper is your own
107
+ profile ID. **The day after submitting, the program chairs assign papers and set a review deadline**
108
+ (2026: submissions 5 Aug, reviews due 21 Aug AoE — sixteen days). Consequences to price in BEFORE
109
+ submitting, not after:
110
+ - **ACL's AI policy applies to the reviews.** Verbatim from the chairs' email: _"the use of
111
+ generative AI tools to write an entire review is prohibited. While such tools may be used for
112
+ minor editing (e.g., grammar or clarity), the content and assessment must be the reviewer's own."_
113
+ Every review hour is personal. The sanction for violating it lands on submissions to the next ARR
114
+ cycle — the same ecosystem the paper is in.
115
+ - **The workshop's PC roster is not published**, so the only durable proof of the service is a
116
+ Web of Science verified-review record: forward the chairs' thank-you email to
117
+ `reviews@webofscience.com`. Set that profile up BEFORE reviewing, not after.
118
+ - It is nonetheless a real judging credential, distinct from authorship. One submission closes two
119
+ criteria — but the reviewing window is not negotiable and may collide with other commitments.
120
+
121
+ 🔴 **Hit for real on `compile-rules-2026`.** This project had _decided on 2026-07-26 not to serve as
122
+ a REALM reviewer_, with three written reasons (no public roster, the window collides with an ASPLOS
123
+ artifact round, the AI policy makes it all personal hours). Eleven days later the required form field
124
+ enrolled him anyway, because the field was filled in from a submission checklist that did not know
125
+ about the decision. **A required form field can silently reverse a recorded decision.** Before
126
+ filling any required field, check whether the project has already decided that question.
127
+
128
+ - **Keywords are a form field, not paper content** — so anything in the PDF's keyword line is
129
+ duplicated dead weight. Keep the list in a non-typeset comment in the source and paste it here.
130
+ - **The abstract field accepts markdown**, so the source abstract can be pasted nearly verbatim.
131
+ Extracting it from the _built PDF_ instead is a mistake: a text extractor on the line-numbered
132
+ build interleaves the margin numbers and silently drops paragraphs.
133
+
134
+ ## The ARR route is not a free fallback
135
+
136
+ The 31 August "ARR commitment" deadline commits a paper **that has already been reviewed by ACL
137
+ Rolling Review**. It is not a second chance for a paper that was never submitted to ARR — that needs
138
+ an ARR submission first, on ARR's own cycle. Do not plan around it without checking the ARR calendar.
139
+
140
+ ## Gotchas hit for real
141
+
142
+ - **Deadline confusion.** The CFP prints "August 5th" and states the AoE rule in a _different_
143
+ sentence on the same page. A pass on 2026-07-31 concluded "AoE not stated, assume noon 5 Aug" and
144
+ was wrong by 29 hours. Read the whole page, then convert.
145
+ - **OpenReview profile moderation is the critical path**, not the writing. An independent author with
146
+ no institutional email and no DBLP record has no expedite route. Start the profile weeks ahead.
147
+ - The workshop's hybrid status is confirmed by REALM's **own** root page — do not carry it over from
148
+ EMNLP's general page.
149
+
150
+ ## Sources
151
+
152
+ - `realm-workshop.github.io/call_for_papers` — CFP (fetched 2026-08-02, 2026-08-03)
153
+ - `realm-workshop.github.io/` — root, hybrid confirmation
154
+ - `api2.openreview.net/invitations?id=…/-/Submission` — the live form schema
155
+ - Per-paper compliance state: `<paper-dir>/SUBMIT-CHECKLIST.md`
@@ -0,0 +1,50 @@
1
+ // The TeX Live packages EVERY paper gets — and ALL a paper gets when its venue is unknown (no
2
+ // venue.json, or a venue.json naming a venue with no profile here). A venue's own `tex.packages`
3
+ // is added on top of this set, never instead of it.
4
+ //
5
+ // Read by `paperlint toolchain` (it installs this set plus every venue's) and by `paperlint build` (it checks
6
+ // that the TeX Live it is about to use has this set plus the paper's venue's). Validated against
7
+ // venue-profile.schema.json next door.
8
+ //
9
+ // 🔴 THE CONTRACT IS THE FILES, NOT THE NAMES. A package name is what tlmgr is asked for; the
10
+ // files listed under it are what `kpsewhich` must find afterwards. An installer's exit code is not
11
+ // the criterion — on 2026-09-01 an apt step reported success having installed zero packages.
12
+ //
13
+ // What the base set is FOR: a plain `article` paper with the usual tools, typeset in Type 1 fonts.
14
+ // cm-super — without it pdflatex silently RASTERIZES Computer Modern in some contexts (a Type 3
15
+ // bitmap font in the PDF; measured 2026-09-01 on an ACL paper: 1 Type 3 font before, 0 after).
16
+ // ACM and ACL both reject such a PDF, and the build does not complain.
17
+ {
18
+ "tex": {
19
+ "packages": {
20
+ "latex": ["latex.ltx", "article.cls"],
21
+ "bibtex": ["plain.bst"],
22
+ "hyperref": ["hyperref.sty"],
23
+ "geometry": ["geometry.sty"],
24
+ "graphics": ["graphicx.sty"],
25
+ "tools": ["array.sty"],
26
+ "amsmath": ["amsmath.sty"],
27
+ "amsfonts": ["amssymb.sty"],
28
+ "url": ["url.sty"],
29
+ "xcolor": ["xcolor.sty"],
30
+ "booktabs": ["booktabs.sty"],
31
+ "natbib": ["natbib.sty"],
32
+ "microtype": ["microtype.sty"],
33
+ "caption": ["caption.sty"],
34
+ "enumitem": ["enumitem.sty"],
35
+ "xurl": ["xurl.sty"],
36
+ "pgf": ["tikz.sty"],
37
+ "seqsplit": ["seqsplit.sty"],
38
+ "cm-super": ["sfrm1000.pfb"],
39
+ },
40
+ // Programs the skills run over a paper, installed WITH TeX Live because they ARE TeX Live
41
+ // packages. The build does not need them, so a system TeX Live without them still builds.
42
+ // texcount — the word count a paper's length is measured by. Added to the old CTAN list on
43
+ // 2026-09-17 after a consumer's CI went red on a cache miss without it.
44
+ // checkcites — asks whether a bibliography entry is uncited.
45
+ "tools": {
46
+ "texcount": ["texcount"],
47
+ "checkcites": ["checkcites"],
48
+ },
49
+ },
50
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://github.com/zernie/research-paper-pipeline/venue-profile.schema.json",
4
+ "title": "Venue profile",
5
+ "description": "One venue's format profile (venues/<venue>.jsonc) and the TeX base set (venues/tex-base.jsonc). The format numbers are read by the consumer's pdf/profile rule; `tex` is read by `paperlint toolchain` and `paperlint build`.",
6
+ "type": "object",
7
+ "required": ["tex"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "tex": { "$ref": "#/definitions/tex" },
11
+ "template": {
12
+ "description": "The \\documentclass the venue's template uses.",
13
+ "type": "string",
14
+ "minLength": 1
15
+ },
16
+ "page_size": { "type": "string", "enum": ["letter", "a4"] },
17
+ "page_w_in": { "type": "number", "exclusiveMinimum": 0 },
18
+ "page_h_in": { "type": "number", "exclusiveMinimum": 0 },
19
+ "textblock_w_in": { "type": "number", "exclusiveMinimum": 0 },
20
+ "textblock_h_in": { "type": "number", "exclusiveMinimum": 0 },
21
+ "columns": { "type": "integer", "minimum": 1 },
22
+ "body_pt": { "type": "number", "exclusiveMinimum": 0 },
23
+ "body_pt_tol": { "type": "number", "minimum": 0 },
24
+ "ref_pt_min": { "type": "number", "exclusiveMinimum": 0 },
25
+ "ref_pt_max": { "type": "number", "exclusiveMinimum": 0 },
26
+ "fonts_text": { "type": "string", "minLength": 1 },
27
+ "fonts_title": { "type": "string", "minLength": 1 },
28
+ "page_limits_not_gated": { "type": "object" },
29
+ "kinds": {
30
+ "type": "object",
31
+ "additionalProperties": {
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "properties": {
35
+ "body_pages_max": { "type": "integer", "minimum": 1 },
36
+ "ref_pages_max": { "type": "integer", "minimum": 0 }
37
+ }
38
+ }
39
+ }
40
+ },
41
+ "definitions": {
42
+ "ctanName": {
43
+ "description": "A package name as tlmgr knows it (CTAN / TeX Live), not a distribution package name.",
44
+ "type": "string",
45
+ "pattern": "^[a-z0-9][a-z0-9.-]*$"
46
+ },
47
+ "proofs": {
48
+ "type": "array",
49
+ "minItems": 1,
50
+ "uniqueItems": true,
51
+ "items": { "type": "string", "minLength": 1, "pattern": "^[^/\\s]+$" }
52
+ },
53
+ "tex": {
54
+ "description": "The TeX Live packages this template needs. Each package maps to the files that PROVE it is present: `kpsewhich` must find every one after an install, or the install failed and says which package.",
55
+ "type": "object",
56
+ "required": ["packages"],
57
+ "additionalProperties": false,
58
+ "properties": {
59
+ "packages": {
60
+ "type": "object",
61
+ "minProperties": 1,
62
+ "propertyNames": { "$ref": "#/definitions/ctanName" },
63
+ "additionalProperties": { "$ref": "#/definitions/proofs" }
64
+ },
65
+ "tools": {
66
+ "description": "Packages that ship a PROGRAM rather than a file LaTeX loads. Proved by an executable of that name in TeX Live's bin directory, not by kpsewhich.",
67
+ "type": "object",
68
+ "propertyNames": { "$ref": "#/definitions/ctanName" },
69
+ "additionalProperties": { "$ref": "#/definitions/proofs" }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * submit-paper — the PAID tier: does this skill's description actually fire?
3
+ *
4
+ * COLOCATED ON PURPOSE (vigiles decides coverage by placement as of 2026-08-11).
5
+ * The prompts live in `.claude/lib/skill-trigger-cases.mjs` so all 21 cases
6
+ * are reviewed as one table where collisions between siblings are visible;
7
+ * copying them here would recreate the drift that rule exists to prevent.
8
+ *
9
+ * Measures recall (fires on its own territory) AND precision (stays quiet on a
10
+ * colliding sibling's territory), against the REAL `.claude` harness so the skill
11
+ * competes with every other installed description — an isolated run overstates
12
+ * recall and understates false positives.
13
+ *
14
+ * Costs money; not CI.
15
+ * node .claude/skills/submit-paper/submit-paper.eval.mjs [trials]
16
+ */
17
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
18
+
19
+ await runSkillTriggerEval("submit-paper");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * submit-paper — the free, deterministic tier. No model, no network.
3
+ *
4
+ * COLOCATED ON PURPOSE. vigiles decides coverage by PLACEMENT as of 2026-08-11:
5
+ * a test that merely names a surface no longer counts, because that tier was
6
+ * crediting surfaces nothing touched. So each skill needs a file inside its own
7
+ * directory — this one.
8
+ *
9
+ * The assertions live in `.claude/lib/skill-checks.mjs` and are CALLED here with
10
+ * this skill's name. They are not copied: 22 copies of the same checks is the drift that
11
+ * module exists to avoid. (Until 2026-08-11 this was an env-var side channel into a
12
+ * 614-line file named after no surface; it is a function call now.)
13
+ *
14
+ * What this proves: this skill's frontmatter parses as strict YAML, its declared
15
+ * tool contract is sane, its pipeline wiring points at scripts that exist, and it
16
+ * announces/records under ITS OWN identity rather than a sibling's.
17
+ *
18
+ * What it does NOT prove: that the skill fires, or that its guidance produces a
19
+ * good result. Those need a real model — see `submit-paper.eval.mjs`.
20
+ */
21
+ import { checkSkill } from "../../lib/skill-checks.mjs";
22
+
23
+ await checkSkill("submit-paper");
@@ -0,0 +1,269 @@
1
+ ---
2
+ name: sweep-design-space
3
+ description: Find a real MECHANISM for a problem — sweep the design space across type systems, formal verification, functional programming, capabilities, specification-by-example, data integrity, authoring UX, other professions (aviation/law/audit), and historical ancestors in SE — instead of circling the same two or three obvious options. Use when the deliverable needs a solution rather than a measurement, when the last few proposals all rhymed with each other, or when the user says "your options are stale / you're thinking narrowly / think fresh". Encodes the hard filters that kill most candidates (does it re-require the thing already measured as unworkable? is it occupied? who writes the formalization? does it demand a new format? unrepresentable or merely detectable?) and the ladder pattern for when one mechanism can't cover the range. Distinct from research-ideate (validates ONE idea you already have), map-prior-work (finds competitors for a claim), and analyze-sibling-paper (deep-reads one rival) — this one GENERATES candidate mechanisms and filters them.
4
+ context: fork
5
+ allowed-tools: [WebSearch, WebFetch, Read, Write, Grep, Glob, Bash, Agent]
6
+ ---
7
+
8
+ <!-- vigiles:sha256:1822c8c01e352f42 compiled from skills/sweep-design-space/SKILL.md.spec.ts -->
9
+
10
+ # sweep-design-space — stop circling, sweep
11
+
12
+ ## Run me
13
+
14
+ 🔴 FIRST, before any other step:
15
+
16
+ ```
17
+ node .claude/skills/paper-pipeline/scripts/announce.mjs sweep-design-space <dir>
18
+ ```
19
+
20
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
21
+ state — so starting is an event, and events get written down.
22
+
23
+ The `<dir>` argument is **optional in spirit**: this skill can run before a paper directory exists, so
24
+ pass whichever directory the work lives in, or `.`. The ledger row is written either way, and a plain
25
+ dot is more honest than an invented path.
26
+
27
+ A model asked for "a solution" returns the three designs nearest its training prior, then variations of
28
+ those, then variations of the variations. The user experiences this as *"you are thinking very narrowly"* —
29
+ and they are right. The fix is not to think harder in place; it is to **sweep named source domains on
30
+ purpose** and filter hard.
31
+
32
+ Grounding lesson (2026-07-29, `the reference paper`): four consecutive proposals were reformulations of
33
+ one idea ("check the prose"), and two of them turned out to be **already shipped in production** by
34
+ other people. The design space was never actually swept; it was sampled from memory.
35
+
36
+ ## When it fires
37
+
38
+ - The task needs a **mechanism**, not a measurement, and the mechanism isn't obvious.
39
+ - Your last two or three proposals rhyme with each other.
40
+ - The user pushes back with *"your options are stale / you're seeing only old solutions / think fresh"*.
41
+ - A measurement phase just finished and the paper/product needs a constructive half.
42
+ - 🔴 **You are about to recommend the first design you thought of.** That alone is the trigger.
43
+
44
+ ## How to run it
45
+
46
+ ### 1. State the defect as a STATE, not as a wish
47
+ Not "we want rules to be enforced". Write the exact state that must not exist:
48
+ > *a rule asserts an enforcement that nothing provides.*
49
+
50
+ Everything downstream is judged by whether it makes **that state** impossible.
51
+
52
+ ### 2. Write the hard filters BEFORE generating
53
+ Filters written after generation get bent to save a favourite. Standard ones — keep the ones that apply:
54
+
55
+ - **🔴 Does it re-require the thing you already measured as unworkable?** The sharpest filter and the
56
+ easiest to violate. In the grounding case, prose-to-checker synthesis was measured leaking at
57
+ **84–96%** — and half the proposed designs still began with *"parse the prose"*. If your evidence
58
+ says X doesn't work, a design that starts with X is dead **regardless of how elegant the rest is**.
59
+ - **Unrepresentable or merely detectable?** "We check for it afterwards" is a different (weaker) claim
60
+ than "it cannot occur". Say which one honestly.
61
+ - **Who produces the formalization — a model or a human?** This, not "is a model involved", is what
62
+ predicts leakage. Model-synthesized formalization leaks; human-written formalization does not leak,
63
+ it is merely expensive. Sort candidates by this.
64
+ - **Adoption cost.** Does it require a new format, a migration, or a new file? Count the artifacts
65
+ already in the wild that would have to move. A design requiring migration of a large installed base
66
+ has near-zero adoption regardless of merit.
67
+ - **Scope honesty.** Which fraction of the real population does it cover, and does it *silently* cover
68
+ nothing for the rest? Force each candidate to say "for class X it is silent."
69
+
70
+ ### 3. Sweep the catalog — the point of this skill
71
+ Take the groups below. For each, generate **3 candidates whose MECHANISMS differ** (three phrasings of
72
+ one idea is a failed group). Delegate to a subagent with **no thread context** — the thread is exactly
73
+ what anchors you — and hand it: the defect state, the hard filters, the measured constraints, and the
74
+ **already-considered list**.
75
+
76
+ 🔴 **Hand that list as "considered, and here is exactly why each was set aside" — never as a bare
77
+ ban.** A blanket prohibition is the wrong instrument, because some of those options were set aside
78
+ for a *bad* reason, and a *modification* of a rejected option is often the best thing in the sweep.
79
+ So the instruction to the agent is two-sided:
80
+
81
+ - returning a considered option **unchanged** is a failure — that is the laziness the list exists to
82
+ prevent;
83
+ - returning it **because you can attack the stated reason it was rejected**, or with a modification
84
+ that survives that reason, is a **first-class result** — say so explicitly in the brief.
85
+
86
+ This shape does something a ban cannot: it surfaces bad rejections. In the grounding session, one
87
+ option was discarded with the objection *"the generated file can still be hand-edited"* — an objection
88
+ already solved, years earlier, by a checksum on the generated section. Under a bare ban that option
89
+ stays dead forever, killed by a wrong reason nobody re-examines. **Record the reason next to every
90
+ retired option precisely so it can be attacked later.**
91
+
92
+ ### 4. Occupancy check BEFORE you fall in love
93
+ Every surviving candidate goes through a refutation-framed occupancy pass (*"find who already did
94
+ this"*, not *"confirm it's free"*). In the grounding case this killed the front-runner: the
95
+ `enforced-by:` tag design was **already shipped** — CI blocking PRs, reference resolution in Rust,
96
+ across several independent projects. "I don't know of such work" ≠ "no such work". Search GitHub code
97
+ search, not only papers: practice ships years before it is written up.
98
+
99
+ ### 5. Red-team the survivor
100
+ Separate subagent, framed to **break** it. See the paper corpus's own refutation rules (`CLAUDE.md` beside the papers).
101
+
102
+ ### 6. Save to the repo
103
+ A swept design space that lives only in a chat is re-swept from scratch next month. Write the map —
104
+ axes, cells, occupancy verdicts, what kills each — as a file, and record **which candidates were
105
+ retired and why**, so they are not proposed again.
106
+
107
+ ---
108
+
109
+ ## The catalog — source domains, with constructs named
110
+
111
+ Do not treat this as exhaustive; it is a floor, so the agent starts from named constructs instead of
112
+ inventing the list each time. Add groups when the problem calls for them.
113
+
114
+ ### A. Type systems and language design
115
+ Smart constructors · newtype and phantom types · GADTs · **typestate** · linear and affine types
116
+ (a permission that is *consumed*) · refinement types · totality checking · effects in the type ·
117
+ **parse-don't-validate** · make illegal states unrepresentable · instance resolution as a gate
118
+ (the operation *doesn't exist* when there is no backend for it).
119
+
120
+ ### B. Formal verification
121
+ Coq · Lean · **TLA+ and Alloy** (model the *process*, not the code) · model checking · SMT ·
122
+ **satisfiability as a meaningfulness test** (a constraint that removes no models is vacuous — a
123
+ mechanical vacuity check) · refinement (does the implementation refine the spec) · proof-carrying
124
+ artifacts · Design-by-Contract · **blame** (Findler & Felleisen — who is at fault at the boundary).
125
+
126
+ ### C. Functional programming
127
+ Free monads and DSL-as-data (one AST, many interpreters) · tagless-final · **session types**
128
+ (protocols as types — the natural home for "order of operations" rules) · algebraic effects ·
129
+ optics · **monoids and folds** (how do rules compose, merge, override?) · lattices and semilattices
130
+ (CRDT-style merge without conflict) · catamorphisms · **Curry–Howard** (rule as type, proof as value) ·
131
+ property laws · denotational semantics (a rule *is* the set it forbids; empty set = vacuous).
132
+
133
+ ### D. Capabilities and systems
134
+ Capability-based security · **reference monitor with complete mediation** · principle of least
135
+ authority · object capabilities · **grants instead of prohibitions** (if the file can only *grant*,
136
+ "don't do X" has no syntax) · sandboxing · seccomp/eBPF · information-flow control · taint.
137
+
138
+ ### E. Testing and specification by example
139
+ Property-based testing · metamorphic relations · golden/approval tests · **mutation testing as an
140
+ admission criterion** (a rule that kills no mutant is not admitted) · executable specifications ·
141
+ example pairs as the artifact with prose as caption (machine never reads the prose) ·
142
+ **A/B measurement of effect** (treat the artifact as opaque and measure whether it changes outcomes —
143
+ the one way to take unparseable prose seriously without parsing it).
144
+
145
+ ### F. Data integrity and databases
146
+ Constraints · **`ADD CONSTRAINT` validates existing rows** (you cannot add a constraint your current
147
+ data violates — near-universal in databases, near-absent everywhere else) · `NOT NULL` + foreign keys ·
148
+ schema and migrations · `NOT VALID` with a deadline · provenance and lineage · event sourcing ·
149
+ **store the thing as data with the human-readable file as a view**.
150
+
151
+ ### G. Human–system interaction (authoring)
152
+ Asymmetric cost (make the strong claim expensive and the weak one one click) · forced choice with no
153
+ escape hatch · **changing the default** rather than adding a gate · feedback at the moment of writing
154
+ (live "this would have matched: 0") · progressive disclosure · single entry point (the artifact can
155
+ only be created *from* an incident, never from imagination) · what code review, commit hooks and IDE
156
+ hints actually taught us about compliance.
157
+
158
+ ### H. Other professions — how they make an unenforceable norm unwritable
159
+ - **Aviation:** Minimum Equipment List — a defect is permitted only *with* a compensating procedure
160
+ and a **repair deadline** by category; expiry is automatic. Also checklists, and why they work.
161
+ - **Law:** *lex imperfecta* — an obligation with no sanction is a recognized category, not an
162
+ oversight. **Rules vs standards** (Kaplow 1992) — the ex-ante/ex-post distinction, half a century old.
163
+ Adjudicator: a standard must name who decides.
164
+ - **Audit/finance:** SOX controls — owner + frequency + **evidence artifact**, and two separate tests
165
+ (*design* and *operating effectiveness*). "The control exists" stops being a state; there are three.
166
+ - **Medicine:** protocols, contraindications, checklists, and the distinction between guideline and
167
+ protocol.
168
+ - **Safety standards:** MISRA (**decidable/undecidable** is an official per-rule label), DO-178C DAL
169
+ A–E, ISO 26262 ASIL, Common Criteria EAL — industries that already formalized *how strongly backed*
170
+ something is.
171
+ - **Construction codes, military ROE, accounting standards** — same question, different centuries.
172
+
173
+ ### I. 🔴 Historical ancestors in software engineering
174
+ **Assume the problem is old.** In the grounding case, a "novel" controlled-language idea turned out to
175
+ be a 1980s aerospace standard, and its ladder had been published in *Computational Linguistics* in 2014.
176
+ Look here **before** generating anything:
177
+
178
+ - **Gradual typing** — the canonical template for coexisting checked and unchecked in one artifact,
179
+ with an explicit boundary and blame, adopted across a huge installed base *because* it did not
180
+ require migration. If your problem is "some items are backed and some are not, and we cannot move
181
+ everyone", this is the closest ancestor that exists.
182
+ - **Gradual verification**, gradual refinement types.
183
+ - **Design by Contract** (Eiffel) and contract blame (Racket).
184
+ - **JML · SPARK Ada · ACSL · Dafny** — and specifically **SPARK's stone → bronze → silver → gold →
185
+ platinum**: a shipped, mechanically-defined ladder of assurance. Steal the shape.
186
+ - **Aspect-oriented programming** — cross-cutting requirements declared away from the code, and
187
+ **why it failed** (the failure is more instructive than the successes).
188
+ - **lint (Johnson, 1978)** — the original answer to "a rule the compiler does not check".
189
+ - **Assertions** (Floyd, Hoare) and how they became normal.
190
+ - **Literate programming**, doctest, executable documentation.
191
+ - **Requirements engineering** — *testable requirement* as a recognized category, traceability,
192
+ EARS, IEEE 830.
193
+
194
+ ### J. Migration and coexistence strategies
195
+ Not a mechanism but a shape most candidates need: strangler fig · feature flags · `NOT VALID`
196
+ constraints · gradual typing's boundary · deprecation with deadlines · advisory-then-enforcing rollout
197
+ (how linters actually ship a new rule) · opt-in tiers.
198
+
199
+ ---
200
+
201
+ ## The ladder pattern
202
+
203
+ When no single mechanism covers the range — the usual case — the answer is often a **graded scale**
204
+ rather than one gate. A ladder is only worth anything if every rung is:
205
+
206
+ 1. **decided mechanically** — no reading, no judgment, no model interpreting anything;
207
+ 2. **strictly stronger** than the rung below;
208
+ 3. **precedented** — name the ancestor (SPARK levels, DAL, MISRA decidable/undecidable, gradual typing's
209
+ typed/untyped boundary). A ladder with invented rungs is a taxonomy, and taxonomies are usually
210
+ occupied.
211
+
212
+ 🔴 And check whether the *ladder itself* is occupied for your object. Controlled-language scales and
213
+ assurance levels already exist; the question is whether anyone has carried them to your problem.
214
+
215
+ ---
216
+
217
+ ## Record the verdict
218
+
219
+ 🔴 LAST step, once the deliverable exists:
220
+
221
+ ```
222
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record sweep-design-space <dir> FINDING <count> <report-path>
223
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record sweep-design-space <dir> ABSTAINED <reason> "<one line>"
224
+ ```
225
+
226
+ 🔴 **There is no PASS.** A sweep that turns up survivors has not certified anything; it has found
227
+ candidates, and candidates are findings.
228
+
229
+ **FINDING** — the sweep produced something to act on; `<count>` is the number of survivors and
230
+ `<report-path>` the sweep, including the groups that yielded nothing. Add `--blocking` when the
231
+ whole sweep died on the filters — that is the loudest thing this skill can say.
232
+ **ABSTAINED** — `no-witness`: the sweep ran and neither found a survivor nor established that none
233
+ exists. `blocked`: there was no problem statement to sweep against.
234
+
235
+ The skill's own rules already say negative results count. The ledger is how that survives the session:
236
+ a recorded finding names the groups that were swept, so the next sweep starts from named constructs
237
+ instead of from memory — which is the failure mode this skill exists to break.
238
+
239
+ ## Rules
240
+
241
+ - **Name the forbidden options in the generation brief.** Without an explicit "do not return these"
242
+ list, a fresh agent returns your stale options with new names.
243
+ - **Generate with a context-free subagent.** The thread is the anchor you are trying to escape.
244
+ - **Three ideas per group must differ in MECHANISM**, not in phrasing.
245
+ - **Apply the "does it re-require the unworkable thing" filter first** — it is the one most often
246
+ violated, including by designs that feel elegant.
247
+ - **Occupancy before affection.** Search shipped code, not only literature.
248
+ - **Negative results count.** "This group yields nothing here" is a real finding; record it so the
249
+ group is not re-swept.
250
+ - **Prefer designs that work without anything understanding anything** — counting, required fields,
251
+ foreign keys, expiry dates, and grants do not leak. Interpretation does.
252
+ - **Say what each candidate is silent about.** A design that covers a quarter of the population and
253
+ says nothing about the rest is fine — undeclared silence is not.
254
+
255
+ ## Compose with
256
+ - `research-ideate` — validates ONE idea's research value; run after this picks a candidate.
257
+ - `map-prior-work` / `analyze-sibling-paper` — occupancy at the level of a paper's contribution.
258
+ - `build-benchmark` — once the mechanism exists, this measures it.
259
+ - `paper-adversarial-review` / `pc-panel-review` — red-team the survivor.
260
+
261
+ ## Provenance
262
+ Built 2026-07-29 during `the reference paper`, after a solution search stalled for hours. Four
263
+ consecutive proposals were the same idea reworded; when finally swept properly, a context-free agent
264
+ produced 24 candidates across 8 groups, of which the three least obvious came from **capabilities**
265
+ (the rule's text exists only as the monitor's refusal message — no prose is stored at all),
266
+ **databases** (`ADD CONSTRAINT` refuses when current data already violates), and
267
+ **specification-by-example** (measure the artifact's *effect* and never read it). None of the three
268
+ was reachable from the thread, and two of the thread's own front-runners turned out to be shipped
269
+ already. The catalog exists so the next sweep starts from named constructs instead of from memory.