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,585 @@
1
+ ---
2
+ title: "Sweep — what the pipeline should ideally look like (a construction, not a justification for markdown)"
3
+ created: 2026-08-09
4
+ updated: 2026-08-09
5
+ tags:
6
+ [
7
+ paper-pipeline,
8
+ design-space,
9
+ sweep,
10
+ mechanisms,
11
+ unrepresentable,
12
+ claims,
13
+ provenance,
14
+ ]
15
+ findings: 8
16
+ ---
17
+
18
+ # Sweep — the ideal pipeline construction
19
+
20
+ **The author's question:** "the fact that the pipeline uses markdown doesn't mean anything by
21
+ itself — the question is what it should look like **ideally**."
22
+
23
+ **The defect-state that should become unrepresentable:** a manuscript goes out for review carrying
24
+ a claim that is not backed by what it cites.
25
+
26
+ ---
27
+
28
+ ## The short answer (originally written in Russian, 10 lines)
29
+
30
+ 1. **The form is already right, and that's not our opinion — two other groups independently arrived
31
+ at it in 2026.**
32
+ `arXiv:2606.09500` (MedSci Skills, June 8) — "decompose the work into **skills**, gate every
33
+ transition with **halt-on-failure**, resolve each question with the **cheapest sufficient
34
+ mechanism**: a deterministic recheck where that suffices, a prose-level probe only where
35
+ interpretation is unavoidable." This is, word for word, our fact-gate / judgement-gate split from
36
+ `run-mechanical.mjs`, published two months earlier.
37
+ `arXiv:2605.28282` (ResearchLoop, May 27) — "claim ledgers", "paper bindings", "claim-admission
38
+ algorithm". This is our `CLAIMS.md` + `ledger.mjs`. **The architecture can no longer be claimed as
39
+ novel.**
40
+ 2. **Ideal ≠ "not a single unbound claim".** Refusal without a replacement is deletion one step
41
+ earlier; framing prose is the most valuable thing in the file. What should become unrepresentable
42
+ is not the _content_ but the **claim of strength** — i.e. the assertion "this is backed" when it
43
+ isn't.
44
+ 3. **The measurement that changes the conversation: 46 numbers are bound, 264 are exempted by
45
+ "grandfathering".** The numbers gate covers roughly a third of the paper's bolded numbers, and the
46
+ exemption has **no expiration date**. This is not a hypothetical gap, it is `wc -l` on
47
+ `repro/numbers-grandfathered.txt`.
48
+ 4. **The main constructive finding:** the binding mechanism exists for **exactly one carrier** —
49
+ numbers. The same three lines of code close two more: **citations** (a sentence claims that work X
50
+ says Y) and **novelty claims** (a `CLAIMS.md` line that can be retracted). The ideal pipeline is
51
+ **one binding mechanism across three carriers**, not three separate checks.
52
+
53
+ Below is how this was arrived at, what got killed, and by what.
54
+
55
+ ---
56
+
57
+ ## 0. Three findings that matter more than any single candidate
58
+
59
+ ### 0.1 🔴 The architecture is OCCUPIED — twice, in 2026, and the repository knew about neither work
60
+
61
+ A `grep` across the whole repo: `2606.09500`, `2605.28282`, `MedSci`, `ResearchLoop` — **zero
62
+ hits**. The 2026-08-06 occupancy pass (`occupancy-2026-08-06-*`) checked **tools** (knitr, Quarto,
63
+ showyourwork, Vale, aclpubcheck) and missed two arXiv papers about **the architecture itself**.
64
+
65
+ **[B] Abstract verbatim, `arXiv:2606.09500`, Nam, Jeong, Kim, submitted 2026-06-08, revision
66
+ 06-14:**
67
+
68
+ > «We describe an architecture pairing generation with verification, resting on three principles:
69
+ > decompose the workflow into self-contained skills, gate every stage transition with halt-on-failure,
70
+ > and resolve each integrity question with the cheapest sufficient mechanism, a deterministic,
71
+ > re-executable check where one suffices and a prose-level probe only where interpretation is
72
+ > unavoidable. This determinism-where-possible split, organized as an integrity-gate taxonomy, is the
73
+ > core contribution. It is realized as MedSci Skills, an open-source toolkit of 43 skills with a
74
+ > 21-detector deterministic tier, evaluated on three public-dataset pipelines (STARD, PRISMA, STROBE)
75
+ > and a seeded-defect ablation. […] on 27 identical injected defects the deterministic gates detected
76
+ > all 27 with no false positives on the matched clean fixtures, whereas a single-prompt LLM reviewer
77
+ > detected 11, its misses in code, bibliography, and style defects the prose hides. […] MedSci Skills
78
+ > is MIT-licensed and archived (v3.8.0).»
79
+
80
+ Line-by-line correspondences with ours:
81
+
82
+ | theirs | ours |
83
+ | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
84
+ | «self-contained skills» | 22 paper skills |
85
+ | «gate every stage transition with halt-on-failure» | `run-mechanical.mjs`, exit code of the worst gate |
86
+ | «deterministic check where one suffices, prose-level probe only where interpretation is unavoidable» | the FACT-gate / JUDGEMENT-gate split, `verdict: 'exit'` vs `verdict: 'flags'` |
87
+ | «seeded-defect ablation», 27 injected defects | `*.harness.mjs` + `skills.mutations.mjs`, 21 planted defect |
88
+ | «21-detector deterministic tier» | ~8 mechanical checkers |
89
+
90
+ **[B] Abstract verbatim, `arXiv:2605.28282`, Xia, Wang, submitted 2026-05-27:**
91
+
92
+ > «ResearchLoop treats research questions, task contracts, evidence objects, **claim ledgers**,
93
+ > closeouts, and **paper bindings** as durable project state, realized here as a repository-backed
94
+ > runtime. This technical report provides the complete protocol specification, state model, transition
95
+ > rules, **claim-admission algorithm**, and insight-compounding mechanism.»
96
+
97
+ ⚠️ **Being honest about the evidence level:** the abstracts were read verbatim, **[B]**. The full
98
+ PDFs were read by a small model via WebFetch, and its summaries are **[D], not to be trusted**: for
99
+ 2606.09500 it said "reports rather than blocks", while the abstract says `halt-on-failure`; for
100
+ ResearchLoop its answer to the question about "unrepresentable claims" reads stylistically like
101
+ confabulation ("Standard metrics for such systems would measure…"). **P0: read both PDFs in full,
102
+ with human eyes.**
103
+
104
+ **What follows from this, practically.** Not "we're too late." Three things follow:
105
+
106
+ - the claim "we built a manuscript-verification architecture" is **dead** — but nobody was making it
107
+ anyway;
108
+ - **their 21 deterministic detectors are a donor list**, better than ARIS (see §2.4);
109
+ - **their 27/27-vs-11/27 number is our citation** in favor of banning a decision-making model. It is
110
+ a published, measured argument for the filter "no model in the decision loop", which for us is
111
+ still resting on our own 84–96% measurement.
112
+
113
+ ### 0.2 🔴 Coverage measurement: 46 bound, 264 exempted, no expiration
114
+
115
+ ```
116
+ grep -o '{{[a-zA-Z0-9_.]*}}' paper.md | wc -l → 46
117
+ grep -oE '\*\*[^*]*[0-9][^*]*\*\*' paper.md | wc -l → 113
118
+ grep -vc '^\s*#\|^\s*$' repro/numbers-grandfathered.txt → 264
119
+ ```
120
+
121
+ `numbers-grandfathered.txt` describes itself honestly — _"their presence here is an admission, not
122
+ an exemption"_ — but an admission with no expiration date is exactly **lex imperfecta**, precisely
123
+ the category the author's paper studies in others. Aviation's MEL, where the idea "a defect is
124
+ tolerable with a compensating procedure" comes from in the first place, **always supplies the second
125
+ half: a repair deadline by category, that expires automatically.** We took the first half without the
126
+ second.
127
+
128
+ ### 0.3 🔴 The substitution law: it is the STRENGTH of a claim that must become unrepresentable, not its content
129
+
130
+ Inherited from `compile-rules-2026/research/2026-08-02-mechanism-sweep-2.md` §0.1, and it lands
131
+ even harder here: a manuscript's framing prose (the reason anyone reads the paper) **cannot** be
132
+ bound to data, and should not be. A mechanism that refuses to accept an unbound sentence produces the
133
+ same state as deletion: the author wanted to say something — got refused — the file stays silent.
134
+
135
+ > **Law.** Unrepresentability is safe only when the refusal, **in that same authoring action**,
136
+ > returns an accepted substitute.
137
+
138
+ Hence the form of the answer: **gradual typing**, not a flag-day cutover. Bound and unbound coexist,
139
+ **the boundary is declared**, and the ratio is measured and printed. This is the ancestor from group
140
+ I, and it was picked not by taste but by the filter "one author, the migration has to pay for
141
+ itself."
142
+
143
+ ---
144
+
145
+ ## 1. The defect broken down into five classes, then into four properties
146
+
147
+ | # | Observed instance | What actually failed | Closed? |
148
+ | --- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
149
+ | 1 | 22 matched the file perfectly, but sat in a sentence about **a different arm** | the defect lives **in the join** between the sentence and the field path; each check looks at only one side | partial: `paper_numbers.py` `requires`/`forbids` — but that is **a list of phrases matched against open prose** |
150
+ | 2 | 11 unreadable passages survived 6 passes, all within threshold | **a proxy was substituted for the property** and reports as though it settled it | 🔴 **no** |
151
+ | 3 | gate marked passed, input missing/newer | staleness was **declared**, not computed | ✅ `ledger.mjs`, content-addressed key + hash of the checker itself |
152
+ | 4 | a check that never once said "no" was counted as working | **vacuousness** | partial: `everSaidNo` **detects** it but does not forbid it |
153
+ | 5 | every judge in the chain is a model from the same family | **ensemble independence is assumed, not established** | 🔴 **no** |
154
+
155
+ Four properties of the ideal pipeline:
156
+
157
+ - **P1 · Join.** A claim and its backing are **one object**, not two things a human reconciles by eye.
158
+ - **P2 · Proxy honesty.** A gate either settles the property, or **declares** that it is measuring a proxy.
159
+ - **P3 · Freshness.** The backing is provably about **these** bytes and **this** checker. ✅ done.
160
+ - **P4 · Non-vacuousness and independence.** The gate has proven it can say "no"; judge correlation
161
+ is not passed off as confirmation.
162
+
163
+ ---
164
+
165
+ ## 2. An attack on the rejected options (one reason refuted, one fixed, one new donor)
166
+
167
+ The skill requires attacking the reasons, not just keeping the ban on file. Bottom line: **of four
168
+ retired reasons, two are wrong.**
169
+
170
+ ### 2.1 "Moving to a LaTeX source — we'd lose 31 prose checks" → **stands, the reason is now stronger**
171
+
172
+ The reason is correct but weakly stated. The strong form: **the join is only representable in the
173
+ source.** `{{annotated.failedContradicted}}` inside the rendered `.tex` is already just `22`, and the
174
+ arm is unrecoverable. Indirectly confirmed by 2606.09500: their deterministic tier also sits
175
+ **before** rendering.
176
+
177
+ ### 2.2 "DVC/make/snakemake — a second declaration alongside the prose" → **reason CORRECTED**
178
+
179
+ The "second declaration" objection died the day `status.mjs` showed up: there, **nothing is
180
+ declared**, everything is derived. So keeping them out has to rest on a **different** reason, and it
181
+ is already written down in `ledger.mjs`: they key off timestamps and **do not know the recipe
182
+ changed** — which is exactly our own bug. Keep it retired, but with the right reason, or the next
183
+ session reopens the question and gets an unconvincing answer.
184
+
185
+ ### 2.3 "JSON inside markdown — prose readability is lost" → **reason REFUTED**
186
+
187
+ Refuted by our own shipped code. `{{annotated.failedContradicted}}` is **more readable** than the
188
+ `22` it replaced: the name names the arm, the digit named nothing. What destroys readability is not
189
+ structure inside prose, but **unresolved** structure.
190
+
191
+ > **Corrected rule:** structure inside prose is admissible exactly when it **resolves into prose
192
+ > at render time**. A sidecar table of claims next to the file is still a no (§3.F3, the AOP lesson).
193
+
194
+ ### 2.4 "ARIS — a LaTeX source + 46/83 skills require the Codex MCP" → **stands, but a better donor has appeared**
195
+
196
+ **MedSci Skills** (2606.09500): MIT, skill-based decomposition, **21 deterministic detectors**, no
197
+ Codex dependency, domain is clinical manuscripts (STARD/PRISMA/STROBE). Its form is closer to ours
198
+ than ARIS's. **P1 action:** pull the list of 21 detectors and diff it against our eight — what they
199
+ have that we don't. That is cheaper than any generation.
200
+
201
+ ---
202
+
203
+ ## 3. A sweep of the catalog (what survived and what was killed)
204
+
205
+ Generation proceeded from the catalog's **named constructions**, not from thin air. An honest
206
+ caveat about method is in §6.
207
+
208
+ ### A. Type systems
209
+
210
+ - **A1 · smart constructor: no literal in the source.** ✅ **ALREADY SHIPPED** (`{{name}}` +
211
+ jinja2). Difference from knitr — knitr _allows_ both ways; here the literal is **forbidden**
212
+ (`check_bypass`).
213
+ - **A2 · typestate: the arm declared by a block.** 🟢 **SURVIVED, S2.** Right now the arm is caught
214
+ by phrase lists (`requires`/`forbids`) matched against open prose — a synonym not on the list gets
215
+ through. Strictly stronger: `::: {.arm name=strict}` — and `{{annotated.x}}` inside such a block is
216
+ a **build error by string equality** against a **closed vocabulary** (the arms of your own
217
+ experiment, five of them). No model reads the prose at all.
218
+ - **A3 · affine types: evidence is consumed.** 🟢 **SURVIVED, S7** (see H6 — the same idea from
219
+ medicine).
220
+ - **A4 · instance resolution as a gate.** ❌ the same thing as A2, in someone else's syntax. Killed
221
+ as a mechanism duplicate.
222
+
223
+ ### B. Formal verification
224
+
225
+ - **B1 · vacuousness as an admission criterion.** 🟢 **SURVIVED, S4.** `everSaidNo` **detects** a
226
+ vacuous gate. Stronger: a gate **cannot be registered** in `EXPECTED_GATES` without a harness case
227
+ that plants its defect and observes it firing. `skills.harness.mjs` already reads
228
+ `EXPECTED_GATES` — the change is small. There is a published precedent: their seeded-defect
229
+ ablation, 27/27 against 11/27.
230
+ - **B2 · refinement: the manuscript refines `CLAIMS.md`.** 🟢 **SURVIVED, part of S1.** Today
231
+ `CLAIMS.md` and `paper.md` are **mechanically connected by nothing at all** — and `CLAIMS.md`
232
+ already holds RETRACTED wordings ("two wordings are DEAD, must not be used"). Nothing stops a
233
+ retracted wording from ending up in the PDF.
234
+ - **B3 · TLA+/Alloy on the process.** ❌ **NEGATIVE RESULT.** The invariant "no reachable submit
235
+ with a stale gate" is already **computed** by `status.mjs`. A model here would add ceremony, not
236
+ safety.
237
+ - **B4 · blame at the boundary.** 🟢 partial, absorbed into S6 + §0.3 (the boundary is declared,
238
+ blame falls on whoever widened it).
239
+
240
+ ### C. Functional programming
241
+
242
+ - **C2 · a claim-strength lattice** (`measured < observed < suggests < shows`), abstract ≤ the join
243
+ of the body. ❌ **KILLED BY OCCUPANCY.** This is the literature on **spin in abstracts**, and it is
244
+ large: 97% of trials in one review contain spin, 84% in another; LLM detectors have already been
245
+ measured (GPT-o1, F1 0.932–0.98). Our version would be "no model, on a closed hedge vocabulary" —
246
+ but it can't be claimed as new, and as a tool it's weaker than what's already shipped. File under
247
+ occupied.
248
+ - **C3 · session types on gate ordering.** ❌ **NEGATIVE.** Absorbed by content-addressed
249
+ staleness.
250
+ - **C4 · one AST, many interpreters.** 🟡 **already half exists, and it is the key.**
251
+ `md2submission.py` parses `paper.md` and emits `.tex` + `.bib`. So **a point of complete mediation
252
+ already exists** — every character reaching the reviewer passes through it. Today it's used only
253
+ for formatting. The strong form (markdown as a pure projection of a claim table) ❌ killed by the
254
+ migration filter.
255
+
256
+ ### D. Capabilities
257
+
258
+ - **D1 · grants instead of bans.** 🟡 absorbed into S7: the experiment issues "citable" cells, the
259
+ paper spends them; unspent = unreported, overspent = unbacked.
260
+ - **D2 · a reference monitor, a paragraph only through the CLI.** ❌ **KILLED** by the
261
+ "substitution in the same action" filter: friction destroys the framing prose that is the reason
262
+ anyone reads the paper.
263
+ - **D3 · least privilege for judges.** 🟢 **SURVIVED, S5.** Judge correlation is not just shared
264
+ weights, it is **shared context**. Giving each judge only its own section + the declared backing is
265
+ cheaper than sourcing a second vendor, and it lowers correlation on the one axis available to us.
266
+
267
+ ### E. Specification by example
268
+
269
+ - **E2 · a golden file per claim.** 🟡 partially covered by provenance.
270
+ - **E3 · extracting a claim with a cold reader and checking it against a DECLARED ID.** 🟡
271
+ **conditionally alive.** The one place a model is admissible: it **does not decide**, it proposes a
272
+ label from a **closed** set, and the decision is equality against the author's declaration. The
273
+ author fixes a mismatch. Risk, stated honestly: the model can guess the declared ID and produce a
274
+ false negative. Keep it advisory, not a gate.
275
+ - **E4 · metamorphic relations: swap the arm and rebuild.** 🟢 **SURVIVED, S7-adjacent.** If you
276
+ swap `annotated` and `strict` and **every gate is still green** — the sentences are not bound to the
277
+ arm, and that is proof without a single declaration from the author. Occupancy: metamorphic testing
278
+ of scientific software is a large field, but the search found no application **to a manuscript
279
+ against its own data**.
280
+
281
+ ### F. Data integrity
282
+
283
+ - **F1 · `ADD CONSTRAINT` validates existing rows / `NOT VALID`.** ✅ **SHIPPED** — and
284
+ **with no expiration**, see §0.2 → that is S3.
285
+ - **F2 · a foreign key `ON DELETE RESTRICT`.** 🟡 a cheap add-on to S1: deleting a data row that a
286
+ sentence references should fail.
287
+ - **F3 · store the claim as data, `.md` is a view.** ❌ **KILLED by the AOP lesson** (see I6):
288
+ reading `paper.md`, you stop being able to see what's backed. Admissible only together with S8
289
+ (a marker at the point of use).
290
+
291
+ ### G. Author UX
292
+
293
+ - **G1 · asymmetric cost:** "we show" requires a backing ID, "we observed, informally" is free.
294
+ 🟢 absorbed into S1+S6.
295
+ - **G2 · change the DEFAULT, don't add a gate.** 🟢 **SURVIVED, S8 — the cheapest thing in the
296
+ sweep.** The author looks at the PDF dozens of times. Let unbound numbers **render with a marker**
297
+ in the draft build (not the submission build). Zero new discipline, feedback lands in the artifact
298
+ people already read.
299
+ - **G3 · a single entry point:** `claim add --from aggregate.json:path`. 🟡 good, but after S1.
300
+
301
+ ### H. Other professions
302
+
303
+ - **H1 · aviation's MEL: a repair deadline by category, expires on its own.** 🟢 **SURVIVED, folded
304
+ into S3.**
305
+ - **H2 · SOX: design effectiveness ≠ operating effectiveness.** ✅ **already borrowed**
306
+ deliberately (the `requires`/`forbids` pair). Under-used: the gate table should have **three**
307
+ states, not one — "the control exists / it's designed correctly / it operated in this period."
308
+ - **H3 · MISRA: a decidable/undecidable label on every rule.** 🟢 **SURVIVED, S6.** The only honest
309
+ answer to instance #2: the gate declares whether it settles the property or a proxy. Cost: zero,
310
+ it's a field.
311
+ - **H4 · DO-178C DAL / ISO 26262 ASIL: assurance levels.** 🟢 folded into S3 (level by **position**,
312
+ see below).
313
+ - **H5 · lex imperfecta.** 🟡 a frame, not a mechanism; §0.2 is its application to ourselves.
314
+ - **H6 · CONSORT: accounting for every participant at every stage.** 🟢 **SURVIVED, S7.** Every
315
+ cell of the grid (arm × metric) is either cited by a claim, or **explicitly marked as not
316
+ reported**. This catches the opposite direction of the defect — **measured and not reported**
317
+ (cherry-picking), which nothing catches today and which a reviewer will ask about.
318
+
319
+ ### I. Historical ancestors in software engineering
320
+
321
+ - **I1 · gradual typing.** 🟢 **the form of the whole answer** (§0.3). It caught on across a huge
322
+ installed base precisely because it **required no migration** — the one filter that actually bites
323
+ here.
324
+ - **I2 · SPARK's stone→bronze→silver→gold→platinum.** 🟢 the ladder for S3, the rungs are already
325
+ mechanical and published — don't invent our own.
326
+ - **I3 · lint (1978).** ✅ this is the current construction.
327
+ - **I5 · requirements engineering: _testable requirement_ as a category + a traceability matrix.**
328
+ 🟢 `CLAIMS.md` is a traceability matrix with no mechanical leg. S1 attaches the leg.
329
+ - **I6 · AOP, and WHY IT FAILED.** 🔴 the most useful negative in the sweep: cross-cutting
330
+ declarations, pulled out of the code, made the code unreadable — looking at it, you can't tell what
331
+ applies to it. **A direct ban on a sidecar table of claims** (F3), and the reason S8 is mandatory
332
+ next to any such extraction: the projection has to be visible **at the point of use**.
333
+
334
+ ### J. Migration
335
+
336
+ Strangler fig · `NOT VALID` with a deadline · advisory-then-enforcing · opt-in tiers. This is the
337
+ **rollout form** for everything selected, not a separate mechanism.
338
+
339
+ ---
340
+
341
+ ## 4. The ideal construction — five laws
342
+
343
+ Not "a new pipeline." Naming what the construction has already converged on, plus what it's still
344
+ missing.
345
+
346
+ > **Law 1 · Complete mediation at the converter.** Everything that reaches the reviewer passes
347
+ > through `md2submission.py`. That is **where** to check, because it is the one place where "the
348
+ > manuscript cannot be produced" is a reachable state, while "the checker complained" is not.
349
+ >
350
+ > **Law 2 · One binding mechanism, three carriers.** Numbers, **citations**, **novelty claims** are
351
+ > the same join, "sentence ↔ backing record." Today the mechanism exists only for numbers.
352
+ >
353
+ > **Law 3 · Strength is unrepresentable, not content.** Unbound prose is a first-class, cheap,
354
+ > declared category. Its **share** is measured and printed, not its existence forbidden.
355
+ >
356
+ > **Law 4 · A proxy declares itself a proxy.** A gate carries a decidable/undecidable label. A gate
357
+ > measuring a proxy has no right to report as though it settled the property.
358
+ >
359
+ > **Law 5 · A gate without a killed mutant does not exist.** Registration requires a witness.
360
+ > Agreement among N judges of the same family counts as **one** witness.
361
+
362
+ **What the construction stays SILENT on (declared, not concealed):**
363
+
364
+ - Only `paper.md → PDF` is gated. **The rebuttal, the artifact README, the cover letter, a blog
365
+ post** carry the same claims and are gated by nothing.
366
+ - Nothing checks that the cited work **actually says** what it's credited with saying (S1 makes the
367
+ link representable, but a human fills it in).
368
+ - Framing prose is not checked and should not be — that is the price of Law 3, accepted knowingly.
369
+ - A metric that was never computed at all will not show up in any accounting (S7 only sees the grid
370
+ of what was computed).
371
+
372
+ ---
373
+
374
+ ## 5. Eight survivors, ranked by (cost → what it kills)
375
+
376
+ | # | Mechanism | Kills | Cost | Occupancy |
377
+ | ------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ----------------------------------- | ------------------------------------------------------------ |
378
+ | **S8** | unbound numbers **render with a marker** in the draft build | the 264 exempted self-liquidate | ~5 lines in `md2submission.py` | unoccupied |
379
+ | **S4** | a gate **cannot be registered** without a killed mutant | instance #4 (vacuousness) | ~20 lines in `skills.harness.mjs` | published as an ablation, the mechanism itself is unoccupied |
380
+ | **S6** | a **decidable/undecidable** label on the gate | instance #2 (proxy as property) | a field + a column | MISRA, take as-is |
381
+ | **S5** | least-privilege judges; N of the same family = **1** witness | instance #5 (correlation) | a ledger field + a narrowed prompt | unoccupied |
382
+ | **S2** | **arm declared by a block** instead of phrase lists | instance #1, no prose heuristics | a block attribute + string equality | no occupancy found |
383
+ | **S1** | **one binding, three carriers** (numbers + citations + `CLAIMS.md`) | a retracted claim ends up in the PDF | medium, a resolver exists | ResearchLoop calls it "paper bindings" — **check the PDF** |
384
+ | **S3** | a ladder by **position** (abstract/section-lead-in = binding required; appendix = optional) + a deadline | the 264 with no expiration | medium | SPARK/DO-178C, take the form |
385
+ | **S7** | **arm × metric** accounting: every cell is either cited or explicitly marked not reported | measured-and-not-reported (cherry-picking) | a diff script | CONSORT — the form; no application found for our case |
386
+
387
+ **Why a ladder by POSITION and not a global deadline:** an unbound number in the abstract and one
388
+ in appendix B differ by an order of magnitude in blast radius. A single author does not convert 264
389
+ positions; they convert the ones a reviewer will quote. This is the DO-178C move (assurance level by
390
+ consequence of failure), not the MEL move (a single deadline), and it is more honest about a real
391
+ budget.
392
+
393
+ ---
394
+
395
+ ## 6. Negative results and honesty about method
396
+
397
+ **Groups that gave nothing** (don't re-sweep these): **B3** (TLA+/Alloy on the process — the
398
+ invariant is already computed), **C3** (session types on ordering — absorbed by staleness), **C2**
399
+ (claim-strength lattice — occupied by the spin literature), **D2** (complete mediation at the
400
+ paragraph level — killed by friction), **F3** (sidecar claims — killed by the AOP lesson), **A4**
401
+ (instance resolution — a duplicate of A2), **C4's strong form** (markdown as a pure projection —
402
+ killed by migration cost).
403
+
404
+ **🔴 Departure from the skill's procedure, stated plainly.** The skill requires generating
405
+ candidates via **a subagent with no thread context**. In this environment there is no
406
+ subagent-spawning tool (`Task` is unavailable; there is only cross-session, asynchronous
407
+ `SendMessage`/`create_session`). Generation was done by me, under the discipline "from the catalog's
408
+ named constructions," **after** reading the pipeline — meaning the thread anchor was **not**
409
+ removed. Practical consequence: §3 should be considered complete by group, but possibly incomplete on
410
+ the "non-obvious" candidates — exactly the class that produced the three best ideas last time.
411
+ Compensated by where the budget actually went: **the occupancy check**, which no anchor fixes and
412
+ which is what turned the picture around here (§0.1).
413
+
414
+ **Evidence levels:** [A] read in full at the primary source · [B] abstract verbatim ·
415
+ [C] search results · [D] a PDF summarized by a small model, **do not trust**.
416
+
417
+ ---
418
+
419
+ ## 7. What to do (ranked by benefit-to-cost, descending)
420
+
421
+ 1. **P0 · Read both PDFs in full** (2606.09500, 2605.28282). Summaries are [D]. How much of
422
+ S1/S4/S7 remains ours depends on their content.
423
+ 2. **P0 · Re-check the claim in the `paper_numbers.py` docstring** — _"Not one of them has a hook
424
+ where you could say the sentence around this number must say counterfactual and must not say as
425
+ committed"_ — against **MedSci's 21 detectors**. The claim was written before this work was known
426
+ about; if it's false, it's false **both in shipped code and in the novelty reasoning**.
427
+ 3. **P1 · Build S8 and S4** — together that is under fifty lines and closes two of the five
428
+ instances.
429
+ 4. **P1 · Diff our eight checkers against their 21** — cheaper than any generation.
430
+ 5. **P2 · S2 and S1** — the constructive part; S1 is itself the answer to "how it should be
431
+ ideally."
432
+ 6. **P3 · S3 and S7** — require budget, do after submission.
433
+
434
+ ---
435
+
436
+ # 8. Second pass, FOR REFUTATION (2026-08-09, addendum)
437
+
438
+ A separate `sweep-design-space` run. The goal is not to redo the sweep but to attack its single
439
+ most load-bearing part. §0.1 kills the architecture-novelty claim, is marked **[B]**, and warns
440
+ about confabulation about itself ("stylistically resembles confabulation"). Per the base's own rule
441
+ ("a conclusion that changes a decision → a second pass for refutation"), this must be re-checked
442
+ before it is cited as fact.
443
+
444
+ **Method: the model is removed from the decision loop.** The previous pass read the PDF through
445
+ WebFetch, where a small model synthesizes the answer — exactly the mechanism under suspicion here.
446
+ Instead: raw XML from the arXiv API (`export.arxiv.org/api/query?id_list=…`) and **a clone of the
447
+ source repository**. Not a single model summary in the chain. The level rises to **[A]**.
448
+
449
+ ## 8.1 ✅ §0.1 HELD — both works are real, quotes are verbatim
450
+
451
+ | field | 2606.09500 | 2605.28282 |
452
+ | -------------- | ------------------------------------------------- | ------------------------------ |
453
+ | `totalResults` | 1 | 1 |
454
+ | version | **v4** | v1 |
455
+ | `published` | **2026-06-08T13:51:04Z** | **2026-05-27T10:29:00Z** |
456
+ | `updated` | 2026-06-14T00:06:13Z | 2026-05-27T10:29:00Z |
457
+ | authors | Yoojin **Nam**, Jinhoon **Jeong**, Namkug **Kim** | Yihan **Xia**, Taotao **Wang** |
458
+ | category | cs.AI (+cs.DL) | cs.AI |
459
+
460
+ The title of 2606.09500 (not given in §0.1): _«Deterministic Integrity Gates for LLM-Assisted
461
+ Clinical Manuscript Preparation: An Auditable Biomedical Informatics Architecture»_.
462
+ Both abstract paragraphs in §0.1 were checked character-by-character against the API output —
463
+ **no discrepancies**. The architecture's occupancy is confirmed. The claim "we built a
464
+ manuscript-verification architecture" remains dead, and it is now [A] rather than [B].
465
+
466
+ From the arXiv comment (absent from §0.1, and it is the key to everything below):
467
+
468
+ > Software (MIT): `https://github.com/Aperivue/medsci-skills` . Archived on Zenodo: concept DOI
469
+ > `10.5281/zenodo.20155321` and version DOI (v3.8.0) `10.5281/zenodo.20582972`
470
+
471
+ ## 8.2 🔴 S4 IS OCCUPIED — and its owner has already published it — WHY THAT IS NOT ENOUGH
472
+
473
+ The repository was cloned and checked for identity:
474
+ `aperivue/medsci-skills`, HEAD `b2c120e667d5a329add8ae5bc3371411f739bd60`, origin verified.
475
+
476
+ **S4 in the §5 table** ranked second by cost/benefit: _"a gate cannot be registered without a
477
+ killed mutant, ~20 lines in `skills.harness.mjs`"_, occupancy — _"published as an ablation, the
478
+ mechanism is unoccupied"_.
479
+
480
+ **The mechanism is NOT unoccupied. It has been shipped, under MIT, across 85 detectors.**
481
+ Verbatim, `paper.md:23`:
482
+
483
+ > «Each detector ships a synthetic **challenge card** — a positive case and a negative control —
484
+ > that runs in continuous integration, so **a clean result is meaningful** and a flagged defect is
485
+ > reproducible.»
486
+
487
+ "so a clean result is meaningful" — that is exactly our anti-vacuousness argument, in their prose.
488
+ On top of the card, they have a second leg — `check_detector_crossfire.py` (a detector must **stay
489
+ silent** on clean demo manuscripts).
490
+
491
+ **And that is not even the main thing.** `reverse_engineer/HELDOUT.md:3–17`, verbatim:
492
+
493
+ > «Every detector in this repo is tested against fixtures authored alongside it: a challenge card
494
+ > proving it fires on a planted defect, and `check_detector_crossfire.py` proving it stays silent on
495
+ > the demo manuscripts. Both are necessary. **Neither is independent.** In machine-learning terms
496
+ > they are a **training set**, and a detector passing its own challenge card is a **training accuracy
497
+ > of 100% — true, and uninformative about anything.**»
498
+
499
+ > «An improvement loop whose generator and evaluator share a framing drifts toward the evaluator
500
+ > rather than the goal — the measured quality rises while the unmeasured quality falls. **The
501
+ > counterweight is not another gate. Adding gates is what produces the drift.** The counterweight is
502
+ > a set of cases the gates were never allowed to learn from, scored periodically, whose trend can
503
+ > contradict us.»
504
+
505
+ Their replacement is a held-out corpus with a mandatory `frozen_at` field:
506
+
507
+ > «`frozen_at` is required on every held-out record, because the claim is chronological: a freeze
508
+ > date that **precedes the detector** is what makes it checkable rather than asserted.»
509
+
510
+ **Consequence for S4 — rewrite, don't discard.** A harness case planted by the gate's own author
511
+ gives 100% training accuracy. That is still strictly better than nothing (it catches instance #4 —
512
+ a gate that never once said "no"), but **it cannot be claimed as sufficient**, and even less so as
513
+ novel. The honest form of S4 is two tiers, where the second is the real one — (a) the author's card =
514
+ admission, training; (b) a corpus frozen **before** the gate was written = the one measurement worth
515
+ trusting. We have (b) in no form at all.
516
+
517
+ To be honest about the caveat: their own HELDOUT.md records that the rule **was violated on
518
+ 2026-07-31** (three agents reached `_corpus/heldout/`, one ran a detector against the corpus). The
519
+ finding was quarantined and not applied. This does not weaken the mechanism — it shows its cost.
520
+
521
+ ## 8.3 🔴 The "21 detectors" number is stale — theirs is **85**, and the catalog is machine-generated
522
+
523
+ `metadata/detectors_catalog.json`, field `detector_count` = **85** (not 21; 21 is the June paper's
524
+ number, the repo has moved on). Breakdown by family, verbatim from the catalog:
525
+
526
+ | n | family_label |
527
+ | --- | --------------------------------------- |
528
+ | 24 | Style & review-process integrity |
529
+ | 17 | Data preparation & validation |
530
+ | 17 | Reporting compliance |
531
+ | 11 | Numerical, cohort & pool arithmetic |
532
+ | 9 | Citation & reference integrity |
533
+ | 7 | Confounding, scope & estimand contracts |
534
+
535
+ The catalog itself is **AUTO-GENERATED** (`scripts/gen_detectors_catalog_json.py` globbing
536
+ `skills/*/scripts/`, with a CI gate on drift). So their registry is **derived, not declared** — the
537
+ same discipline as our `status.mjs`, and confirmation that §2.2 (the retired reason about "a second
538
+ declaration") was closed correctly.
539
+
540
+ **P1 #4 from §7 is reformulated:** the diff is not "our 8 against their 21" but **our 7 against
541
+ their 85** (there are exactly 7 gates in `run-mechanical.mjs`, not 8 — recounted). Diffing by
542
+ family: our seven fall entirely inside "Numerical" + "Style", and **three of their families are
543
+ represented by nothing of ours** — Reporting compliance, Data preparation, Confounding/estimand.
544
+ Directly relevant to our topic is "Citation & reference integrity" (9 detectors) — that is carrier
545
+ #2 from Law 2 (citations), which is listed in our §5/S1 as unwritten.
546
+
547
+ ## 8.4 🔴 An attack on the frame of the whole sweep
548
+
549
+ The sentence _«The counterweight is not another gate. Adding gates is what produces the drift»_
550
+ hits not one candidate but the shape of the whole answer: §5 is a list of eight **new gates**. It
551
+ does not invalidate S1–S8 (our instances #1–#5 are real and observed), but it adds a filter that
552
+ wasn't in §2 and that needs to be recorded in the skill:
553
+
554
+ > **Filter: what measures whether a new gate actually helped?** A gate whose effect is observable
555
+ > only through the same gates raises measured quality and says nothing about the unmeasured kind.
556
+
557
+ By this filter, S8 (the marker in the draft build) looks **better** than all the rest: its
558
+ feedback lands on the human, in the PDF, not in a gate table. S8's rank of #1 in §5 is confirmed
559
+ independently.
560
+
561
+ ## 8.5 What is still unoccupied (checked by grepping their repo)
562
+
563
+ - **S6** (a `decidable/undecidable` label on the gate) — they have `family`, but there is **no**
564
+ proxy-honesty label: `grep -ri undecidable` over the repo → **zero hits**. Unoccupied, stands.
565
+ - **S3** (the ladder + an expiration date on exemptions) — `grep -ri grandfather` → **zero**.
566
+ Unoccupied.
567
+ - **S1/S2/S7** — no direct matches found, but this was only checked by grepping keywords, not by
568
+ reading all 85 detectors. Level **[C]**, not [A].
569
+
570
+ ## 8.6 Occupancy is wider than two papers
571
+
572
+ `paper.md` in their repo is a **third** artifact: a separate software paper that cites 2606.09500
573
+ as a companion (`[@nam2026gates]`, _«conducted on an earlier release of the toolkit»_). So this is
574
+ not "two papers" but an actively developing line of work from 2026-05 to 2026-08. The previous
575
+ occupancy pass did not see this.
576
+
577
+ ## 8.7 What this pass did NOT do
578
+
579
+ - **P0 #1 (read both PDFs in full) — still NOT closed.** The abstracts [A] and shipped code [A]
580
+ were checked; the bodies of the papers were not read. Everything §0.1 derives from the bodies
581
+ remains [B]/[D].
582
+ - No generation of new candidates was done — this pass was a verification pass. The gap from §6
583
+ (generation without thread context) **remains open**; `Task` is still unavailable in this
584
+ environment.
585
+ - S1/S2/S7 against their 85 detectors were checked by grepping, not by reading — [C].