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,19 @@
1
+ /**
2
+ * camera-ready β€” 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/camera-ready/camera-ready.eval.mjs [trials]
16
+ */
17
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
18
+
19
+ await runSkillTriggerEval("camera-ready");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * camera-ready β€” 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 `camera-ready.eval.mjs`.
20
+ */
21
+ import { checkSkill } from "../../lib/skill-checks.mjs";
22
+
23
+ await checkSkill("camera-ready");
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: cold-read-diff
3
+ description: Send just-changed paper prose to a reader with NO context and ask what each sentence claims β€” the only check that catches a sentence which is short, true, jargon-free and still meaningless to anyone who does not already know the idea. Run after every prose edit to a paper, before calling the edit done, and before reporting a section as fixed. Scoped to the diff, so it is cheap enough to run every time. Not a writing grade (grade-paper-writing), not a structural pass (tighten-paper), not a defect review.
4
+ context: fork
5
+ allowed-tools: [Bash, Read, Agent]
6
+ ---
7
+
8
+ <!-- vigiles:sha256:f3c36e3e56bbd3cd compiled from skills/cold-read-diff/SKILL.md.spec.ts -->
9
+
10
+ # cold-read-diff β€” the reader who cannot fake understanding
11
+
12
+ ## Run me
13
+
14
+ πŸ”΄ FIRST, before any other step:
15
+
16
+ ```
17
+ node .claude/skills/paper-pipeline/scripts/announce.mjs cold-read-diff <paper-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 failure this exists for
24
+
25
+ On 2026-08-05 the author of `the reference paper` found eleven unreadable passages by eye, in a paper
26
+ that had passed six writing grades, four structural passes and five review panels. Every one of them
27
+ was short, factually correct, free of every word on the jargon list, and inside every mechanical
28
+ threshold. Samples, with his reactions:
29
+
30
+ > *"The state to remove is therefore not the rule but its claim about itself"* β€” **Β«wtfΒ»**
31
+ > *"these files are filled with constructions nobody built"* β€” **Β«wtfΒ»**
32
+ > *"Three answers, all of them after the fact"* β€” **Β«VAGUE AFΒ»**
33
+ > *"Both numbers carry a caveat…"* β€” **Β«WTF.Β»**
34
+
35
+ They share one property: **they parse only for a reader who already holds the idea.** That is not a
36
+ style defect and no metric can see it. Sentence length, number density, hedge share, tic frequency β€”
37
+ all green on every one of these.
38
+
39
+ ## Why the existing pipeline could not catch it
40
+
41
+ Every reader in it knows too much or cannot read at all:
42
+
43
+ | reader | holds the idea? | can judge meaning? |
44
+ |---|---|---|
45
+ | the author | maximally β€” that is the curse of knowledge | yes |
46
+ | the persona subagent | **yes: it is handed the paper and the framing** | yes |
47
+ | the review panel | yes | yes |
48
+ | `prose-lint` | no | **no β€” it counts patterns** |
49
+
50
+ The gap between "knows too much" and "cannot read" is exactly where these sentences live. Closing it
51
+ needs a reader who is competent and **structurally uninformed**, and the only way to guarantee that
52
+ is to withhold the context rather than ask them to ignore it.
53
+
54
+ ## Why the DIFF, and not the paper
55
+
56
+ A full cold read costs a long agent run, so it gets run once a day, which means prose written after
57
+ it ships unread. Scoped to the changed paragraphs it costs a couple of minutes, so it runs every
58
+ time β€” and coverage beats depth here, because the defect is per-sentence.
59
+
60
+ Scoping also makes the check honest. Hand an agent the whole paper and it reconstructs the idea from
61
+ the surrounding text, then reports that the sentence is clear. Hand it three paragraphs and there is
62
+ nothing to reconstruct from: if the sentence does not carry its own meaning, the agent cannot invent
63
+ one, and its confusion is the finding.
64
+
65
+ ## How to run it
66
+
67
+ 1. **Take the diff.** `git diff -U0 -- <paper.md>` since the last commit, or the `new_string` of the
68
+ edits just applied. Prose only β€” skip comments, tables, bibliography.
69
+ 2. **Spawn ONE agent with no repository context.** Give it the changed paragraphs **as text in the
70
+ prompt**, not as a file path. A path is an invitation to read the neighbours, and reading the
71
+ neighbours is how the check fails silently. `sonnet` is the right model: competent, cheap,
72
+ and not the one that wrote the sentence.
73
+ 3. **Ask exactly two questions per sentence:**
74
+ - *What does this sentence claim? Restate it in your own words.* If restating requires guessing,
75
+ the answer is `CANNOT PARSE` plus what stopped them β€” an undefined term, a pronoun with no
76
+ referent, a number with no denominator, two clauses that do not connect.
77
+ - *Would a reader who stops here understand it?* Yes / No / Only-if-they-know-X.
78
+ 4. **Ask for the dangerous class explicitly:** *which sentences sound clever but say less than they
79
+ appear to?* Those read fine and carry nothing, and they are the ones a knowing reader waves
80
+ through.
81
+ 5. **Apply the fixes β€” as rewrites of the whole thought, never as excisions.** See the rule below.
82
+ 6. **Re-run on the fix.** An edit is not done until the same kind of reader parses the replacement.
83
+ One confirming round; do not loop past it.
84
+
85
+ ## πŸ”΄ Hand the reader WHOLE PARAGRAPHS, never `+` lines
86
+
87
+ Measured on 2026-08-05, first machine run of this skill: about a third of the reader's stalls were
88
+ artefacts of the extract, not defects in the paper β€” *"`it` has no referent"*, *"this sentence is cut
89
+ off mid-clause"*, *"those populations have no antecedent"*. The neighbouring sentences simply had not
90
+ changed, so they were not in the diff.
91
+
92
+ Two more things the same run proved:
93
+
94
+ - **Expand build-time macros first.** The reader saw seven raw `{{placeholders}}` and correctly
95
+ reported that every headline number was missing. That is a true statement about the extract and a
96
+ false one about the paper.
97
+ - **Strip working comments.** He graded `<!-- JUSTIFY … -->` notes as prose because he could not tell
98
+ them apart β€” and said so, which is itself a finding about the extract.
99
+
100
+ **So:** take the changed lines, then widen each to its enclosing paragraph, expand macros, drop
101
+ comments, and hand the reader continuous prose. The findings that survive that are worth the run; the
102
+ ones that do not are noise, and noise is how this check gets muted.
103
+
104
+ ## Record the verdict
105
+
106
+ πŸ”΄ LAST step, once the deliverable exists:
107
+
108
+ ```
109
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record cold-read-diff <paper-dir> FINDING <count> <report-path>
110
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record cold-read-diff <paper-dir> ABSTAINED <reason> "<one line>"
111
+ ```
112
+
113
+ **FINDING** β€” `<count>` is the number of changed sentences the cold reader could not restate (every
114
+ `CANNOT PARSE` counts), `<report-path>` is the `reviews/*cold-read*.md` file.
115
+ **ABSTAINED** β€” `no-witness`: every changed sentence came back restated correctly.
116
+ `input-missing`: the diff held no prose to read.
117
+
118
+ πŸ”΄ These two are different answers and the difference is the whole reason the vocabulary is closed:
119
+ one says a reader read it and found nothing, the other says there was nothing to hand a reader.
120
+ Prose collapses them and the old `PASS`/`ABSENT` pair only half-separated them, because `PASS` also
121
+ got recorded when nobody had run a reader at all. There is no `PASS` now; the reason is the answer.
122
+
123
+ ## Rules
124
+
125
+ - πŸ”΄ **No context in the prompt. Ever.** Not the title, not the abstract, not "this is a paper about
126
+ agent rules files". Every sentence of background handed to the reader is a sentence of confusion
127
+ they will no longer report.
128
+ - πŸ”΄ **A fix that removes the flagged construction and keeps the compression is not a fix.** Proven
129
+ twice in one hour: *"not through any defect in how we write it, but because that is what English
130
+ is"* β†’ *"that is what English is for"* (tic gone, meaning inverted into nonsense); *"the agent
131
+ turns out not to be the weak link"* β†’ *"The agent obeys"* (three words, zero flags, wrong finding).
132
+ Rewrite the **thought** in plain words. The tic is usually a symptom of a compressed idea, and
133
+ decompressing removes it as a side effect.
134
+ - **Length is not the constraint here β€” meaning is.** If plain language needs more words, take them
135
+ and pay from an appendix, which is outside the page limit. Paying by shortening another sentence
136
+ is what created the problem.
137
+ - **`CANNOT PARSE` is a result, not a failure of the reader.** Never argue with it. The author's
138
+ ability to understand his own sentence is not evidence about anyone else's.
139
+ - **Run it on your own fixes too.** The author is the least qualified judge of whether his repair
140
+ reads, and that is exactly when he feels most certain.
141
+
142
+ ## Enforcement
143
+
144
+ `pipeline-check.mjs` raises `stale-cold-read` when the newest `reviews/*cold-read*.md` is older than
145
+ the paper source, and `no-cold-read` when none exists. The date comparison is the whole mechanism:
146
+ a cold read that predates the current text describes prose that no longer exists.
147
+
148
+ ## Compose with
149
+
150
+ - `grade-paper-writing` β€” the batch readability gate; this is its continuous counterpart. That one
151
+ produces a stall inventory over the whole paper; this one asks whether the last edit means anything.
152
+ - `tighten-paper` β€” structural cuts. Note the interaction: a tighten pass that pays for an addition
153
+ by shortening sentences elsewhere is precisely what generates work for this skill.
154
+ - `paper-pipeline` β€” owns the text-pass / evidence-pass split; this belongs to the text pass.
155
+
156
+ ## Provenance
157
+
158
+ Built 2026-08-05, the day before the `the reference paper` deadline, after the corpus owner read the built PDF and
159
+ found eleven unreadable passages in twenty minutes β€” none of which any automated check had flagged,
160
+ and several of which had been introduced that same morning by fixes to other automated checks.
@@ -0,0 +1,166 @@
1
+ // Compiled to SKILL.md by `vigiles compile`. Edit THIS file, never the markdown.
2
+ //
3
+ // Adopted 2026-08-17. Body VERBATIM from the previous SKILL.md. This is the only one
4
+ // of the batch that runs FORKED β€” `context: "fork"` is what gives a skill a real
5
+ // call→return boundary, so it is carried explicitly rather than dropped.
6
+ import { experimental_skill } from "vigiles/spec";
7
+
8
+ export default experimental_skill({
9
+ name: "cold-read-diff",
10
+ description:
11
+ "Send just-changed paper prose to a reader with NO context and ask what each sentence claims β€” the only check that catches a sentence which is short, true, jargon-free and still meaningless to anyone who does not already know the idea. Run after every prose edit to a paper, before calling the edit done, and before reporting a section as fixed. Scoped to the diff, so it is cheap enough to run every time. Not a writing grade (grade-paper-writing), not a structural pass (tighten-paper), not a defect review.",
12
+ context: "fork",
13
+ tools: ["Bash", "Read", "Agent"],
14
+ body: `
15
+ # cold-read-diff β€” the reader who cannot fake understanding
16
+
17
+ ## Run me
18
+
19
+ πŸ”΄ FIRST, before any other step:
20
+
21
+ \`\`\`
22
+ node .claude/skills/paper-pipeline/scripts/announce.mjs cold-read-diff <paper-dir>
23
+ \`\`\`
24
+
25
+ An advisory pass cannot be observed failing β€” silence is both its error state and its normal
26
+ state β€” so starting is an event, and events get written down.
27
+
28
+ ## The failure this exists for
29
+
30
+ On 2026-08-05 the author of \`the reference paper\` found eleven unreadable passages by eye, in a paper
31
+ that had passed six writing grades, four structural passes and five review panels. Every one of them
32
+ was short, factually correct, free of every word on the jargon list, and inside every mechanical
33
+ threshold. Samples, with his reactions:
34
+
35
+ > *"The state to remove is therefore not the rule but its claim about itself"* β€” **Β«wtfΒ»**
36
+ > *"these files are filled with constructions nobody built"* β€” **Β«wtfΒ»**
37
+ > *"Three answers, all of them after the fact"* β€” **Β«VAGUE AFΒ»**
38
+ > *"Both numbers carry a caveat…"* β€” **Β«WTF.Β»**
39
+
40
+ They share one property: **they parse only for a reader who already holds the idea.** That is not a
41
+ style defect and no metric can see it. Sentence length, number density, hedge share, tic frequency β€”
42
+ all green on every one of these.
43
+
44
+ ## Why the existing pipeline could not catch it
45
+
46
+ Every reader in it knows too much or cannot read at all:
47
+
48
+ | reader | holds the idea? | can judge meaning? |
49
+ |---|---|---|
50
+ | the author | maximally β€” that is the curse of knowledge | yes |
51
+ | the persona subagent | **yes: it is handed the paper and the framing** | yes |
52
+ | the review panel | yes | yes |
53
+ | \`prose-lint\` | no | **no β€” it counts patterns** |
54
+
55
+ The gap between "knows too much" and "cannot read" is exactly where these sentences live. Closing it
56
+ needs a reader who is competent and **structurally uninformed**, and the only way to guarantee that
57
+ is to withhold the context rather than ask them to ignore it.
58
+
59
+ ## Why the DIFF, and not the paper
60
+
61
+ A full cold read costs a long agent run, so it gets run once a day, which means prose written after
62
+ it ships unread. Scoped to the changed paragraphs it costs a couple of minutes, so it runs every
63
+ time β€” and coverage beats depth here, because the defect is per-sentence.
64
+
65
+ Scoping also makes the check honest. Hand an agent the whole paper and it reconstructs the idea from
66
+ the surrounding text, then reports that the sentence is clear. Hand it three paragraphs and there is
67
+ nothing to reconstruct from: if the sentence does not carry its own meaning, the agent cannot invent
68
+ one, and its confusion is the finding.
69
+
70
+ ## How to run it
71
+
72
+ 1. **Take the diff.** \`git diff -U0 -- <paper.md>\` since the last commit, or the \`new_string\` of the
73
+ edits just applied. Prose only β€” skip comments, tables, bibliography.
74
+ 2. **Spawn ONE agent with no repository context.** Give it the changed paragraphs **as text in the
75
+ prompt**, not as a file path. A path is an invitation to read the neighbours, and reading the
76
+ neighbours is how the check fails silently. \`sonnet\` is the right model: competent, cheap,
77
+ and not the one that wrote the sentence.
78
+ 3. **Ask exactly two questions per sentence:**
79
+ - *What does this sentence claim? Restate it in your own words.* If restating requires guessing,
80
+ the answer is \`CANNOT PARSE\` plus what stopped them β€” an undefined term, a pronoun with no
81
+ referent, a number with no denominator, two clauses that do not connect.
82
+ - *Would a reader who stops here understand it?* Yes / No / Only-if-they-know-X.
83
+ 4. **Ask for the dangerous class explicitly:** *which sentences sound clever but say less than they
84
+ appear to?* Those read fine and carry nothing, and they are the ones a knowing reader waves
85
+ through.
86
+ 5. **Apply the fixes β€” as rewrites of the whole thought, never as excisions.** See the rule below.
87
+ 6. **Re-run on the fix.** An edit is not done until the same kind of reader parses the replacement.
88
+ One confirming round; do not loop past it.
89
+
90
+ ## πŸ”΄ Hand the reader WHOLE PARAGRAPHS, never \`+\` lines
91
+
92
+ Measured on 2026-08-05, first machine run of this skill: about a third of the reader's stalls were
93
+ artefacts of the extract, not defects in the paper β€” *"\`it\` has no referent"*, *"this sentence is cut
94
+ off mid-clause"*, *"those populations have no antecedent"*. The neighbouring sentences simply had not
95
+ changed, so they were not in the diff.
96
+
97
+ Two more things the same run proved:
98
+
99
+ - **Expand build-time macros first.** The reader saw seven raw \`{{placeholders}}\` and correctly
100
+ reported that every headline number was missing. That is a true statement about the extract and a
101
+ false one about the paper.
102
+ - **Strip working comments.** He graded \`<!-- JUSTIFY … -->\` notes as prose because he could not tell
103
+ them apart β€” and said so, which is itself a finding about the extract.
104
+
105
+ **So:** take the changed lines, then widen each to its enclosing paragraph, expand macros, drop
106
+ comments, and hand the reader continuous prose. The findings that survive that are worth the run; the
107
+ ones that do not are noise, and noise is how this check gets muted.
108
+
109
+ ## Record the verdict
110
+
111
+ πŸ”΄ LAST step, once the deliverable exists:
112
+
113
+ \`\`\`
114
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record cold-read-diff <paper-dir> FINDING <count> <report-path>
115
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record cold-read-diff <paper-dir> ABSTAINED <reason> "<one line>"
116
+ \`\`\`
117
+
118
+ **FINDING** β€” \`<count>\` is the number of changed sentences the cold reader could not restate (every
119
+ \`CANNOT PARSE\` counts), \`<report-path>\` is the \`reviews/*cold-read*.md\` file.
120
+ **ABSTAINED** β€” \`no-witness\`: every changed sentence came back restated correctly.
121
+ \`input-missing\`: the diff held no prose to read.
122
+
123
+ πŸ”΄ These two are different answers and the difference is the whole reason the vocabulary is closed:
124
+ one says a reader read it and found nothing, the other says there was nothing to hand a reader.
125
+ Prose collapses them and the old \`PASS\`/\`ABSENT\` pair only half-separated them, because \`PASS\` also
126
+ got recorded when nobody had run a reader at all. There is no \`PASS\` now; the reason is the answer.
127
+
128
+ ## Rules
129
+
130
+ - πŸ”΄ **No context in the prompt. Ever.** Not the title, not the abstract, not "this is a paper about
131
+ agent rules files". Every sentence of background handed to the reader is a sentence of confusion
132
+ they will no longer report.
133
+ - πŸ”΄ **A fix that removes the flagged construction and keeps the compression is not a fix.** Proven
134
+ twice in one hour: *"not through any defect in how we write it, but because that is what English
135
+ is"* β†’ *"that is what English is for"* (tic gone, meaning inverted into nonsense); *"the agent
136
+ turns out not to be the weak link"* β†’ *"The agent obeys"* (three words, zero flags, wrong finding).
137
+ Rewrite the **thought** in plain words. The tic is usually a symptom of a compressed idea, and
138
+ decompressing removes it as a side effect.
139
+ - **Length is not the constraint here β€” meaning is.** If plain language needs more words, take them
140
+ and pay from an appendix, which is outside the page limit. Paying by shortening another sentence
141
+ is what created the problem.
142
+ - **\`CANNOT PARSE\` is a result, not a failure of the reader.** Never argue with it. The author's
143
+ ability to understand his own sentence is not evidence about anyone else's.
144
+ - **Run it on your own fixes too.** The author is the least qualified judge of whether his repair
145
+ reads, and that is exactly when he feels most certain.
146
+
147
+ ## Enforcement
148
+
149
+ \`pipeline-check.mjs\` raises \`stale-cold-read\` when the newest \`reviews/*cold-read*.md\` is older than
150
+ the paper source, and \`no-cold-read\` when none exists. The date comparison is the whole mechanism:
151
+ a cold read that predates the current text describes prose that no longer exists.
152
+
153
+ ## Compose with
154
+
155
+ - \`grade-paper-writing\` β€” the batch readability gate; this is its continuous counterpart. That one
156
+ produces a stall inventory over the whole paper; this one asks whether the last edit means anything.
157
+ - \`tighten-paper\` β€” structural cuts. Note the interaction: a tighten pass that pays for an addition
158
+ by shortening sentences elsewhere is precisely what generates work for this skill.
159
+ - \`paper-pipeline\` β€” owns the text-pass / evidence-pass split; this belongs to the text pass.
160
+
161
+ ## Provenance
162
+
163
+ Built 2026-08-05, the day before the \`the reference paper\` deadline, after the corpus owner read the built PDF and
164
+ found eleven unreadable passages in twenty minutes β€” none of which any automated check had flagged,
165
+ and several of which had been introduced that same morning by fixes to other automated checks.`,
166
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * cold-read-diff β€” 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/cold-read-diff/cold-read-diff.eval.mjs [trials]
16
+ */
17
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
18
+
19
+ await runSkillTriggerEval("cold-read-diff");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * cold-read-diff β€” 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 `cold-read-diff.eval.mjs`.
20
+ */
21
+ import { checkSkill } from "../../lib/skill-checks.mjs";
22
+
23
+ await checkSkill("cold-read-diff");
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: draft-paper
3
+ description: Use when the numbers exist and it's time to WRITE the paper β€” "draft the paper", "turn these findings into a submission", "write the abstract/intro/threats". Gives the section skeleton of a measurement/benchmark paper plus what gets it accepted AND cited β€” precise claim-sizing (including an explicit "what we do NOT claim"), a construct-validity frame, an honest threats-to-validity section that turns limitations in your favor, and one memorable stat that travels. Encodes the two theses that carried real measurement papers ("measuring the wrong number", "safety theater"). NOT for grading finished prose (grade-paper-writing) or structural editing (tighten-paper) β€” this is the generative counterpart. Compose with build-benchmark (numbers), grade-paper-writing (prose QA), render-paper, verify-citations, then the review skills.
4
+ allowed-tools: [Read, Write, Edit, Grep, Glob, Agent, Skill, Bash(node .claude/skills/paper-pipeline/scripts/announce.mjs:*), Bash(node .claude/skills/paper-pipeline/scripts/ledger.mjs:*)]
5
+ ---
6
+
7
+ <!-- vigiles:sha256:1b6a7bdc0ea402ec compiled from skills/draft-paper/SKILL.md.spec.ts -->
8
+
9
+ # draft-paper β€” prose that survives review and gets cited
10
+
11
+ ## Run me
12
+
13
+ πŸ”΄ FIRST, before any other step:
14
+
15
+ ```
16
+ node .claude/skills/paper-pipeline/scripts/announce.mjs draft-paper <paper-dir>
17
+ ```
18
+
19
+ An advisory pass cannot be observed failing β€” silence is both its error state and its normal
20
+ state β€” so starting is an event, and events get written down.
21
+
22
+ A measurement paper lives or dies on two things reviewers actually reward: a **reusable method/norm**
23
+ they can apply to the next system, and **claim-sizing so precise it can't be attacked**. Numbers alone
24
+ are a blog post. This skill turns `build-benchmark`'s output into that kind of draft.
25
+
26
+ The bar is not "is the result true" β€” it's "will a stranger cite this in two years." That happens when
27
+ you gave them a *way to measure something* or a *bound they can quote*, not a verdict on one tool.
28
+
29
+ ## Section skeleton (measurement/benchmark paper)
30
+ Write in this order; it's also roughly the read order a reviewer skims.
31
+
32
+ πŸ”΄ **Decide body vs appendix as you write, not when the page limit forces it** β€”
33
+ `paper-pipeline/references/body-vs-appendix.md`. A page limit with no rule behind it evicts whatever
34
+ was written last, which is reliably the honest qualification nobody had room for. The rule in one
35
+ line: the body carries everything a reviewer's decision depends on, and **a bound that narrows a
36
+ number in the body stays in the body**.
37
+
38
+ 1. **Abstract** β€” the ONE contribution, sized. Problem β†’ the method/insight β†’ the single headline
39
+ number β†’ what it means. Tight (see "Scope the abstract" below).
40
+ 2. **Introduction + contributions** β€” the gap (what everyone measures / assumes today and why it's
41
+ wrong or unmeasured), then a bulleted **contributions** list. Each contribution is a *thing you
42
+ built or established* (a method, a benchmark, a bound, a norm), not "we ran experiments."
43
+ 3. **Background + threat model** (security) / **Setup** (non-security) β€” define terms, the system under
44
+ study, and β€” for security β€” the explicit threat model (attacker goals/capabilities/knowledge). A
45
+ fuzzy threat model is the fastest reject at a security venue.
46
+ 4. **Method** β€” the reusable core. How the measurement/benchmark is *constructed* so someone else can
47
+ run it on a different target. This is the part that gets cited; give it the most care.
48
+ 5. **Results** β€” the numbers from `build-benchmark`, each tied to a claim. Report ranges/CIs, not
49
+ rounded maxes. One figure or table carries the paper β€” make it legible standalone.
50
+ 6. **Threats to validity** β€” construct / internal / external, honestly (see below). This section is a
51
+ trust signal, not a confession.
52
+ 7. **Related work** β€” position against the *nearest* neighbor explicitly ("X measures A; we measure B
53
+ because A is the wrong number"). Credit generously; that's where the framing lands.
54
+ 8. **Ethics** (security papers) β€” responsible disclosure, who could be harmed, punching-down check.
55
+ Point to `paper-pipeline/references/anonymization.md` before naming any real system/maintainer.
56
+ 9. **Conclusion** β€” restate the method and the one insight; no new claims.
57
+ 10. **Availability** β€” the anonymized artifact link (see `submit-paper`). Reviewers reward a runnable
58
+ artifact more than another paragraph.
59
+
60
+ ## What makes it ACCEPTED and CITED
61
+ - **A reusable method/norm over a one-off result.** "Tool Y scores 40%" dies; "here's how to measure
62
+ Z, and by it Y scores 40%" survives, because the method outlives Y. Frame every result as an instance
63
+ of a general procedure.
64
+ - **A crisp, generalizable bound or insight** the reader can quote without your paper open β€” one
65
+ sentence they'll paraphrase back to you in review. That sentence is the abstract's spine.
66
+ - **Precise claim-sizing.** Say exactly how big the claim is and no bigger. Include an explicit
67
+ **"What we do NOT claim"** paragraph β€” it pre-empts Reviewer 2's whole attack surface and reads as
68
+ rigor, not weakness. (Both real papers have one; it's the highest-leverage paragraph in the draft.)
69
+ - **A construct-validity frame.** State plainly what quantity you're measuring and why it's the *right*
70
+ quantity β€” "measuring the wrong number" only works if you've defined the right one. Make the mapping
71
+ from concept β†’ metric explicit; that's what separates a benchmark from a leaderboard.
72
+ - **An honest threats section that turns limitations in your favor.** Every limitation you name first,
73
+ bounded, is one a reviewer can't wield against you. "N is small, so we claim a lower bound not a
74
+ point estimate" converts a weakness into a scoped claim. Don't hide; scope.
75
+ - **One memorable stat or figure that travels.** Pick the single number/image that survives out of
76
+ context (a tweet, a related-work sentence in someone else's paper). Everything else supports it.
77
+ - **Credit-the-humans tone.** Dunk on the *claim or the metric*, never the authors. "The field measures
78
+ X; X is the wrong number" β€” not "prior work is naive." Punching down reads as insecurity and invites
79
+ a hostile review; generous framing invites a citation.
80
+
81
+ ## Scope the abstract tightly
82
+ The abstract sells ONE contribution and ONE headline number. Do **not** cram every hedged sub-result β€”
83
+ each extra qualified number dilutes the one that matters and invites nitpicks before the reviewer
84
+ reaches the method. Hedge in Results/Threats, not the abstract. If you can't say the contribution in one
85
+ sentence, you haven't found it yet β€” go back to the method. Structure it against the five-move template
86
+ (context β†’ gap β†’ approach β†’ one number β†’ so-what) in `../paper-pipeline/references/writing-craft.md`, which
87
+ also holds the craft rules and the writing rubric `grade-paper-writing` grades against β€” write toward the
88
+ grade.
89
+
90
+ ## Run the prose through the PAPER suite's QA (do not skip β€” and do not use the blog skills)
91
+ Before any review pass, run the draft through the paper-side prose QA β€” it catches what a self-read won't:
92
+ - **`grade-paper-writing`** β€” the 9-dim rubric + the PERSONA cold-read stall pass (a committed
93
+ non-academic persona, per-section β€” the localized "wait, what does that even mean?" axis authors are
94
+ blind to). Its avoid-list grep also strips the AI-writing tropes (hedge-stacking, "it's worth
95
+ noting", limp connectives, fake balance) that make a draft read unserious to a human PC.
96
+ - **`../paper-pipeline/references/writing-craft.md`** β€” write toward the rubric; its
97
+ register-calibration buckets decide which jargon to keep / gloss / rename for the venue's actual reader.
98
+
99
+ **Boundary:** the site repo's `writing-quality` + `audience-test` skills are for **blog posts only**.
100
+ For papers they duplicate β€” and are superseded by β€” `grade-paper-writing` + writing-craft's persona
101
+ pass (the blog skills lack the persona fix, so they under-fire on paper prose). Never route paper
102
+ prose QA to them.
103
+
104
+ ## Record the verdict
105
+
106
+ πŸ”΄ LAST step, once the deliverable exists:
107
+
108
+ ```
109
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record draft-paper <paper-dir> FINDING <count> <report-path>
110
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record draft-paper <paper-dir> ABSTAINED <reason> "<one line>"
111
+ ```
112
+
113
+ This skill generates rather than judges, so what it records is about the run, not about the paper.
114
+
115
+ **FINDING** β€” it declined to draft because a required input was missing: no numbers from
116
+ `build-benchmark`, or an empty `frame` paragraph from `argument-arc`. `--blocking`, always, because
117
+ drafting past it produces prose about numbers that do not exist.
118
+ **ABSTAINED** β€” `no-witness`: sections were written and the generator has nothing to report about
119
+ the paper. Put the drafted sections in the note; they are the deliverable, not evidence of a defect.
120
+
121
+ πŸ”΄ **Design smell, stated plainly: this gate will almost always record an abstention**, and
122
+ `status.mjs` will flag it as one that has never returned a finding. Leave the flag standing β€” it is
123
+ telling the truth. A generator is not a gate, and the only honest negative it can produce is the
124
+ refusal above. If a run ever ends with prose written from numbers that do not exist, that is a
125
+ `FINDING --blocking` and must be recorded as one rather than quietly upgraded.
126
+
127
+ πŸ”΄ Deleting `PASS` did not fix this skill and was never going to: the old vocabulary let it write
128
+ down "I produced sections" as though that were an answer about the manuscript, and the new one
129
+ simply refuses to. The generator is still not a gate. `draft-paper/population-map` β€” a real check β€”
130
+ is the row that can say no about this skill's output.
131
+
132
+ ## Compose with
133
+ - **`build-benchmark`** β€” its numbers/CIs are the Results section's raw material; never hand-type a
134
+ number that isn't in its output (that's how paper↔artifact mismatches get born).
135
+ - **`grade-paper-writing`** (+ `../paper-pipeline/references/writing-craft.md`) β€” the paper-side prose
136
+ QA, above. (Site-repo `writing-quality` / `audience-test` = blog posts only.)
137
+ - **`render-paper`** β€” compile + eyeball pages 1–2 once prose is in.
138
+ - **`verify-citations`** β€” every cite in Related Work must exist AND say what you claim.
139
+ - Then the review loop: **`paper-adversarial-review`** β†’ **`pc-panel-review`** (venue-fit mode for a
140
+ quick fit score, then the full panel as the gate).
141
+
142
+ ## Provenance (two real papers)
143
+ - **AgenticDev 2026 @ ASE β€” "Measuring the Wrong Number."** The thesis IS the construct-validity frame:
144
+ the field optimizes a metric that isn't the thing anyone cares about. The method (how to measure the
145
+ *right* number) is the contribution; the tool verdict is just the demonstration. Its "what we do NOT
146
+ claim" paragraph and lower-bound-not-point-estimate threats framing are what moved it through review.
147
+ - **AISec 2026 @ ACM CCS β€” "Safety Theater."** A security-venue measurement paper: a defense that
148
+ *looks* like safety without measurably being it. Needs the explicit threat model + ethics/disclosure
149
+ sections above, and dunks on the *defense pattern*, never the maintainers who shipped it β€” the
150
+ credit-the-humans rule is load-bearing at a top-tier security venue where a hostile framing draws a
151
+ hostile review. Both papers win on precise claim-sizing and an honest threats section, not on the
152
+ size of the effect.