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,136 @@
1
+ ---
2
+ name: research-ideate
3
+ description: "Decide whether a research idea is worth doing at all — before any work goes into it. Use when someone has an idea and asks: is this worth pursuing, should we take it on, is it a paper or just a blog post, is there a quick minimal result that doesn't need a dramatic finding, will it pull us away from our main line of work. Returns a go / no-go verdict with the sharpest framing, the minimal finding and the kinds of venue that would take it. Judges the idea by what counts in a body of work: a peer-reviewed indexed publication, a reusable method or benchmark rather than a one-off \"tool X is bad\", onward citations rather than GitHub stars, and one connected line rather than scattered topics. Stage: conception, before find-venue and before any draft; hands off to find-venue, build-benchmark, draft-paper."
4
+ allowed-tools: [Read, Write, 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:f0ccfb74162bca40 compiled from skills/research-ideate/SKILL.md.spec.ts -->
8
+
9
+ # research-ideate — is this idea worth a paper, and does the paper earn authorship credit?
10
+
11
+ ## Run me
12
+
13
+ 🔴 FIRST, before any other step:
14
+
15
+ ```
16
+ node .claude/skills/paper-pipeline/scripts/announce.mjs research-ideate <dir>
17
+ ```
18
+
19
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
20
+ state — so starting is an event, and events get written down.
21
+
22
+ The `<dir>` argument is **optional in spirit**: this skill can run before a paper directory exists, so
23
+ pass whichever directory the work lives in, or `.`. The ledger row is written either way, and a plain
24
+ dot is more honest than an invented path.
25
+
26
+ Runs BEFORE any effort is spent. An idea can be interesting and still be a bad *publication*
27
+ investment — the wrong framing produces something un-publishable or un-citable, which counts for
28
+ nothing toward a body of work. This skill kills those ideas early and reshapes the survivors into the framing
29
+ that publishes. It does NOT do the venue search (that's `find-venue`) — it decides whether there's a
30
+ paper worth taking to `find-venue` at all.
31
+
32
+ Grounding for every judgment below: the authorship, judging and original-contribution criteria —
33
+ what a reviewer of a body of work actually counts.
34
+
35
+ ## Score the idea on five axes
36
+
37
+ Answer each explicitly. A "no" on (a) is a hard stop; a "no" on the rest is a reshape signal.
38
+
39
+ **(a) Does it yield a PEER-REVIEWED, INDEXED publication?**
40
+ This is the authorship criterion, full stop. The paper must land in indexed proceedings (ACM DL /
41
+ IEEE Xplore / archival workshop proceedings). Peer-reviewed + indexed papers count
42
+ **regardless of caliber** — conference and workshop proceedings qualify. There is **no
43
+ approved-venue list** and **venue newness does not hurt** the authorship criterion (prestige is
44
+ only a late-stage enhancer). So the bar here is binary: will
45
+ this produce something that goes through peer review and gets indexed? A blog post, a preprint that
46
+ never gets reviewed, or a non-archival talk = **no credit**. If the idea can't clear this, stop.
47
+
48
+ **(b) Is the contribution a reusable METHOD/BENCHMARK, or a one-off result?**
49
+ Reviewers accept methods and benchmarks; they reject "we ran tool X and it's bad." Name both framings:
50
+ - **Weakest framing** — the bare result. "Coding agent X produces insecure code." Reads as a blog
51
+ post, doesn't generalize, dies in review, earns nothing citable.
52
+ - **Strongest framing** — the reusable artifact. The *way you measured it*: a benchmark, a metric, a
53
+ probe, a protocol others can rerun against the next tool. That survives review AND gets cited when
54
+ someone applies it to tool Y. Pick the strongest framing before writing a line.
55
+
56
+ **(c) Will it generate downstream CITATIONS / ADOPTION?**
57
+ This is the original-contribution criterion, and it is read through **citations and adoption, NOT
58
+ GitHub stars**. Ask: when the next person studies this space, must they cite or reuse this? A
59
+ benchmark others rerun, a metric others report, a finding others build on — yes. A one-off teardown of
60
+ one product — no. Methods/benchmarks (axis b) are exactly what earns this credit; scattered results do
61
+ not.
62
+
63
+ **(d) Is there a fast MVP finding — a "proof of method" that needs no scary result?**
64
+ The idea should have a small first result that *validates the method itself*, independent of how
65
+ dramatic the finding is. A **medium-severity finding is sufficient** if the method is the
66
+ contribution. You do not need to prove the tool is catastrophically broken; you need to prove your
67
+ measurement works and reveals something real. If the idea only pays off with a huge, hard-to-get
68
+ result, it's slow and risky — reshape it toward a proof-of-method MVP.
69
+
70
+ **(e) Does it stay in the researcher's coherent LANE?**
71
+ **Name the lane explicitly** — the research area the existing corpus is already in. A
72
+ connected corpus of papers in one lane beats scattered topics — review of a body of work rewards a
73
+ sustained, coherent corpus, not a grab-bag. Score whether this idea deepens the existing corpus
74
+ (good) or wanders into an unrelated field (weak, even if publishable). Same lane compounds; scattered
75
+ does not.
76
+
77
+ ## Output
78
+
79
+ Emit a compact verdict:
80
+ 1. **Go / No-go** — with the single reason. No-go if (a) fails, or if (b)+(c) can't be reshaped out of
81
+ blog-post territory.
82
+ 2. **Sharpest framing** — the one-sentence method/benchmark contribution, in its strongest form (the
83
+ thing every future reviewer will paraphrase back). This sentence is the seed for `draft-paper`.
84
+ 3. **The MVP finding** — the smallest proof-of-method result that validates the contribution;
85
+ explicitly note the minimum severity that suffices (usually: medium is enough).
86
+ 4. **2–3 candidate venue TYPES** — not specific venues (that's `find-venue`'s job), but the shape:
87
+ e.g. "security-of-AI-coding workshop @ a top-tier security conference," "SE-measurement workshop @
88
+ ASE/FSE," "eval/benchmark track." Hand these to `find-venue`.
89
+
90
+ ## Record the verdict
91
+
92
+ 🔴 LAST step, once the deliverable exists:
93
+
94
+ ```
95
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record research-ideate <dir> FINDING <count> <report-path>
96
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record research-ideate <dir> ABSTAINED <reason> "<one line>"
97
+ ```
98
+
99
+ 🔴 **There is no PASS**, so there is no way to write down "go" as a value. A clean go is the
100
+ absence of findings across the axes, and whoever wants to call it a go says so themselves.
101
+
102
+ **FINDING** — go with reshaping, where `<count>` is the number of axes that need it and
103
+ `<report-path>` is the output. Add `--blocking` for a no-go: axis (a) is a hard stop, not a weight,
104
+ and a no-go is the loudest finding this skill produces.
105
+ **ABSTAINED** — `no-witness`: all axes were scored and none needed reshaping. `blocked`: the idea
106
+ was too vague to score, which is a different thing from a no-go and must not be recorded as one.
107
+
108
+ A recorded no-go is the cheapest artifact in this whole pipeline, and the one most often lost: an idea
109
+ killed in conversation comes back three months later wearing a different name, and nothing in the repo
110
+ remembers that it was already judged.
111
+
112
+ ## Rules
113
+ - Axis (a) is a gate, not a weight — no indexed peer review, no idea. Everything else reshapes.
114
+ - Never justify an idea by GitHub stars, demo virality, or "it'd be a great blog post." Those don't
115
+ count. Citations/adoption and indexed proceedings do.
116
+ - Prefer the proof-of-method MVP over the heroic result — a shipped medium finding beats a stalled big
117
+ one, and it's what earns the credit on time.
118
+ - Keep it in lane. If it's a great idea in the wrong field, say so and note it belongs elsewhere.
119
+ - Don't invent numbers, severities, or venue names here — this is a framing pass, not a study.
120
+
121
+ ## Compose with
122
+ - `find-venue` (downstream) — hand it the candidate venue types + the sharpest framing.
123
+ - `build-benchmark` — the MVP finding usually IS a small benchmark; this skill scopes it.
124
+ - `draft-paper` — the sharpest-framing sentence becomes the paper's one-contribution seed.
125
+ - `plan-paper-timeline` — once go/no-go is "go," size the effort against a real deadline.
126
+
127
+ ## Provenance
128
+ Both real papers passed this filter as **proof-of-method, medium-severity-is-sufficient** ideas in one
129
+ lane:
130
+ - **AgenticDev 2026 @ ASE — "Measuring the Wrong Number"** (~90%, submitted). The contribution was the
131
+ *measurement method*, not a verdict on one tool; a medium-severity finding was enough because the
132
+ reusable way-to-measure was the point. Stayed in the AI-assisted-SE reliability lane.
133
+ - **AISec 2026 @ ACM CCS — "Safety Theater in Agentic Coding"** (~87–88%). Same shape at a security
134
+ bar: a reusable probe/finding about agentic coding safety, proof-of-method sufficient, squarely in
135
+ the security-of-AI-coding lane. Together the two form a *connected corpus* — exactly what axis (e)
136
+ rewards — rather than two scattered one-offs.
@@ -0,0 +1,152 @@
1
+ // Compiled to SKILL.md by `vigiles compile`. Edit THIS file, never the markdown.
2
+ //
3
+ // Adopted 2026-08-17 (batch 3). Body carried over VERBATIM so the compiled diff shows
4
+ // only what the compiler adds. No `disallowedTools` fence yet — the field landed on
5
+ // `SkillSpec` in vigiles branch `claude/skill-disallowed-tools` and is not in a release
6
+ // this repo installs, so writing one here would not compile.
7
+ import { experimental_skill } from "vigiles/spec";
8
+
9
+ export default experimental_skill({
10
+ name: "research-ideate",
11
+ description:
12
+ 'Decide whether a research idea is worth doing at all — before any work goes into it. Use when someone has an idea and asks: is this worth pursuing, should we take it on, is it a paper or just a blog post, is there a quick minimal result that doesn\'t need a dramatic finding, will it pull us away from our main line of work. Returns a go / no-go verdict with the sharpest framing, the minimal finding and the kinds of venue that would take it. Judges the idea by what counts in a body of work: a peer-reviewed indexed publication, a reusable method or benchmark rather than a one-off "tool X is bad", onward citations rather than GitHub stars, and one connected line rather than scattered topics. Stage: conception, before find-venue and before any draft; hands off to find-venue, build-benchmark, draft-paper.',
13
+ tools: [
14
+ "Read",
15
+ "Write",
16
+ "Grep",
17
+ "Glob",
18
+ "Agent",
19
+ "Skill",
20
+ "Bash(node .claude/skills/paper-pipeline/scripts/announce.mjs:*)",
21
+ "Bash(node .claude/skills/paper-pipeline/scripts/ledger.mjs:*)",
22
+ ],
23
+ body: `
24
+ # research-ideate — is this idea worth a paper, and does the paper earn authorship credit?
25
+
26
+ ## Run me
27
+
28
+ 🔴 FIRST, before any other step:
29
+
30
+ \`\`\`
31
+ node .claude/skills/paper-pipeline/scripts/announce.mjs research-ideate <dir>
32
+ \`\`\`
33
+
34
+ An advisory pass cannot be observed failing — silence is both its error state and its normal
35
+ state — so starting is an event, and events get written down.
36
+
37
+ The \`<dir>\` argument is **optional in spirit**: this skill can run before a paper directory exists, so
38
+ pass whichever directory the work lives in, or \`.\`. The ledger row is written either way, and a plain
39
+ dot is more honest than an invented path.
40
+
41
+ Runs BEFORE any effort is spent. An idea can be interesting and still be a bad *publication*
42
+ investment — the wrong framing produces something un-publishable or un-citable, which counts for
43
+ nothing toward a body of work. This skill kills those ideas early and reshapes the survivors into the framing
44
+ that publishes. It does NOT do the venue search (that's \`find-venue\`) — it decides whether there's a
45
+ paper worth taking to \`find-venue\` at all.
46
+
47
+ Grounding for every judgment below: the authorship, judging and original-contribution criteria —
48
+ what a reviewer of a body of work actually counts.
49
+
50
+ ## Score the idea on five axes
51
+
52
+ Answer each explicitly. A "no" on (a) is a hard stop; a "no" on the rest is a reshape signal.
53
+
54
+ **(a) Does it yield a PEER-REVIEWED, INDEXED publication?**
55
+ This is the authorship criterion, full stop. The paper must land in indexed proceedings (ACM DL /
56
+ IEEE Xplore / archival workshop proceedings). Peer-reviewed + indexed papers count
57
+ **regardless of caliber** — conference and workshop proceedings qualify. There is **no
58
+ approved-venue list** and **venue newness does not hurt** the authorship criterion (prestige is
59
+ only a late-stage enhancer). So the bar here is binary: will
60
+ this produce something that goes through peer review and gets indexed? A blog post, a preprint that
61
+ never gets reviewed, or a non-archival talk = **no credit**. If the idea can't clear this, stop.
62
+
63
+ **(b) Is the contribution a reusable METHOD/BENCHMARK, or a one-off result?**
64
+ Reviewers accept methods and benchmarks; they reject "we ran tool X and it's bad." Name both framings:
65
+ - **Weakest framing** — the bare result. "Coding agent X produces insecure code." Reads as a blog
66
+ post, doesn't generalize, dies in review, earns nothing citable.
67
+ - **Strongest framing** — the reusable artifact. The *way you measured it*: a benchmark, a metric, a
68
+ probe, a protocol others can rerun against the next tool. That survives review AND gets cited when
69
+ someone applies it to tool Y. Pick the strongest framing before writing a line.
70
+
71
+ **(c) Will it generate downstream CITATIONS / ADOPTION?**
72
+ This is the original-contribution criterion, and it is read through **citations and adoption, NOT
73
+ GitHub stars**. Ask: when the next person studies this space, must they cite or reuse this? A
74
+ benchmark others rerun, a metric others report, a finding others build on — yes. A one-off teardown of
75
+ one product — no. Methods/benchmarks (axis b) are exactly what earns this credit; scattered results do
76
+ not.
77
+
78
+ **(d) Is there a fast MVP finding — a "proof of method" that needs no scary result?**
79
+ The idea should have a small first result that *validates the method itself*, independent of how
80
+ dramatic the finding is. A **medium-severity finding is sufficient** if the method is the
81
+ contribution. You do not need to prove the tool is catastrophically broken; you need to prove your
82
+ measurement works and reveals something real. If the idea only pays off with a huge, hard-to-get
83
+ result, it's slow and risky — reshape it toward a proof-of-method MVP.
84
+
85
+ **(e) Does it stay in the researcher's coherent LANE?**
86
+ **Name the lane explicitly** — the research area the existing corpus is already in. A
87
+ connected corpus of papers in one lane beats scattered topics — review of a body of work rewards a
88
+ sustained, coherent corpus, not a grab-bag. Score whether this idea deepens the existing corpus
89
+ (good) or wanders into an unrelated field (weak, even if publishable). Same lane compounds; scattered
90
+ does not.
91
+
92
+ ## Output
93
+
94
+ Emit a compact verdict:
95
+ 1. **Go / No-go** — with the single reason. No-go if (a) fails, or if (b)+(c) can't be reshaped out of
96
+ blog-post territory.
97
+ 2. **Sharpest framing** — the one-sentence method/benchmark contribution, in its strongest form (the
98
+ thing every future reviewer will paraphrase back). This sentence is the seed for \`draft-paper\`.
99
+ 3. **The MVP finding** — the smallest proof-of-method result that validates the contribution;
100
+ explicitly note the minimum severity that suffices (usually: medium is enough).
101
+ 4. **2–3 candidate venue TYPES** — not specific venues (that's \`find-venue\`'s job), but the shape:
102
+ e.g. "security-of-AI-coding workshop @ a top-tier security conference," "SE-measurement workshop @
103
+ ASE/FSE," "eval/benchmark track." Hand these to \`find-venue\`.
104
+
105
+ ## Record the verdict
106
+
107
+ 🔴 LAST step, once the deliverable exists:
108
+
109
+ \`\`\`
110
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record research-ideate <dir> FINDING <count> <report-path>
111
+ node .claude/skills/paper-pipeline/scripts/ledger.mjs record research-ideate <dir> ABSTAINED <reason> "<one line>"
112
+ \`\`\`
113
+
114
+ 🔴 **There is no PASS**, so there is no way to write down "go" as a value. A clean go is the
115
+ absence of findings across the axes, and whoever wants to call it a go says so themselves.
116
+
117
+ **FINDING** — go with reshaping, where \`<count>\` is the number of axes that need it and
118
+ \`<report-path>\` is the output. Add \`--blocking\` for a no-go: axis (a) is a hard stop, not a weight,
119
+ and a no-go is the loudest finding this skill produces.
120
+ **ABSTAINED** — \`no-witness\`: all axes were scored and none needed reshaping. \`blocked\`: the idea
121
+ was too vague to score, which is a different thing from a no-go and must not be recorded as one.
122
+
123
+ A recorded no-go is the cheapest artifact in this whole pipeline, and the one most often lost: an idea
124
+ killed in conversation comes back three months later wearing a different name, and nothing in the repo
125
+ remembers that it was already judged.
126
+
127
+ ## Rules
128
+ - Axis (a) is a gate, not a weight — no indexed peer review, no idea. Everything else reshapes.
129
+ - Never justify an idea by GitHub stars, demo virality, or "it'd be a great blog post." Those don't
130
+ count. Citations/adoption and indexed proceedings do.
131
+ - Prefer the proof-of-method MVP over the heroic result — a shipped medium finding beats a stalled big
132
+ one, and it's what earns the credit on time.
133
+ - Keep it in lane. If it's a great idea in the wrong field, say so and note it belongs elsewhere.
134
+ - Don't invent numbers, severities, or venue names here — this is a framing pass, not a study.
135
+
136
+ ## Compose with
137
+ - \`find-venue\` (downstream) — hand it the candidate venue types + the sharpest framing.
138
+ - \`build-benchmark\` — the MVP finding usually IS a small benchmark; this skill scopes it.
139
+ - \`draft-paper\` — the sharpest-framing sentence becomes the paper's one-contribution seed.
140
+ - \`plan-paper-timeline\` — once go/no-go is "go," size the effort against a real deadline.
141
+
142
+ ## Provenance
143
+ Both real papers passed this filter as **proof-of-method, medium-severity-is-sufficient** ideas in one
144
+ lane:
145
+ - **AgenticDev 2026 @ ASE — "Measuring the Wrong Number"** (~90%, submitted). The contribution was the
146
+ *measurement method*, not a verdict on one tool; a medium-severity finding was enough because the
147
+ reusable way-to-measure was the point. Stayed in the AI-assisted-SE reliability lane.
148
+ - **AISec 2026 @ ACM CCS — "Safety Theater in Agentic Coding"** (~87–88%). Same shape at a security
149
+ bar: a reusable probe/finding about agentic coding safety, proof-of-method sufficient, squarely in
150
+ the security-of-AI-coding lane. Together the two form a *connected corpus* — exactly what axis (e)
151
+ rewards — rather than two scattered one-offs.`,
152
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * research-ideate — 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/research-ideate/research-ideate.eval.mjs [trials]
16
+ */
17
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
18
+
19
+ await runSkillTriggerEval("research-ideate");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * research-ideate — 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 `research-ideate.eval.mjs`.
20
+ */
21
+ import { checkSkill } from "../../lib/skill-checks.mjs";
22
+
23
+ await checkSkill("research-ideate");
@@ -0,0 +1,179 @@
1
+ /**
2
+ * skill-contract.mutations.mjs — the non-vacuity proof for the colocated skill harnesses.
3
+ *
4
+ * Run: `node skills/skill-contract.mutations.mjs` (~1 min; it rewrites each SKILL.md and restores
5
+ * it, so it is not part of the plain test run).
6
+ *
7
+ * ── WHY IT EXISTS, AND WHY IT ARRIVED WITH THE SKILLS ───────────────────────
8
+ * `scripts/run-mutations.mjs` refuses a repository where some `*.harness.mjs` is named by no
9
+ * battery, and the refusal is the whole argument of this package: silence is the success state of
10
+ * every check here, so «it passed» and «it cannot fail» are byte-identical from outside. The ten
11
+ * skill harnesses arrived on 2026-09-12 and were orphans the moment they landed — the guard said
12
+ * so on the first run, which is exactly what a guard is for.
13
+ *
14
+ * ── HOW THE SKILLS ARE REACHED FROM INSIDE THIS PACKAGE ─────────────────────
15
+ * 🔴 `checkSkill()` looks at `<consumerRoot>/.claude/skills/<name>/SKILL.md` — the fixed Claude
16
+ * Code layout — not at `skills/<name>` where this repository keeps them. So this repository is its
17
+ * OWN FIRST CONSUMER: `.claude/skills/<name>` is a symlink to `../../skills/<name>`, and
18
+ * `.claude/skills/paper-pipeline/scripts` is a symlink to the real scripts directory, so the path
19
+ * every SKILL.md's prose names (`node .claude/skills/paper-pipeline/scripts/announce.mjs …`)
20
+ * resolves here too. Without those symlinks `skill-corpus.mjs` throws while LOADING, and a harness
21
+ * whose module fails to load is reported by `vigiles test` as SKIPPED with exit code 0 — a green
22
+ * run that tested nothing. That is not a hypothetical: it is what the first attempt printed.
23
+ *
24
+ * Because the symlinks point back at `skills/`, an edit to `skills/<n>/SKILL.md` IS the edit the
25
+ * harness sees. The driver therefore writes the real file and restores it, verifying both.
26
+ *
27
+ * ── THE DEFECT EACH CASE PLANTS, AND WHY THAT ONE ───────────────────────────
28
+ * Nine of the ten are `checkSkill()` one-liners, so they all fail the same way and one defect
29
+ * shape covers them: make the skill announce under a SIBLING'S name. It is the defect the
30
+ * assertion exists for — these record blocks are copy-paste templates differing in one token,
31
+ * `announce.mjs` validates nothing, and the wrong gate then reads FRESH in `status.mjs` while the
32
+ * right one reads NEVER-RUN. Each case names a DIFFERENT sibling so that no two cases could pass
33
+ * on one shared accident.
34
+ *
35
+ * `osf-artifact-upload` is not a `checkSkill()` skill (it carries no `announce.mjs <self>` line —
36
+ * it is a utility `submit-paper` composes with, not a stage), so its case plants the defect ITS
37
+ * harness is about: a `curl` that loses `-g`, which makes a bracketed OSF parameter glob and the
38
+ * request fail silently.
39
+ */
40
+ import { readdirSync } from "node:fs";
41
+ import { dirname, join } from "node:path";
42
+ import { fileURLToPath } from "node:url";
43
+ import { runMutations } from "../lib/mutation-driver.mjs";
44
+ import { consumerRoot } from "./paper-pipeline/scripts/consumer.mjs";
45
+
46
+ const HERE = dirname(fileURLToPath(import.meta.url));
47
+ const md = (s) => join(HERE, s, "SKILL.md");
48
+ const harness = (s) => join(HERE, s, `${s}.harness.mjs`);
49
+
50
+ /** [skill, the sibling it is made to announce under] — every sibling distinct. */
51
+ const ANNOUNCERS = [
52
+ ["analyze-sibling-paper", "map-prior-work"],
53
+ ["argument-arc", "tighten-paper"],
54
+ ["cold-read-diff", "argument-arc"],
55
+ ["draft-paper", "build-benchmark"],
56
+ ["map-prior-work", "find-venue"],
57
+ ["paper-adversarial-review", "pc-panel-review"],
58
+ ["pc-panel-review", "harden-paper"],
59
+ ["sweep-design-space", "research-ideate"],
60
+ ["tighten-paper", "grade-paper-writing"],
61
+ // ── wave ② (2026-09-12). Same defect shape: all twelve are `checkSkill()` stage skills
62
+ // carrying exactly one `announce.mjs <self>` line, verified unambiguous before these were
63
+ // written. Siblings stay pairwise distinct across the WHOLE list, so no two cases can pass
64
+ // on one shared accident.
65
+ ["build-benchmark", "draft-paper"],
66
+ ["camera-ready", "extend-paper"],
67
+ ["harden-paper", "paper-adversarial-review"],
68
+ ["paper-status", "render-paper"],
69
+ ["extend-paper", "camera-ready"],
70
+ ["study-accepted-papers", "analyze-sibling-paper"],
71
+ ["verify-citations", "cold-read-diff"],
72
+ ["render-paper", "paper-status"],
73
+ ["find-venue", "plan-paper-timeline"],
74
+ ["research-ideate", "sweep-design-space"],
75
+ ["plan-paper-timeline", "study-accepted-papers"],
76
+ ["grade-paper-writing", "verify-citations"],
77
+ // ── wave ③ (2026-09-12). `submit-paper` is a `checkSkill()` stage skill with exactly one
78
+ // `announce.mjs submit-paper` line (verified unambiguous before this was written). Its sibling
79
+ // is the conductor itself — the only name left that keeps the whole list pairwise distinct, and
80
+ // a fitting one: recording a submission under the orchestrator's gate is precisely the
81
+ // copy-paste slip that reads FRESH on the wrong row.
82
+ ["submit-paper", "paper-pipeline"],
83
+ ];
84
+
85
+ // 🔴 "Every sibling is distinct" is an ASSERTION, not a wish stated in a comment. The list is
86
+ // written by hand, and exactly this kind of list has already rotted silently before. If two cases
87
+ // mutate into the same name, they can pass on one shared accident, and the battery stops being
88
+ // able to tell their failures apart.
89
+ {
90
+ const seen = new Set();
91
+ for (const [skill, sibling] of ANNOUNCERS) {
92
+ if (skill === sibling)
93
+ throw new Error(
94
+ `${skill}: the sibling must be DIFFERENT from the skill itself`,
95
+ );
96
+ if (seen.has(sibling))
97
+ throw new Error(
98
+ `sibling "${sibling}" is named twice — the cases stopped being independent. ` +
99
+ `Each case needs its own, otherwise two of them can pass on one shared accident.`,
100
+ );
101
+ seen.add(sibling);
102
+ }
103
+ }
104
+
105
+ const CASES = ANNOUNCERS.map(([skill, sibling]) => ({
106
+ name: `${skill}: announces as ${sibling}`,
107
+ disables:
108
+ "the identity check — a run recorded under a sibling's gate, which then reads FRESH",
109
+ edits: [[md(skill), `announce.mjs ${skill} `, `announce.mjs ${sibling} `]],
110
+ harness: harness(skill),
111
+ expect: "its announce command files under",
112
+ }));
113
+
114
+ CASES.push({
115
+ name: "osf-artifact-upload: one curl loses -g",
116
+ disables:
117
+ "the globbing rule this skill states in its own §gotchas, three paragraphs above the command",
118
+ // 🔴 ANCHORED ON THE ONE CALL THAT IS UNIQUE, not on the shared prefix. `curl -g -s --retry 3`
119
+ // appears three times, and the driver refuses an ambiguous target rather than guessing — which
120
+ // is how the first version of this case reported AMBIGUOUS instead of quietly mutating one of
121
+ // three and calling it a kill.
122
+ edits: [
123
+ [
124
+ md("osf-artifact-upload"),
125
+ 'curl -g -s --retry 3 --cacert $CA -H "$AUTH" https://api.osf.io/v2/users/me/',
126
+ 'curl -s --retry 3 --cacert $CA -H "$AUTH" https://api.osf.io/v2/users/me/',
127
+ ],
128
+ ],
129
+ harness: harness("osf-artifact-upload"),
130
+ expect: 'command(s) omit "-g"',
131
+ });
132
+
133
+ // ── wave ③: the conductor. NOT a `checkSkill()` skill — its harness (`paper-pipeline.harness.mjs`)
134
+ // checks ROUTING INTEGRITY, so the defect has to be a routing one, the same way
135
+ // `osf-artifact-upload` above gets the defect ITS harness is about.
136
+ //
137
+ // 🔴 THE FORWARD DIRECTION IS THE ONE A MUTATION CAN REACH. Backward ("a wired stage the map never
138
+ // names") cannot be planted by editing the map alone — deleting a route makes the skill un-named,
139
+ // which is exactly what the MISSING allowance list tolerates for three skills, so the kill would
140
+ // depend on which name was picked. Forward is unconditional: a bolded backticked token in a routing
141
+ // table that resolves to no skill directory is a route to nowhere, and a run following the map
142
+ // stalls there. `**\`camera-ready\`**` occurs exactly once, so the edit cannot be ambiguous.
143
+ CASES.push({
144
+ name: "paper-pipeline: the map routes to a skill that does not exist",
145
+ disables:
146
+ "forward routing integrity — the conductor pointing at a name with no SKILL.md behind it",
147
+ edits: [
148
+ [md("paper-pipeline"), "**`camera-ready`**", "**`camera-ready-v2`**"],
149
+ ],
150
+ harness: harness("paper-pipeline"),
151
+ expect: "no .claude/skills/camera-ready-v2/SKILL.md exists",
152
+ });
153
+
154
+ // 🔴 A FLOOR, NOT A COMMENT. The list above is written by hand, and a hand-written list of paths
155
+ // is the thing this package replaced in `package.json` on 2026-09-11 because it had already
156
+ // rotted SILENTLY. A skill added to `skills/` with a colocated harness and no case here would be
157
+ // caught by `run-mutations.mjs` — but only on the run AFTER someone added it, and only if they
158
+ // ran it. This asserts the pairing from the other side, at import time.
159
+ // 🔴 THE `paper-pipeline` EXCLUSION IS GONE (wave ③, 2026-09-12). It was written when that
160
+ // directory held only `scripts/` — no SKILL.md, no colocated harness, nothing for a case to kill.
161
+ // Both arrived with wave ③, so the exclusion would now hide the orchestrator from the very floor
162
+ // that exists to notice an uncovered harness: `e.name !== "paper-pipeline"` and «it has no harness»
163
+ // were the same statement for one day and are opposite statements now.
164
+ const withHarness = readdirSync(HERE, { withFileTypes: true })
165
+ .filter((e) => e.isDirectory())
166
+ .map((e) => e.name)
167
+ .filter((n) => readdirSync(join(HERE, n)).includes(`${n}.harness.mjs`));
168
+ const covered = new Set(CASES.map((c) => c.harness));
169
+ const missing = withHarness.filter((n) => !covered.has(harness(n)));
170
+ if (missing.length)
171
+ throw new Error(
172
+ `skill-contract.mutations.mjs covers no case for: ${missing.join(", ")}.\n` +
173
+ `Each skill directory carrying <name>.harness.mjs needs a case here, or that harness is a ` +
174
+ `test nothing can kill — green and silent whether or not it still checks anything.`,
175
+ );
176
+
177
+ process.exit(
178
+ runMutations({ root: consumerRoot(), runner: "vigiles", cases: CASES }),
179
+ );