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.
- package/.github/dependabot.yml +72 -0
- package/.github/workflows/ci.yml +297 -0
- package/.github/workflows/dependabot-automerge.yml +70 -0
- package/.github/workflows/pr-title.yml +59 -0
- package/.github/workflows/release.yml +54 -0
- package/CLAUDE.md +598 -0
- package/CONTRIBUTING.md +159 -0
- package/LICENSE +21 -0
- package/README.md +240 -0
- package/action.harness.mjs +287 -0
- package/action.mutations.mjs +162 -0
- package/action.yml +138 -0
- package/bin/rpp.mjs +43 -0
- package/dist/action-ref.d.ts +12 -0
- package/dist/action-ref.d.ts.map +1 -0
- package/dist/action-ref.js +16 -0
- package/dist/action-ref.js.map +1 -0
- package/dist/adapters/banal/failure.d.ts +73 -0
- package/dist/adapters/banal/failure.d.ts.map +1 -0
- package/dist/adapters/banal/failure.js +58 -0
- package/dist/adapters/banal/failure.js.map +1 -0
- package/dist/adapters/banal/index.d.ts +17 -0
- package/dist/adapters/banal/index.d.ts.map +1 -0
- package/dist/adapters/banal/index.js +56 -0
- package/dist/adapters/banal/index.js.map +1 -0
- package/dist/adapters/banal/install.d.ts +26 -0
- package/dist/adapters/banal/install.d.ts.map +1 -0
- package/dist/adapters/banal/install.js +15 -0
- package/dist/adapters/banal/install.js.map +1 -0
- package/dist/adapters/banal/invocation.d.ts +48 -0
- package/dist/adapters/banal/invocation.d.ts.map +1 -0
- package/dist/adapters/banal/invocation.js +43 -0
- package/dist/adapters/banal/invocation.js.map +1 -0
- package/dist/adapters/banal/locate.d.ts +50 -0
- package/dist/adapters/banal/locate.d.ts.map +1 -0
- package/dist/adapters/banal/locate.js +34 -0
- package/dist/adapters/banal/locate.js.map +1 -0
- package/dist/adapters/banal/output.d.ts +27 -0
- package/dist/adapters/banal/output.d.ts.map +1 -0
- package/dist/adapters/banal/output.js +112 -0
- package/dist/adapters/banal/output.js.map +1 -0
- package/dist/adapters/banal/pin.d.ts +19 -0
- package/dist/adapters/banal/pin.d.ts.map +1 -0
- package/dist/adapters/banal/pin.js +15 -0
- package/dist/adapters/banal/pin.js.map +1 -0
- package/dist/adapters/banal/probe.d.ts +12 -0
- package/dist/adapters/banal/probe.d.ts.map +1 -0
- package/dist/adapters/banal/probe.js +27 -0
- package/dist/adapters/banal/probe.js.map +1 -0
- package/dist/adapters/banal/run.d.ts +89 -0
- package/dist/adapters/banal/run.d.ts.map +1 -0
- package/dist/adapters/banal/run.js +104 -0
- package/dist/adapters/banal/run.js.map +1 -0
- package/dist/adapters/banal/settings.d.ts +18 -0
- package/dist/adapters/banal/settings.d.ts.map +1 -0
- package/dist/adapters/banal/settings.js +29 -0
- package/dist/adapters/banal/settings.js.map +1 -0
- package/dist/adapters/banal/xml.d.ts +48 -0
- package/dist/adapters/banal/xml.d.ts.map +1 -0
- package/dist/adapters/banal/xml.js +67 -0
- package/dist/adapters/banal/xml.js.map +1 -0
- package/dist/adapters/curl/download.io.d.ts +14 -0
- package/dist/adapters/curl/download.io.d.ts.map +1 -0
- package/dist/adapters/curl/download.io.js +69 -0
- package/dist/adapters/curl/download.io.js.map +1 -0
- package/dist/adapters/curl/index.d.ts +6 -0
- package/dist/adapters/curl/index.d.ts.map +1 -0
- package/dist/adapters/curl/index.js +6 -0
- package/dist/adapters/curl/index.js.map +1 -0
- package/dist/adapters/memory/index.d.ts +43 -0
- package/dist/adapters/memory/index.d.ts.map +1 -0
- package/dist/adapters/memory/index.js +79 -0
- package/dist/adapters/memory/index.js.map +1 -0
- package/dist/adapters/node/files.io.d.ts +3 -0
- package/dist/adapters/node/files.io.d.ts.map +1 -0
- package/dist/adapters/node/files.io.js +31 -0
- package/dist/adapters/node/files.io.js.map +1 -0
- package/dist/adapters/node/host.io.d.ts +3 -0
- package/dist/adapters/node/host.io.d.ts.map +1 -0
- package/dist/adapters/node/host.io.js +14 -0
- package/dist/adapters/node/host.io.js.map +1 -0
- package/dist/adapters/node/index.d.ts +25 -0
- package/dist/adapters/node/index.d.ts.map +1 -0
- package/dist/adapters/node/index.js +14 -0
- package/dist/adapters/node/index.js.map +1 -0
- package/dist/adapters/node/process.io.d.ts +14 -0
- package/dist/adapters/node/process.io.d.ts.map +1 -0
- package/dist/adapters/node/process.io.js +41 -0
- package/dist/adapters/node/process.io.js.map +1 -0
- package/dist/adapters/node/workspace.io.d.ts +4 -0
- package/dist/adapters/node/workspace.io.d.ts.map +1 -0
- package/dist/adapters/node/workspace.io.js +33 -0
- package/dist/adapters/node/workspace.io.js.map +1 -0
- package/dist/adapters/pdfjs/fill.d.ts +42 -0
- package/dist/adapters/pdfjs/fill.d.ts.map +1 -0
- package/dist/adapters/pdfjs/fill.js +91 -0
- package/dist/adapters/pdfjs/fill.js.map +1 -0
- package/dist/build-engine.d.ts +48 -0
- package/dist/build-engine.d.ts.map +1 -0
- package/dist/build-engine.js +148 -0
- package/dist/build-engine.js.map +1 -0
- package/dist/build.d.ts +163 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +575 -0
- package/dist/build.js.map +1 -0
- package/dist/cli.d.ts +151 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +951 -0
- package/dist/cli.js.map +1 -0
- package/dist/doctor.d.ts +42 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +280 -0
- package/dist/doctor.js.map +1 -0
- package/dist/domain/geometry.d.ts +71 -0
- package/dist/domain/geometry.d.ts.map +1 -0
- package/dist/domain/geometry.js +35 -0
- package/dist/domain/geometry.js.map +1 -0
- package/dist/domain/host.d.ts +16 -0
- package/dist/domain/host.d.ts.map +1 -0
- package/dist/domain/host.js +8 -0
- package/dist/domain/host.js.map +1 -0
- package/dist/domain/page-layout.d.ts +34 -0
- package/dist/domain/page-layout.d.ts.map +1 -0
- package/dist/domain/page-layout.js +8 -0
- package/dist/domain/page-layout.js.map +1 -0
- package/dist/domain/paths.d.ts +5 -0
- package/dist/domain/paths.d.ts.map +1 -0
- package/dist/domain/paths.js +2 -0
- package/dist/domain/paths.js.map +1 -0
- package/dist/domain/result.d.ts +23 -0
- package/dist/domain/result.d.ts.map +1 -0
- package/dist/domain/result.js +10 -0
- package/dist/domain/result.js.map +1 -0
- package/dist/domain/sha256.d.ts +7 -0
- package/dist/domain/sha256.d.ts.map +1 -0
- package/dist/domain/sha256.js +14 -0
- package/dist/domain/sha256.js.map +1 -0
- package/dist/domain/text.d.ts +6 -0
- package/dist/domain/text.d.ts.map +1 -0
- package/dist/domain/text.js +7 -0
- package/dist/domain/text.js.map +1 -0
- package/dist/engine.d.ts +93 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +119 -0
- package/dist/engine.js.map +1 -0
- package/dist/exit-code.d.ts +22 -0
- package/dist/exit-code.d.ts.map +1 -0
- package/dist/exit-code.js +10 -0
- package/dist/exit-code.js.map +1 -0
- package/dist/facts-file.d.ts +96 -0
- package/dist/facts-file.d.ts.map +1 -0
- package/dist/facts-file.js +134 -0
- package/dist/facts-file.js.map +1 -0
- package/dist/hooks-settings.d.ts +141 -0
- package/dist/hooks-settings.d.ts.map +1 -0
- package/dist/hooks-settings.js +306 -0
- package/dist/hooks-settings.js.map +1 -0
- package/dist/init.d.ts +201 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +579 -0
- package/dist/init.js.map +1 -0
- package/dist/latex-log.d.ts +80 -0
- package/dist/latex-log.d.ts.map +1 -0
- package/dist/latex-log.js +187 -0
- package/dist/latex-log.js.map +1 -0
- package/dist/latex-loop.d.ts +129 -0
- package/dist/latex-loop.d.ts.map +1 -0
- package/dist/latex-loop.js +113 -0
- package/dist/latex-loop.js.map +1 -0
- package/dist/link-skills.d.ts +51 -0
- package/dist/link-skills.d.ts.map +1 -0
- package/dist/link-skills.js +199 -0
- package/dist/link-skills.js.map +1 -0
- package/dist/new-paper.d.ts +48 -0
- package/dist/new-paper.d.ts.map +1 -0
- package/dist/new-paper.js +110 -0
- package/dist/new-paper.js.map +1 -0
- package/dist/pdf-facts.d.ts +44 -0
- package/dist/pdf-facts.d.ts.map +1 -0
- package/dist/pdf-facts.js +239 -0
- package/dist/pdf-facts.js.map +1 -0
- package/dist/pdf-geometry.d.ts +170 -0
- package/dist/pdf-geometry.d.ts.map +1 -0
- package/dist/pdf-geometry.js +158 -0
- package/dist/pdf-geometry.js.map +1 -0
- package/dist/ports/download.d.ts +9 -0
- package/dist/ports/download.d.ts.map +1 -0
- package/dist/ports/download.js +2 -0
- package/dist/ports/download.js.map +1 -0
- package/dist/ports/files.d.ts +11 -0
- package/dist/ports/files.d.ts.map +1 -0
- package/dist/ports/files.js +2 -0
- package/dist/ports/files.js.map +1 -0
- package/dist/ports/measure-geometry.d.ts +8 -0
- package/dist/ports/measure-geometry.d.ts.map +1 -0
- package/dist/ports/measure-geometry.js +2 -0
- package/dist/ports/measure-geometry.js.map +1 -0
- package/dist/ports/process.d.ts +45 -0
- package/dist/ports/process.d.ts.map +1 -0
- package/dist/ports/process.js +2 -0
- package/dist/ports/process.js.map +1 -0
- package/dist/ports/tool-installer.d.ts +29 -0
- package/dist/ports/tool-installer.d.ts.map +1 -0
- package/dist/ports/tool-installer.js +2 -0
- package/dist/ports/tool-installer.js.map +1 -0
- package/dist/ports/workspace.d.ts +18 -0
- package/dist/ports/workspace.d.ts.map +1 -0
- package/dist/ports/workspace.js +2 -0
- package/dist/ports/workspace.js.map +1 -0
- package/dist/rules-config.d.ts +34 -0
- package/dist/rules-config.d.ts.map +1 -0
- package/dist/rules-config.js +132 -0
- package/dist/rules-config.js.map +1 -0
- package/dist/structure.d.ts +34 -0
- package/dist/structure.d.ts.map +1 -0
- package/dist/structure.js +149 -0
- package/dist/structure.js.map +1 -0
- package/dist/tex-requirements.d.ts +43 -0
- package/dist/tex-requirements.d.ts.map +1 -0
- package/dist/tex-requirements.js +127 -0
- package/dist/tex-requirements.js.map +1 -0
- package/dist/toolchain.d.ts +159 -0
- package/dist/toolchain.d.ts.map +1 -0
- package/dist/toolchain.js +542 -0
- package/dist/toolchain.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docs/configuration.md +235 -0
- package/docs/e2e.md +152 -0
- package/docs/incidents.md +59 -0
- package/docs/install.md +170 -0
- package/docs/optional-rules.md +107 -0
- package/docs/package-shape-options.md +262 -0
- package/docs/prior-art/README.md +76 -0
- package/docs/prior-art/blocking-vs-advisory.md +83 -0
- package/docs/prior-art/content-delivery.md +124 -0
- package/docs/prior-art/multi-mode-tools.md +106 -0
- package/docs/prior-art/nondeterministic-checks.md +99 -0
- package/docs/prior-art/package-location.md +422 -0
- package/docs/prior-art/paper-folder-scaffolding.md +538 -0
- package/docs/prior-art/readme-structure.md +69 -0
- package/docs/prior-art/repro/README.md +92 -0
- package/docs/prior-art/repro/claim1-allowedtools.mjs +66 -0
- package/docs/prior-art/repro/claim1-at2.mjs +40 -0
- package/docs/prior-art/repro/claim1-crosschannel.mjs +54 -0
- package/docs/prior-art/repro/claim1-frontmatter.mjs +76 -0
- package/docs/prior-art/repro/claim1-hook-payload-reporter.mjs +10 -0
- package/docs/prior-art/repro/claim1-plugin-frontmatter.mjs +27 -0
- package/docs/prior-art/repro/claim1-plugin-skill.mjs +52 -0
- package/docs/prior-art/repro/claim1-project-skill.mjs +81 -0
- package/docs/prior-art/repro/claim2-marketplace-flat-asclaimed.json +1 -0
- package/docs/prior-art/repro/claim2-marketplace-negative-control.json +1 -0
- package/docs/prior-art/repro/claim2-marketplace-nested-exact.json +9 -0
- package/docs/prior-art/repro/claim2-marketplace-nested-noversion.json +9 -0
- package/docs/prior-art/repro/claim2-marketplace-nested-range.json +1 -0
- package/docs/prior-art/repro/claim3-imports.mjs +50 -0
- package/docs/prior-art/repro/claim4-find-package-json.mjs +8 -0
- package/docs/prior-art/repro/claim4-package-dir.mjs +39 -0
- package/docs/prior-art/repro/claim4-parent-arg.mjs +17 -0
- package/docs/prior-art/repro/claim4-resolve-apis.mjs +21 -0
- package/docs/prior-art/repro/claim4-setup-consumers.mjs +45 -0
- package/docs/prior-art/repro/claim4-yarn-pnp.mjs +70 -0
- package/docs/prior-art/repro/claim5-bin-launch.mjs +39 -0
- package/docs/prior-art/repro/claim5-exports-mutation.mjs +57 -0
- package/docs/prior-art/repro/claim5-resolved-location-and-bin.mjs +33 -0
- package/docs/prior-art/repro/claim6-candidate-ambiguity.mjs +17 -0
- package/docs/prior-art/repro/claim6-doc-path-candidates.mjs +27 -0
- package/docs/prior-art/test-tooling.md +131 -0
- package/docs/rules.md +58 -0
- package/docs/texlive-install-decision.md +230 -0
- package/docs/toolchain.md +152 -0
- package/eslint-rules/doc-fields.harness.mjs +336 -0
- package/eslint-rules/doc-fields.mjs +186 -0
- package/eslint-rules/doc-fields.mutations.mjs +96 -0
- package/eslint-rules/install-path-literals.harness.mjs +121 -0
- package/eslint-rules/install-path-literals.mjs +108 -0
- package/eslint-rules/install-path-literals.mutations.mjs +62 -0
- package/eslint-rules/latex-language.harness.mjs +599 -0
- package/eslint-rules/latex-language.mjs +591 -0
- package/eslint-rules/latex-language.mutations.mjs +196 -0
- package/eslint-rules/paper-research-question.harness.mjs +146 -0
- package/eslint-rules/paper-research-question.mjs +180 -0
- package/eslint-rules/paper-research-question.mutations.mjs +127 -0
- package/eslint-rules/paper-stages.harness.mjs +356 -0
- package/eslint-rules/paper-stages.mjs +455 -0
- package/eslint-rules/paper-stages.mutations.mjs +157 -0
- package/eslint-rules/paper-typography.harness.mjs +291 -0
- package/eslint-rules/paper-typography.mjs +313 -0
- package/eslint-rules/paper-typography.mutations.mjs +131 -0
- package/eslint-rules/papers.harness.mjs +259 -0
- package/eslint-rules/papers.mjs +166 -0
- package/eslint-rules/papers.mutations.mjs +186 -0
- package/eslint-rules/pdf-last-page-balance.harness.mjs +206 -0
- package/eslint-rules/pdf-last-page-balance.mjs +208 -0
- package/eslint-rules/review-findings-cause.harness.mjs +228 -0
- package/eslint-rules/review-findings-cause.mjs +135 -0
- package/eslint-rules/review-findings-cause.mutations.mjs +72 -0
- package/eslint-rules/temp-root-realpath.harness.mjs +176 -0
- package/eslint-rules/temp-root-realpath.mjs +129 -0
- package/eslint-rules/temp-root-realpath.mutations.mjs +99 -0
- package/eslint-rules/tex-build.harness.mjs +753 -0
- package/eslint-rules/tex-build.mjs +322 -0
- package/eslint-rules/tex-build.mutations.mjs +258 -0
- package/eslint.config.mjs +521 -0
- package/fixtures/build-e2e/acmart/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/acmart/paper.tex +11 -0
- package/fixtures/build-e2e/acmart/venue.json +1 -0
- package/fixtures/build-e2e/broken/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/broken/paper.tex +7 -0
- package/fixtures/build-e2e/cite/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/cite/build.sh +5 -0
- package/fixtures/build-e2e/cite/paper.tex +10 -0
- package/fixtures/build-e2e/cite/refs.bib +9 -0
- package/fixtures/build-e2e/empty/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/empty/paper.tex +6 -0
- package/fixtures/build-e2e/fallback/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/fallback/paper.tex +11 -0
- package/fixtures/build-e2e/guards/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/guards/paper.tex +10 -0
- package/fixtures/build-e2e/no-source/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/unbalanced/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/unbalanced/paper.tex +28 -0
- package/fixtures/build-e2e/unbalanced/refs.bib +269 -0
- package/fixtures/install-path-literals/clean.fixture.mjs +3 -0
- package/fixtures/install-path-literals/clean.md +15 -0
- package/fixtures/install-path-literals/defect.fixture.mjs +3 -0
- package/fixtures/install-path-literals/defect.md +14 -0
- package/fixtures/latex-language/clean.tex +50 -0
- package/fixtures/latex-language/defect.tex +52 -0
- package/fixtures/paper-research-question/comment-only/PIPELINE-STATUS.md +9 -0
- package/fixtures/paper-research-question/comment-only/paper.tex +7 -0
- package/fixtures/paper-research-question/declared-not-in-paper/PIPELINE-STATUS.md +10 -0
- package/fixtures/paper-research-question/declared-not-in-paper/paper.tex +6 -0
- package/fixtures/paper-research-question/draft/PIPELINE-STATUS.md +6 -0
- package/fixtures/paper-research-question/draft/paper.tex +2 -0
- package/fixtures/paper-research-question/markdown-no-rq/PIPELINE-STATUS.md +9 -0
- package/fixtures/paper-research-question/markdown-no-rq/paper.md +4 -0
- package/fixtures/paper-research-question/shipped-no-rq/PIPELINE-STATUS.md +12 -0
- package/fixtures/paper-research-question/shipped-no-rq/paper.tex +3 -0
- package/fixtures/paper-research-question/shipped-with-rq/PIPELINE-STATUS.md +10 -0
- package/fixtures/paper-research-question/shipped-with-rq/paper.tex +2 -0
- package/fixtures/paper-stages/authors-ran/PIPELINE-STATUS.md +16 -0
- package/fixtures/paper-stages/marker-in-prose/PIPELINE-STATUS.md +17 -0
- package/fixtures/paper-stages/nofile/PIPELINE-STATUS.md +8 -0
- package/fixtures/paper-stages/noheader/PIPELINE-STATUS.md +1 -0
- package/fixtures/paper-stages/noheader/versions/2026-07-22-submitted.pdf +0 -0
- package/fixtures/paper-stages/nothing/PIPELINE-STATUS.md +3 -0
- package/fixtures/paper-stages/ok/PIPELINE-STATUS.md +9 -0
- package/fixtures/paper-stages/ok/versions/2026-07-22-submitted.pdf +0 -0
- package/fixtures/paper-stages/stale/PIPELINE-STATUS.md +1 -0
- package/fixtures/paper-stages/stale/versions/2026-07-22-submitted.STALE-WRONG-FILE.pdf +0 -0
- package/fixtures/paper-stages/twice/PIPELINE-STATUS.md +14 -0
- package/fixtures/paper-stages/twice/versions/2026-08-06-submitted.pdf +0 -0
- package/fixtures/paper-stages/twice/versions/2026-10-24-submitted.pdf +0 -0
- package/fixtures/paper-stages/undeclared/PIPELINE-STATUS.md +8 -0
- package/fixtures/paper-stages/undeclared/versions/2026-07-22-submitted.pdf +0 -0
- package/fixtures/paper-stages/undeclared/versions/2026-08-29-camera-ready.pdf +0 -0
- package/fixtures/paper-stages/wrongsize/PIPELINE-STATUS.md +8 -0
- package/fixtures/paper-stages/wrongsize/versions/2026-07-22-submitted.pdf +0 -0
- package/fixtures/paper-typography/clean-paper/paper.tex +29 -0
- package/fixtures/paper-typography/messy-paper/paper.tex +27 -0
- package/fixtures/pdf-facts/README.md +22 -0
- package/fixtures/pdf-facts/corrupt-font.pdf +0 -0
- package/fixtures/pdf-facts/encrypted.pdf +0 -0
- package/fixtures/pdf-facts/hidden-text.pdf +0 -0
- package/fixtures/pdf-facts/hidden-text.tex +28 -0
- package/fixtures/pdf-facts/t3-all.pdf +0 -0
- package/fixtures/pdf-facts/t3-all.tex +8 -0
- package/fixtures/pdf-facts/t3-mixed.pdf +0 -0
- package/fixtures/pdf-facts/t3-mixed.tex +9 -0
- package/fixtures/pdf-facts/ttf.pdf +2240 -1
- package/fixtures/pdf-facts/ttf.tex +6 -0
- package/fixtures/real-markdown-paper/baseline.json +24 -0
- package/fixtures/real-markdown-paper/baseline.mjs +48 -0
- package/fixtures/render-paper/build-clean.sh +25 -0
- package/fixtures/render-paper/build-defect.sh +15 -0
- package/fixtures/review-findings-cause/clean.md +17 -0
- package/fixtures/review-findings-cause/defect.md +14 -0
- package/fixtures/review-findings-cause/old-debt.md +14 -0
- package/fixtures/review-findings-cause/quiet-in-fence.md +16 -0
- package/fixtures/tex-build/clean.tex +21 -0
- package/fixtures/tex-build/defect.tex +24 -0
- package/fixtures/tex-build/frontmatter-clean.tex +25 -0
- package/fixtures/tex-build/frontmatter-defect.tex +23 -0
- package/fixtures/toolchain-mirror/catalog.txt +5 -0
- package/fixtures/toolchain-mirror/install-tl +27 -0
- package/fixtures/toolchain-mirror/release-texlive.txt +3 -0
- package/fixtures/toolchain-mirror/release-year +1 -0
- package/fixtures/toolchain-mirror/stub-kpsewhich +8 -0
- package/fixtures/toolchain-mirror/stub-pdflatex +3 -0
- package/fixtures/toolchain-mirror/stub-tlmgr +44 -0
- package/hooks/hooks.harness.mjs +713 -0
- package/hooks/hooks.mutations.mjs +337 -0
- package/hooks/paper-edit-guard.hook.d.mts +13 -0
- package/hooks/paper-edit-guard.hook.mjs +457 -0
- package/hooks/paper-skills-nudge.hook.mjs +136 -0
- package/hooks/paper-status-gates.hook.mjs +156 -0
- package/hooks/paper-status-gates.sh +91 -0
- package/lib/agent-cli-version.harness.mjs +165 -0
- package/lib/agent-cli-version.mjs +106 -0
- package/lib/agent-cli-version.mutations.mjs +109 -0
- package/lib/markdown.mjs +386 -0
- package/lib/mutation-driver.harness.mjs +227 -0
- package/lib/mutation-driver.mjs +397 -0
- package/lib/mutation-driver.mutations.mjs +68 -0
- package/lib/paper-config.d.mts +34 -0
- package/lib/paper-config.harness.mjs +286 -0
- package/lib/paper-config.mjs +142 -0
- package/lib/paper-config.mutations.mjs +143 -0
- package/lib/skill-checks.mjs +701 -0
- package/lib/skill-corpus.mjs +403 -0
- package/lib/skill-eval-fixture.mjs +63 -0
- package/lib/skill-eval-kit.mjs +257 -0
- package/lib/skill-trigger-cases.harness.mjs +170 -0
- package/lib/skill-trigger-cases.mjs +446 -0
- package/lib/skill-trigger-cases.mutations.mjs +65 -0
- package/lib/trigger-ledger.mjs +215 -0
- package/package.json +97 -0
- package/plugin/.claude-plugin/plugin.json +8 -0
- package/plugin/hooks/hooks.json +30 -0
- package/scripts/check.harness.mjs +177 -0
- package/scripts/check.mjs +239 -0
- package/scripts/check.mutations.mjs +110 -0
- package/scripts/eslint-report-guard.mjs +82 -0
- package/scripts/exclusive.mjs +138 -0
- package/scripts/harness-api.frozen.json +76 -0
- package/scripts/harness-api.test.ts +175 -0
- package/scripts/layer-legacy-frozen.d.mts +28 -0
- package/scripts/layer-legacy-frozen.mjs +152 -0
- package/scripts/layer-legacy-frozen.test.ts +115 -0
- package/scripts/layer-legacy.frozen.json +50 -0
- package/scripts/mutation-batteries-frozen.harness.mjs +204 -0
- package/scripts/mutation-batteries-frozen.mjs +238 -0
- package/scripts/mutation-batteries.frozen.json +117 -0
- package/scripts/release-config.test.ts +90 -0
- package/scripts/rules-are-content-only.harness.mjs +113 -0
- package/scripts/rules-are-content-only.mjs +138 -0
- package/scripts/rules-are-content-only.mutations.mjs +81 -0
- package/scripts/rules-see-files.harness.mjs +115 -0
- package/scripts/rules-see-files.mjs +99 -0
- package/scripts/rules-see-files.mutations.mjs +131 -0
- package/scripts/run-mutations.mjs +100 -0
- package/scripts/semantic-release-plugins.d.ts +16 -0
- package/skills/README.md +15 -0
- package/skills/analyze-sibling-paper/SKILL.md +170 -0
- package/skills/analyze-sibling-paper/SKILL.md.spec.ts +186 -0
- package/skills/analyze-sibling-paper/analyze-sibling-paper.eval.mjs +19 -0
- package/skills/analyze-sibling-paper/analyze-sibling-paper.harness.mjs +23 -0
- package/skills/argument-arc/SKILL.md +177 -0
- package/skills/argument-arc/SKILL.md.spec.ts +192 -0
- package/skills/argument-arc/argument-arc.eval.mjs +19 -0
- package/skills/argument-arc/argument-arc.harness.mjs +23 -0
- package/skills/build-benchmark/SKILL.md +213 -0
- package/skills/build-benchmark/SKILL.md.spec.ts +220 -0
- package/skills/build-benchmark/build-benchmark.eval.mjs +19 -0
- package/skills/build-benchmark/build-benchmark.harness.mjs +23 -0
- package/skills/build-benchmark/references/adversarial-cold-repro.md +68 -0
- package/skills/camera-ready/SKILL.md +148 -0
- package/skills/camera-ready/SKILL.md.spec.ts +164 -0
- package/skills/camera-ready/camera-ready.eval.mjs +19 -0
- package/skills/camera-ready/camera-ready.harness.mjs +23 -0
- package/skills/cold-read-diff/SKILL.md +160 -0
- package/skills/cold-read-diff/SKILL.md.spec.ts +166 -0
- package/skills/cold-read-diff/cold-read-diff.eval.mjs +19 -0
- package/skills/cold-read-diff/cold-read-diff.harness.mjs +23 -0
- package/skills/draft-paper/SKILL.md +152 -0
- package/skills/draft-paper/SKILL.md.spec.ts +169 -0
- package/skills/draft-paper/draft-paper.eval.mjs +19 -0
- package/skills/draft-paper/draft-paper.harness.mjs +23 -0
- package/skills/extend-paper/SKILL.md +99 -0
- package/skills/extend-paper/SKILL.md.spec.ts +116 -0
- package/skills/extend-paper/extend-paper.eval.mjs +19 -0
- package/skills/extend-paper/extend-paper.harness.mjs +23 -0
- package/skills/find-venue/SKILL.md +128 -0
- package/skills/find-venue/SKILL.md.spec.ts +145 -0
- package/skills/find-venue/find-venue.eval.mjs +19 -0
- package/skills/find-venue/find-venue.harness.mjs +23 -0
- package/skills/grade-paper-writing/SKILL.md +436 -0
- package/skills/grade-paper-writing/SKILL.md.spec.ts +453 -0
- package/skills/grade-paper-writing/fixtures/control_gopen.txt +1 -0
- package/skills/grade-paper-writing/fixtures/control_human_paper.txt +1 -0
- package/skills/grade-paper-writing/fixtures/rewrite.txt +1 -0
- package/skills/grade-paper-writing/fixtures/specimen.txt +1 -0
- package/skills/grade-paper-writing/fixtures/structure-checks.md +22 -0
- package/skills/grade-paper-writing/grade-paper-writing.eval.mjs +19 -0
- package/skills/grade-paper-writing/grade-paper-writing.harness.mjs +23 -0
- package/skills/grade-paper-writing/prose-lint.mjs +713 -0
- package/skills/harden-paper/SKILL.md +318 -0
- package/skills/harden-paper/SKILL.md.spec.ts +336 -0
- package/skills/harden-paper/check-numbers.sh +33 -0
- package/skills/harden-paper/check-release-claims.sh +35 -0
- package/skills/harden-paper/fixtures/uncited-assertions-sample.md +43 -0
- package/skills/harden-paper/fixtures/uncited-assertions-sample.tex +77 -0
- package/skills/harden-paper/harden-paper.eval.mjs +19 -0
- package/skills/harden-paper/harden-paper.harness.mjs +23 -0
- package/skills/map-prior-work/SKILL.md +211 -0
- package/skills/map-prior-work/SKILL.md.spec.ts +227 -0
- package/skills/map-prior-work/map-prior-work.eval.mjs +19 -0
- package/skills/map-prior-work/map-prior-work.harness.mjs +23 -0
- package/skills/osf-artifact-upload/SKILL.md +52 -0
- package/skills/osf-artifact-upload/SKILL.md.spec.ts +59 -0
- package/skills/osf-artifact-upload/osf-artifact-upload.eval.mjs +22 -0
- package/skills/osf-artifact-upload/osf-artifact-upload.harness.mjs +103 -0
- package/skills/paper-adversarial-review/SKILL.md +126 -0
- package/skills/paper-adversarial-review/SKILL.md.spec.ts +142 -0
- package/skills/paper-adversarial-review/paper-adversarial-review.eval.mjs +19 -0
- package/skills/paper-adversarial-review/paper-adversarial-review.harness.mjs +23 -0
- package/skills/paper-pipeline/PIPELINE-MAP.md +371 -0
- package/skills/paper-pipeline/SKILL.md +499 -0
- package/skills/paper-pipeline/SKILL.md.spec.ts +517 -0
- package/skills/paper-pipeline/description-language.eval.mjs +347 -0
- package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +891 -0
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1254 -0
- package/skills/paper-pipeline/paper-pipeline.eval.mjs +22 -0
- package/skills/paper-pipeline/paper-pipeline.harness.mjs +143 -0
- package/skills/paper-pipeline/pipeline-firing.baseline.json +270 -0
- package/skills/paper-pipeline/pipeline-firing.eval.mjs +664 -0
- package/skills/paper-pipeline/pipeline-language.eval.mjs +672 -0
- package/skills/paper-pipeline/references/acceptance-gate.md +329 -0
- package/skills/paper-pipeline/references/acl-venue-rules.md +142 -0
- package/skills/paper-pipeline/references/anonymization.md +68 -0
- package/skills/paper-pipeline/references/artifact-checklist.md +93 -0
- package/skills/paper-pipeline/references/body-vs-appendix.md +97 -0
- package/skills/paper-pipeline/references/credit-criteria.md +69 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/README.md +35 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/run_retext.mjs +24 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/sentences.txt +11 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-probe/test_sentences.py +25 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-prose-checkers.md +538 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-reproducible-tooling.md +431 -0
- package/skills/paper-pipeline/references/occupancy-2026-08-06-staleness-and-orchestration.md +592 -0
- package/skills/paper-pipeline/references/pipeline-status-template.md +162 -0
- package/skills/paper-pipeline/references/review-ratchet.md +36 -0
- package/skills/paper-pipeline/references/sweep-2026-08-09-ideal-pipeline.md +585 -0
- package/skills/paper-pipeline/references/writing-craft.md +448 -0
- package/skills/paper-pipeline/repro/2026-08-07-description-language-control.log +63 -0
- package/skills/paper-pipeline/repro/2026-08-07-fork-check.log +52 -0
- package/skills/paper-pipeline/repro/2026-08-07-fork-check2.log +33 -0
- package/skills/paper-pipeline/repro/2026-08-07-language-eval-pilot.log +33 -0
- package/skills/paper-pipeline/repro/2026-08-07-language-eval-raw.log +166 -0
- package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-oracle.json +338 -0
- package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-oracle.log +118 -0
- package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-raw.log +245 -0
- package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary.json +776 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-A6-oracle.log +53 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-A6-raw.log +89 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-oracle.json +450 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-oracle.log +136 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-raw.log +242 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-setupdiff.log +59 -0
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation.json +1032 -0
- package/skills/paper-pipeline/repro/2026-08-08-parent-replication-gpw.json +139 -0
- package/skills/paper-pipeline/repro/2026-08-08-parent-replication-gpw.log +98 -0
- package/skills/paper-pipeline/repro/2026-08-08-parent-replication.mjs +92 -0
- package/skills/paper-pipeline/repro/README.md +129 -0
- package/skills/paper-pipeline/repro/analyze-language-eval.py +116 -0
- package/skills/paper-pipeline/scripts/README.md +344 -0
- package/skills/paper-pipeline/scripts/announce.mjs +67 -0
- package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +496 -0
- package/skills/paper-pipeline/scripts/artifact-coverage.mjs +397 -0
- package/skills/paper-pipeline/scripts/artifact-coverage.mutations.mjs +218 -0
- package/skills/paper-pipeline/scripts/check-provenance.mjs +184 -0
- package/skills/paper-pipeline/scripts/consumer.d.mts +32 -0
- package/skills/paper-pipeline/scripts/consumer.harness.mjs +562 -0
- package/skills/paper-pipeline/scripts/consumer.mjs +535 -0
- package/skills/paper-pipeline/scripts/consumer.mutations.mjs +190 -0
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +457 -0
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +656 -0
- package/skills/paper-pipeline/scripts/extract-ref-facts.mutations.mjs +54 -0
- package/skills/paper-pipeline/scripts/fixtures/clean/PIPELINE-STATUS.md +51 -0
- package/skills/paper-pipeline/scripts/fixtures/dirty/PIPELINE-STATUS.md +52 -0
- package/skills/paper-pipeline/scripts/fixtures/dirty/paper.md +6 -0
- package/skills/paper-pipeline/scripts/fixtures/real-bib/refs.bib +153 -0
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +466 -0
- package/skills/paper-pipeline/scripts/generated-code.mjs +338 -0
- package/skills/paper-pipeline/scripts/generated-code.mutations.mjs +254 -0
- package/skills/paper-pipeline/scripts/ledger.mjs +623 -0
- package/skills/paper-pipeline/scripts/ledger.selftest.mjs +286 -0
- package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +389 -0
- package/skills/paper-pipeline/scripts/pipeline-check.mjs +737 -0
- package/skills/paper-pipeline/scripts/pipeline-check.mutations.mjs +54 -0
- package/skills/paper-pipeline/scripts/pipeline-edges.mjs +169 -0
- package/skills/paper-pipeline/scripts/population-map.harness.mjs +178 -0
- package/skills/paper-pipeline/scripts/population-map.mjs +181 -0
- package/skills/paper-pipeline/scripts/population-map.mutations.mjs +65 -0
- package/skills/paper-pipeline/scripts/population-map.selftest.mjs +122 -0
- package/skills/paper-pipeline/scripts/provenance.harness.mjs +240 -0
- package/skills/paper-pipeline/scripts/provenance.mutations.mjs +59 -0
- package/skills/paper-pipeline/scripts/round-diff.harness.mjs +881 -0
- package/skills/paper-pipeline/scripts/round-diff.mjs +576 -0
- package/skills/paper-pipeline/scripts/round-diff.mutations.mjs +276 -0
- package/skills/paper-pipeline/scripts/run-mechanical.mjs +633 -0
- package/skills/paper-pipeline/scripts/status.mjs +295 -0
- package/skills/paper-status/SKILL.md +183 -0
- package/skills/paper-status/SKILL.md.spec.ts +190 -0
- package/skills/paper-status/paper-status.eval.mjs +22 -0
- package/skills/paper-status/paper-status.harness.mjs +25 -0
- package/skills/pc-panel-review/SKILL.md +263 -0
- package/skills/pc-panel-review/SKILL.md.spec.ts +280 -0
- package/skills/pc-panel-review/pc-panel-review.eval.mjs +19 -0
- package/skills/pc-panel-review/pc-panel-review.harness.mjs +23 -0
- package/skills/plan-paper-timeline/SKILL.md +182 -0
- package/skills/plan-paper-timeline/SKILL.md.spec.ts +200 -0
- package/skills/plan-paper-timeline/fixtures/fake-google-calendar.mjs +239 -0
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +431 -0
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.mutations.mjs +65 -0
- package/skills/plan-paper-timeline/plan-paper-timeline.eval.mjs +19 -0
- package/skills/plan-paper-timeline/plan-paper-timeline.harness.mjs +23 -0
- package/skills/render-paper/SKILL.md +159 -0
- package/skills/render-paper/SKILL.md.spec.ts +166 -0
- package/skills/render-paper/check-render.sh +419 -0
- package/skills/render-paper/checkers-requirements.txt +55 -0
- package/skills/render-paper/ensure-checkers.sh +69 -0
- package/skills/render-paper/extract-pdf-facts.harness.mjs +166 -0
- package/skills/render-paper/extract-pdf-facts.mjs +144 -0
- package/skills/render-paper/render-paper.eval.mjs +19 -0
- package/skills/render-paper/render-paper.harness.mjs +339 -0
- package/skills/research-ideate/SKILL.md +136 -0
- package/skills/research-ideate/SKILL.md.spec.ts +152 -0
- package/skills/research-ideate/research-ideate.eval.mjs +19 -0
- package/skills/research-ideate/research-ideate.harness.mjs +23 -0
- package/skills/skill-contract.mutations.mjs +179 -0
- package/skills/study-accepted-papers/SKILL.md +206 -0
- package/skills/study-accepted-papers/SKILL.md.spec.ts +223 -0
- package/skills/study-accepted-papers/study-accepted-papers.eval.mjs +19 -0
- package/skills/study-accepted-papers/study-accepted-papers.harness.mjs +23 -0
- package/skills/submit-paper/SKILL.md +182 -0
- package/skills/submit-paper/SKILL.md.spec.ts +199 -0
- package/skills/submit-paper/check-deanon.sh +149 -0
- package/skills/submit-paper/references/publishers/acm.md +92 -0
- package/skills/submit-paper/references/venues/agenticdev.jsonc +108 -0
- package/skills/submit-paper/references/venues/agenticdev.md +139 -0
- package/skills/submit-paper/references/venues/agenticdev.tex +19 -0
- package/skills/submit-paper/references/venues/aisec.jsonc +101 -0
- package/skills/submit-paper/references/venues/aisec.md +105 -0
- package/skills/submit-paper/references/venues/paper-guards.tex +41 -0
- package/skills/submit-paper/references/venues/realm.jsonc +81 -0
- package/skills/submit-paper/references/venues/realm.md +155 -0
- package/skills/submit-paper/references/venues/tex-base.jsonc +50 -0
- package/skills/submit-paper/references/venues/venue-profile.schema.json +74 -0
- package/skills/submit-paper/submit-paper.eval.mjs +19 -0
- package/skills/submit-paper/submit-paper.harness.mjs +23 -0
- package/skills/sweep-design-space/SKILL.md +269 -0
- package/skills/sweep-design-space/SKILL.md.spec.ts +285 -0
- package/skills/sweep-design-space/sweep-design-space.eval.mjs +19 -0
- package/skills/sweep-design-space/sweep-design-space.harness.mjs +23 -0
- package/skills/tighten-paper/SKILL.md +368 -0
- package/skills/tighten-paper/SKILL.md.spec.ts +384 -0
- package/skills/tighten-paper/structure.mjs +371 -0
- package/skills/tighten-paper/tighten-paper.eval.mjs +19 -0
- package/skills/tighten-paper/tighten-paper.harness.mjs +23 -0
- package/skills/verify-citations/SKILL.md +328 -0
- package/skills/verify-citations/SKILL.md.spec.ts +345 -0
- package/skills/verify-citations/scripts/bib-authors.mjs +479 -0
- package/skills/verify-citations/scripts/bib-authors.test.mjs +175 -0
- package/skills/verify-citations/scripts/verify-cites.mjs +1108 -0
- package/skills/verify-citations/scripts/verify-cites.test.mjs +735 -0
- package/skills/verify-citations/verify-citations.eval.mjs +19 -0
- package/skills/verify-citations/verify-citations.harness.mjs +23 -0
- package/src/CLAUDE.md +51 -0
- package/src/action-ref.test.ts +26 -0
- package/src/action-ref.ts +15 -0
- package/src/adapters/banal/failure.test.ts +63 -0
- package/src/adapters/banal/failure.ts +118 -0
- package/src/adapters/banal/index.test.ts +119 -0
- package/src/adapters/banal/index.ts +100 -0
- package/src/adapters/banal/install.test.ts +20 -0
- package/src/adapters/banal/install.ts +41 -0
- package/src/adapters/banal/invocation.test.ts +74 -0
- package/src/adapters/banal/invocation.ts +95 -0
- package/src/adapters/banal/locate.test.ts +52 -0
- package/src/adapters/banal/locate.ts +84 -0
- package/src/adapters/banal/output.test.ts +140 -0
- package/src/adapters/banal/output.ts +141 -0
- package/src/adapters/banal/pin.ts +30 -0
- package/src/adapters/banal/probe.ts +35 -0
- package/src/adapters/banal/run.test.ts +191 -0
- package/src/adapters/banal/run.ts +244 -0
- package/src/adapters/banal/settings.test.ts +31 -0
- package/src/adapters/banal/settings.ts +55 -0
- package/src/adapters/banal/xml.test.ts +111 -0
- package/src/adapters/banal/xml.ts +112 -0
- package/src/adapters/curl/download.io.ts +73 -0
- package/src/adapters/curl/download.test.ts +55 -0
- package/src/adapters/curl/index.ts +5 -0
- package/src/adapters/memory/index.ts +131 -0
- package/src/adapters/node/files.io.ts +39 -0
- package/src/adapters/node/files.test.ts +28 -0
- package/src/adapters/node/host.io.ts +15 -0
- package/src/adapters/node/index.ts +36 -0
- package/src/adapters/node/process.io.ts +49 -0
- package/src/adapters/node/process.test.ts +46 -0
- package/src/adapters/node/workspace.io.ts +40 -0
- package/src/adapters/node/workspace.test.ts +58 -0
- package/src/adapters/pdfjs/fill.test.ts +111 -0
- package/src/adapters/pdfjs/fill.ts +141 -0
- package/src/build-engine.harness.mjs +314 -0
- package/src/build-engine.ts +219 -0
- package/src/build.harness.mjs +631 -0
- package/src/build.mutations.mjs +195 -0
- package/src/build.ts +793 -0
- package/src/cli.harness.mjs +2007 -0
- package/src/cli.mutations.mjs +448 -0
- package/src/cli.ts +1189 -0
- package/src/doctor.harness.mjs +396 -0
- package/src/doctor.mutations.mjs +175 -0
- package/src/doctor.ts +356 -0
- package/src/domain/geometry.ts +108 -0
- package/src/domain/host.ts +23 -0
- package/src/domain/page-layout.ts +32 -0
- package/src/domain/paths.ts +5 -0
- package/src/domain/result.test.ts +26 -0
- package/src/domain/result.ts +29 -0
- package/src/domain/sha256.test.ts +12 -0
- package/src/domain/sha256.ts +21 -0
- package/src/domain/text.ts +11 -0
- package/src/engine.harness.mjs +252 -0
- package/src/engine.ts +176 -0
- package/src/exit-code.test.ts +21 -0
- package/src/exit-code.ts +38 -0
- package/src/facts-file.test.ts +240 -0
- package/src/facts-file.ts +241 -0
- package/src/hooks-settings.harness.mjs +386 -0
- package/src/hooks-settings.mutations.mjs +116 -0
- package/src/hooks-settings.ts +434 -0
- package/src/init.ts +900 -0
- package/src/latex-log.harness.mjs +226 -0
- package/src/latex-log.ts +234 -0
- package/src/latex-loop.harness.mjs +449 -0
- package/src/latex-loop.ts +211 -0
- package/src/link-skills.harness.mjs +273 -0
- package/src/link-skills.mutations.mjs +136 -0
- package/src/link-skills.ts +258 -0
- package/src/new-paper.harness.mjs +216 -0
- package/src/new-paper.mutations.mjs +79 -0
- package/src/new-paper.ts +158 -0
- package/src/pdf-facts.harness.mjs +188 -0
- package/src/pdf-facts.ts +327 -0
- package/src/pdf-geometry.harness.mjs +254 -0
- package/src/pdf-geometry.ts +300 -0
- package/src/ports/download.ts +10 -0
- package/src/ports/files.ts +11 -0
- package/src/ports/measure-geometry.ts +8 -0
- package/src/ports/process.ts +46 -0
- package/src/ports/tool-installer.ts +33 -0
- package/src/ports/workspace.ts +20 -0
- package/src/rules-config.harness.mjs +114 -0
- package/src/rules-config.ts +178 -0
- package/src/structure.harness.mjs +179 -0
- package/src/structure.mutations.mjs +83 -0
- package/src/structure.ts +166 -0
- package/src/tex-requirements.harness.mjs +238 -0
- package/src/tex-requirements.ts +181 -0
- package/src/toolchain.harness.mjs +651 -0
- package/src/toolchain.ts +755 -0
- package/src/types.ts +106 -0
- package/templates/paper/PIPELINE-STATUS.md +72 -0
- package/templates/paper/paper.md +4 -0
- package/templates/paper/paper.tex +8 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# Drive vs acquit — which of our gates is allowed to say yes
|
|
2
|
+
|
|
3
|
+
**Adapted from** `skills/shared-references/acceptance-gate.md` in
|
|
4
|
+
[`wanshuiyin/Auto-claude-code-research-in-sleep`](https://github.com/wanshuiyin/Auto-claude-code-research-in-sleep)
|
|
5
|
+
(ARIS), MIT licence, read at HEAD `2a23847` on **2026-08-09**; this adaptation written 2026-08-10.
|
|
6
|
+
Their file is 324 lines about ML training loops and LaTeX sources; the taxonomy is theirs, the
|
|
7
|
+
examples, the fourth rung and the entire classification below are ours. Deep read and the decision to
|
|
8
|
+
take pieces rather than migrate — recorded in the author's private notes
|
|
9
|
+
(`<papers-root>/research/2026-08-09-aris-deep-read-and-decision.md`).
|
|
10
|
+
Their technical report is arXiv:2605.03042.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## The distinction, in one line
|
|
15
|
+
|
|
16
|
+
> **A goal or a loop can DRIVE work. It cannot ACQUIT it.**
|
|
17
|
+
|
|
18
|
+
A pass may freely _drive_: schedule the next round, re-run the failed build, spawn ten readers, decide
|
|
19
|
+
what to try next. What it may not do is _acquit_ — declare the paper good, the claim supported, the
|
|
20
|
+
section earning its place, the delta real, the draft ready to upload. Acquittal is the act of saying
|
|
21
|
+
**yes, this is fine, stop working on it**, and it is the only act in the pipeline that ends work
|
|
22
|
+
rather than directing it.
|
|
23
|
+
|
|
24
|
+
The question is not how careful the pass is or how many rounds it ran. It is **what is being judged**
|
|
25
|
+
at the moment the pass says yes.
|
|
26
|
+
|
|
27
|
+
## The two types
|
|
28
|
+
|
|
29
|
+
Classify every stop/accept gate as exactly one. If a gate looks like both, it is two gates and you
|
|
30
|
+
split it.
|
|
31
|
+
|
|
32
|
+
### Type A — execution / fact
|
|
33
|
+
|
|
34
|
+
A machine-checkable or externally-observable statement about **what happened**, carrying no judgement
|
|
35
|
+
of merit. A gate is Type A iff a non-LLM process — an exit code, a `stat`, a counter, a parser, an
|
|
36
|
+
HTTP lookup against a registry — could in principle return the same answer. Claude may self-judge
|
|
37
|
+
these. It is bookkeeping, not a verdict.
|
|
38
|
+
|
|
39
|
+
In our lane, measurement papers over repositories:
|
|
40
|
+
|
|
41
|
+
- ✅ `latexmk` returned 0 and the PDF has eight body pages
|
|
42
|
+
- ✅ `reproduce.py` recomputed every registered quantity and exited 0
|
|
43
|
+
- ✅ every `**bolded**` figure in the body has a row in `NUMBERS.md`
|
|
44
|
+
- ✅ arXiv's API has a record under this id and its author surnames match ours
|
|
45
|
+
- ✅ `check-anon.sh` found no deanonymising string
|
|
46
|
+
- ✅ the figure measures 203.13pt against a 219.09pt column
|
|
47
|
+
- ✅ the panel **was run** and left a report file
|
|
48
|
+
- ✅ the artifact bundle ships a path for every section the abstract leads with
|
|
49
|
+
|
|
50
|
+
### Type B — quality / correctness / sufficiency
|
|
51
|
+
|
|
52
|
+
A judgement of merit. Claude must never self-acquit one of these; ARIS routes them to a different
|
|
53
|
+
model family. We have no different model family (see below), so for us a Type B gate **can only
|
|
54
|
+
drive**.
|
|
55
|
+
|
|
56
|
+
- ❌ the paper is ready to submit
|
|
57
|
+
- ❌ this section earns its place
|
|
58
|
+
- ❌ the reader could follow that sentence
|
|
59
|
+
- ❌ the delta over the nearest prior work is real
|
|
60
|
+
- ❌ the draft sits at this venue's bar
|
|
61
|
+
- ❌ the idea is worth doing
|
|
62
|
+
- ❌ the arc carries the reader end to end
|
|
63
|
+
- ❌ the accept probability is 88%
|
|
64
|
+
- ❌ "no dimension scored below 3, so the writing is fine" — when _we_ assigned the scores
|
|
65
|
+
|
|
66
|
+
### The dividing question
|
|
67
|
+
|
|
68
|
+
> _Could a program with no taste answer this?_
|
|
69
|
+
> **Yes → A** (self-judge freely). **No → B** (drive only; do not record it as an acquittal).
|
|
70
|
+
|
|
71
|
+
"The PDF compiled" needs no taste. "The PDF is a good paper" is nothing but taste. "The number
|
|
72
|
+
recomputes from the committed data" needs no taste. "The number supports the sentence around it"
|
|
73
|
+
needed taste right up until we built `check-provenance.mjs`, which is the interesting move — see the
|
|
74
|
+
fourth rung.
|
|
75
|
+
|
|
76
|
+
### Compound gates: split, never average
|
|
77
|
+
|
|
78
|
+
Most natural-language stop conditions bundle an A-part and a B-part, and the A-part is the tempting
|
|
79
|
+
one to report because it is the one that comes back green.
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
STOP when "the paper is ready to submit"
|
|
83
|
+
├─ A: the build produced a PDF at or under the page limit → we check this
|
|
84
|
+
├─ A: check-anon.sh exited 0 → we check this
|
|
85
|
+
├─ A: every registered quantity recomputes and matches the text → we check this
|
|
86
|
+
└─ B: "the paper is actually good enough" → nobody outside our family judged this
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`harden-paper` is exactly this gate and it does report the vector rather than a scalar, which is
|
|
90
|
+
right. What it still does is call the whole vector `PASS` when the B-part had no external judge.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## The fourth rung: construction, which their taxonomy has no room for
|
|
95
|
+
|
|
96
|
+
ARIS's taxonomy asks **who judges**. It therefore has two answers: us, or a different family. Our own
|
|
97
|
+
ladder, from the papers tree's own `CLAUDE.md`, asks a different question — **is the bad state expressible
|
|
98
|
+
at all** — and it has four rungs:
|
|
99
|
+
|
|
100
|
+
1. **unrepresentable** — the rule can be deleted from the prose and nothing changes
|
|
101
|
+
2. **blocked** — a mechanism refuses; the prose is unnecessary
|
|
102
|
+
3. **detected** — the prose is needed to say we mean it
|
|
103
|
+
4. **advised** — the prose is prose
|
|
104
|
+
|
|
105
|
+
Type A lives on rung 3 and sometimes 2. **Rung 1 is not in their taxonomy at all**, and it is the
|
|
106
|
+
rung we are actually best at:
|
|
107
|
+
|
|
108
|
+
- `repro/paper_numbers.py` — a registered quantity is written `{{annotated.failedContradicted}}`, not
|
|
109
|
+
`22`. The build refuses to emit a PDF when the name does not resolve, when the value has drifted
|
|
110
|
+
from the data, or when the paragraph does not declare which experimental arm it is reporting. This
|
|
111
|
+
is not a gate that judges the number. **The wrong number has no representation in the source.**
|
|
112
|
+
- `permissions.deny: ["Bash"]` — the tool leaves the model's context. There is no command to match.
|
|
113
|
+
|
|
114
|
+
A rung-1 construction needs no acquittal because there is no verdict: nobody said yes, the bad state
|
|
115
|
+
simply had nowhere to live. **When a Type B gate is stuck at "drive only", the productive move here is
|
|
116
|
+
not to find a second model family we do not have — it is to ask whether the question has an A-shaped
|
|
117
|
+
or rung-1-shaped surrogate.** For measurement papers it very often does, and every time we found one
|
|
118
|
+
it caught a defect the judgement gates had passed:
|
|
119
|
+
|
|
120
|
+
| the taste question | the surrogate we built | what it caught |
|
|
121
|
+
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
122
|
+
| does this number support this sentence | `check-provenance.mjs` — arm word in the data path vs condition word in the sentence | the 2026-08-05 abstract defect, 29 hours before a deadline; five judgement gates had passed it |
|
|
123
|
+
| is this quantity really bound to its data | `repro/arm_permutation.py` — permute the arm labels, rebuild, an unchanged quantity was never bound | a whole class the artifact reviewer recomputes and passes, because the number is _correct_ |
|
|
124
|
+
| did the number survive into the delivered paper | `repro/delivered_pdf.py` — read the built PDF back | a superscript minus lost in typesetting |
|
|
125
|
+
| is this reference real | `extract-ref-facts.mjs` + rules `refs/*` — arXiv / CrossRef | nine fabricated titles carrying correct arXiv ids, and one invented award |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🔴 Our judges are one family, and this is not a nuance
|
|
130
|
+
|
|
131
|
+
Every reviewer, grader, panellist, cold reader and adversary this pipeline fields is an Anthropic
|
|
132
|
+
model. ARIS's file names our construction without having seen it:
|
|
133
|
+
|
|
134
|
+
> ❌ N Claude reviewers each scoring the paper, then taking the **majority/average as the accept
|
|
135
|
+
> verdict.** This _feels_ like a jury — independent voters! — but it is correlated same-family
|
|
136
|
+
> blindness wearing a jury costume. … **Known failure mode:** "We ran the review 5× and all 5 said
|
|
137
|
+
> accept, so it's robust." Five draws from one distribution is one opinion with error bars, not five
|
|
138
|
+
> opinions.
|
|
139
|
+
|
|
140
|
+
That is `pc-panel-review` (N lenses → chair's meta-review → calibrated probability) and the blind
|
|
141
|
+
multi-grader panel in `grade-paper-writing`, described from the outside. By ARIS's own verifier our
|
|
142
|
+
chain grades `provisional` and never `accepted` — and strictly worse than that, since their
|
|
143
|
+
`model_family()` does not know the word `fable` and would reject the artifact outright with
|
|
144
|
+
`unrecognized_model_family`.
|
|
145
|
+
|
|
146
|
+
**What cross-family review would and would not buy.** It decorrelates blind spots and raises recall.
|
|
147
|
+
It does not convert detection into prevention, and it does not touch our own measurement that 84–96%
|
|
148
|
+
of LLM checkers leak on adversarial cases. "Two differently built models fail differently" is a real
|
|
149
|
+
gain; "therefore this is now a gate" is not.
|
|
150
|
+
|
|
151
|
+
**The one acquittal in this pipeline whose adjudicator is outside our family is not a model at all**:
|
|
152
|
+
`verify-citations`' registry leg asks arXiv, CrossRef and Semantic Scholar, and they answer without
|
|
153
|
+
taste. That is the shape to copy.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## The classification: all 22 verdict-bearing gates
|
|
158
|
+
|
|
159
|
+
Every skill under `.claude/skills/` that records a verdict to the ledger — 21 with a `Record the
|
|
160
|
+
verdict` block, plus `map-prior-work`, which was in `EXPECTED_GATES` with no block at all when this
|
|
161
|
+
survey started and was wired during the same session under the heading `Step 8`. Type is
|
|
162
|
+
assigned from the **recorded verdict vocabulary**, not from what the skill does internally — a skill
|
|
163
|
+
whose work is judgement but whose recorded verdict is an exit code is Type A, and that is the design
|
|
164
|
+
we want more of.
|
|
165
|
+
|
|
166
|
+
> ⚠️ **Read the next section first if you are checking this table against the ledger.** The middle
|
|
167
|
+
> column below records what each gate's acquitting verdict _meant_ as of the survey (2026-08-10,
|
|
168
|
+
> morning). A concurrent change deleted the value it was recorded under; the classification is
|
|
169
|
+
> unaffected and the reason it is unaffected is the interesting part.
|
|
170
|
+
|
|
171
|
+
| gate | what a yes from it asserts | type | may it acquit? |
|
|
172
|
+
| -------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
173
|
+
| `render-paper` | `check-render.sh` exited 0 | **A** | ✅ yes |
|
|
174
|
+
| `draft-paper` | sections were written to disk | **A** | ✅ yes (and its own SKILL.md says a generator that can only pass is a design smell — correct, and it is still Type A) |
|
|
175
|
+
| `build-benchmark` | the artifact recomputed every headline number and exited 0 | **A** | ✅ yes |
|
|
176
|
+
| `paper-status` | a program printed zero blockers | **A** | ✅ yes |
|
|
177
|
+
| `submit-paper` | uploaded, marked ready, `check-deanon.sh` green, under the page limit | **A** | ✅ yes (its SKILL.md already calls itself a mechanical gate) |
|
|
178
|
+
| `plan-paper-timeline` | the backwards plan is on the calendar and `access` is green | **A** + B-tail | ⚠️ A-part only; "the deadline cannot be met from here" is taste |
|
|
179
|
+
| `verify-citations` | every cite resolves with correct metadata **and** the delta sentence is present | **A** (external adjudicator) + B-tail | ⚠️ the registry leg genuinely acquits; "is the delta stated" does not |
|
|
180
|
+
| `camera-ready` | de-anonymized, DOI live, limit re-checked, disclosure complete | **A** + B-tail | ⚠️ A-part only; "disclosure is complete enough" is taste |
|
|
181
|
+
| `extend-paper` | ≥30% new material, one named venue, no dual submission | **A** + B-tail | ⚠️ the three facts acquit; "genuinely new" does not |
|
|
182
|
+
| `find-venue` | a ranked shortlist with a keep/switch call | B (+ A-part) | ❌ the indexing/peer-review facts are A; the ranking is taste |
|
|
183
|
+
| `research-ideate` | go | **B** | ❌ drive only |
|
|
184
|
+
| `sweep-design-space` | at least one candidate survived the filters | **B** | ❌ drive only |
|
|
185
|
+
| `map-prior-work` | what you may still claim after the sweep | **B** | ❌ drive only |
|
|
186
|
+
| `argument-arc` | the arc carries the reader end to end | **B** | ❌ drive only |
|
|
187
|
+
| `cold-read-diff` | every changed sentence came back restated correctly | **B** | ❌ drive only — **and the cold reader is the same family as the writer** |
|
|
188
|
+
| `tighten-paper` | a cover-to-cover read produced no action | **B** | ❌ drive only |
|
|
189
|
+
| `grade-paper-writing` | the stall inventory came back empty | **B** | ❌ drive only |
|
|
190
|
+
| `analyze-sibling-paper` | the delta is real and no text has to change | **B** | ❌ drive only |
|
|
191
|
+
| `study-accepted-papers` | the draft already sits at the venue's bar | **B** | ❌ drive only (the corpus is external; the comparison is ours) |
|
|
192
|
+
| `paper-adversarial-review` | a hostile read found nothing | **B** | ❌ drive only |
|
|
193
|
+
| `pc-panel-review` | accept with no must-fix | **B** | ❌ drive only — the flagship offender |
|
|
194
|
+
| `harden-paper` | every gate green and every axis PASS/FIXED — _the only verdict that hands off to `submit-paper`_ | **A over B** | ❌ the wrapper is A, the thing wrapped is B; the handoff is an acquittal |
|
|
195
|
+
|
|
196
|
+
### The honest count
|
|
197
|
+
|
|
198
|
+
**Of 22 verdict-bearing gates: 5 may acquit outright, 4 may acquit only their A-part, and 13 may
|
|
199
|
+
only drive.** Seventeen of twenty-two therefore reach a verdict at least partly beyond what they are
|
|
200
|
+
entitled to give.
|
|
201
|
+
|
|
202
|
+
🔴 **Narrow it to the review chain — the nine gates whose job is to decide whether the paper is good
|
|
203
|
+
enough — and the number is 9 of 9. Every one of them can only drive.** They are `argument-arc`,
|
|
204
|
+
`cold-read-diff`, `tighten-paper`, `grade-paper-writing`, `analyze-sibling-paper`,
|
|
205
|
+
`study-accepted-papers`, `paper-adversarial-review`, `pc-panel-review`, `harden-paper`. Not one has a
|
|
206
|
+
judge outside the family that wrote the text. Nothing in the review chain acquits; the entire chain
|
|
207
|
+
drives, and `harden-paper`'s PASS then hands that driving to `submit-paper` as if it were an
|
|
208
|
+
acquittal.
|
|
209
|
+
|
|
210
|
+
The gates that genuinely acquit are, without exception, the ones where we replaced a judge with a
|
|
211
|
+
program: an exit code, a registry lookup, a recomputation, a re-read of the built PDF. **We are good
|
|
212
|
+
at exactly the thing the taxonomy says is allowed, and we call it a gate exactly where it is not.**
|
|
213
|
+
|
|
214
|
+
### 🟢 2026-08-10, same day: the acquitting verdict was deleted rather than annotated
|
|
215
|
+
|
|
216
|
+
While this classification was being written, a concurrent change to `ledger.mjs` removed `PASS` from
|
|
217
|
+
the verdict vocabulary outright. A check that runs and finds nothing now records
|
|
218
|
+
`ABSTAINED no-witness`, and the ledger's own note says why:
|
|
219
|
+
|
|
220
|
+
> `no-witness` IS NOT A PASS. It says: this check ran to completion and produced no finding.
|
|
221
|
+
>
|
|
222
|
+
> `PASS` — deleted: it stored "nothing was wrong" as a _value_. Record `ABSTAINED no-witness`, and
|
|
223
|
+
> let the reader derive cleanliness from the absence of findings.
|
|
224
|
+
|
|
225
|
+
**This is the fourth rung applied to the taxonomy itself, and it is a better answer than the one
|
|
226
|
+
this document was going to give.** The plan here was to _mark_ Type B verdicts provisional — a
|
|
227
|
+
warning, rung 3, detection. Deleting the value means a gate that cannot acquit has **no way to write
|
|
228
|
+
down that it did**. The bad state stopped being expressible. Every skill in the corpus was rewritten
|
|
229
|
+
the same day to the new vocabulary, so the "its recorded PASS means" column above now describes an
|
|
230
|
+
assertion none of these gates can make.
|
|
231
|
+
|
|
232
|
+
Two things it does _not_ change, and they are why the table stays:
|
|
233
|
+
|
|
234
|
+
- **The classification is about the question, not the vocabulary.** `pc-panel-review` still decides
|
|
235
|
+
whether the paper is good; deleting the word it wrote that down in makes the claim unrecordable,
|
|
236
|
+
not unmade. The 12 drive-only gates are still 12.
|
|
237
|
+
- **The A/B split is still what tells you which gates are trustworthy** — and the five that may
|
|
238
|
+
genuinely acquit are the ones whose `no-witness` can be believed, because an exit code with no
|
|
239
|
+
findings really does mean the question was asked and answered.
|
|
240
|
+
|
|
241
|
+
The remaining hole is the one this move does not reach: `harden-paper` hands off to `submit-paper`,
|
|
242
|
+
and that handoff is still an acquittal being performed by a Type B gate — now performed by the
|
|
243
|
+
absence of findings rather than by a value, which reads even more like clean.
|
|
244
|
+
|
|
245
|
+
### What the mechanical layer looks like under the same taxonomy
|
|
246
|
+
|
|
247
|
+
Everything in `.claude/skills/paper-pipeline/scripts/`, `.claude/lib/` and `<paper>/repro/` is Type A by
|
|
248
|
+
construction — that is why it is trustworthy, and it is not a coincidence but a selection effect: a
|
|
249
|
+
program is what you can write only when the question is Type A.
|
|
250
|
+
|
|
251
|
+
| unit | question | rung |
|
|
252
|
+
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
253
|
+
| `ledger.mjs` / `status.mjs` | did the gate run, against which bytes, and has it ever said no | A (3) |
|
|
254
|
+
| `run-mechanical.mjs` | run every script gate; exit on the worst FACT gate | A (3), wrapping A |
|
|
255
|
+
| `repro/report-submission.py` | body pages, overfull boxes, unresolved refs, dropped characters | A (3) |
|
|
256
|
+
| `repro/check-anon.sh`, `check-figure.sh` | deanonymising strings; does the figure fit the column | A (3) |
|
|
257
|
+
| `structure.mjs`, `prose-lint.mjs` | section weights, unjustified blocks, thresholds with published baselines | A (3) — _measuring_ a B question, which is legitimate and is not the same as answering it |
|
|
258
|
+
| `check-provenance.mjs` | untraced number; arm word in the path vs condition word in the sentence | A (3) |
|
|
259
|
+
| `population-map.mjs`, `artifact-coverage.mjs` | which set does this number count; does the bundle hold data for what the paper points at | A (3) |
|
|
260
|
+
| rules `refs/*` (facts by `extract-ref-facts.mjs`) | does the registry have this record | A (3), **external adjudicator** |
|
|
261
|
+
| `pipeline-check.mjs`, `paper-lint.mjs` | scorecard consistency, gate staleness, appendix ratio, shaved passages | A (3) |
|
|
262
|
+
| `repro/arm_permutation.py`, `repro/delivered_pdf.py` | is the quantity bound to its arm; did it survive typesetting | A (3), metamorphic |
|
|
263
|
+
| **`repro/paper_numbers.py` + `numbers.tsv`** | — | **rung 1: no PDF exists in which the number is wrong** |
|
|
264
|
+
| `paper-edit-guard.hook.ts` | writing to a paper from Bash | rung 2 — **leaky**, an interpreter reading its program from stdin still gets through (`papers/CLAUDE.md`, 2026-08-06) |
|
|
265
|
+
|
|
266
|
+
`structure.mjs` and `prose-lint.mjs` deserve their note. They put a **number with a threshold** on
|
|
267
|
+
questions that are Type B — does this section earn its place, is this sentence readable. That is not
|
|
268
|
+
cheating and it is not acquittal either: a threshold breach is a fact, and the fact drives a human or
|
|
269
|
+
a judgement pass. The failure to avoid is reading a green threshold as an acquittal, which is what
|
|
270
|
+
happened when a prose metric stood at 50.8 against a machine norm of 7.8 and printed as a neutral
|
|
271
|
+
line because **nobody had given it a threshold at all**.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## What follows from this classification
|
|
276
|
+
|
|
277
|
+
Three things are actionable today, and one is not.
|
|
278
|
+
|
|
279
|
+
1. **`single-family-jury` watches three gates; it should watch thirteen.**
|
|
280
|
+
_(2026-08-26: this check now lives in `eslint-rules/pipeline-status.mjs` as the ESLint rule
|
|
281
|
+
`pipeline/judge-recorded`, together with `unattributed-verdict`. The widening to fourteen names
|
|
282
|
+
happened 2026-08-10 and moved with it.)_
|
|
283
|
+
The `ACQUITTING` set is `pc-panel-review`, `paper-adversarial-review`, `harden-paper`. The other
|
|
284
|
+
ten drive-only gates — `find-venue`, `research-ideate`, `sweep-design-space`, `map-prior-work`,
|
|
285
|
+
`argument-arc`, `cold-read-diff`, `tighten-paper`, `grade-paper-writing`,
|
|
286
|
+
`analyze-sibling-paper`, `study-accepted-papers` — report a clean run with no judge recorded and
|
|
287
|
+
nothing objects. Widening that set is a one-line change to a set literal and it makes ten hidden
|
|
288
|
+
acquittals countable.
|
|
289
|
+
2. ~~**`map-prior-work` records nothing.**~~ **Closed the same day.** It was in `EXPECTED_GATES`
|
|
290
|
+
with no ledger call, so the gate deciding what we may still claim had never entered the ledger —
|
|
291
|
+
a Type B gate that is also invisible, the worst square on this board. It is now wired
|
|
292
|
+
(`Step 8`). Kept here rather than deleted because the _shape_ recurs: a gate can be listed as
|
|
293
|
+
expected and still have no way to speak, and nothing but `unlistedGates()`'s mirror image would
|
|
294
|
+
have said so.
|
|
295
|
+
3. **Prefer a surrogate to a second family.** Before wishing for a cross-family reviewer, ask the
|
|
296
|
+
fourth-rung question: is there an A-shaped or rung-1-shaped version of this judgement? Every time
|
|
297
|
+
we have asked, the answer produced a check that caught something the panels had passed. The list
|
|
298
|
+
is in the fourth-rung table above and it is four for four.
|
|
299
|
+
|
|
300
|
+
Not actionable: **we cannot fix the review chain by adding judges.** There is no second family
|
|
301
|
+
available in this environment, and adding more Anthropic readers is the failure mode by name. What is
|
|
302
|
+
available is honesty — record who judged, mark the verdict provisional, and keep converting taste
|
|
303
|
+
questions into programs.
|
|
304
|
+
|
|
305
|
+
## What this does NOT license
|
|
306
|
+
|
|
307
|
+
- **Not a reason to skip a Type B pass.** Drive-only is not worthless; driving is most of the work,
|
|
308
|
+
and `pc-panel-review` finds real must-fixes. It is a reason not to read its PASS as permission to
|
|
309
|
+
stop.
|
|
310
|
+
- **Not a reason to trust a Type A gate more than it deserves.** A green exit code acquits exactly
|
|
311
|
+
the question it asked. The `refs/*` rules acquit "this record exists with this metadata" and say
|
|
312
|
+
nothing about whether the citation supports the sentence it sits in.
|
|
313
|
+
- **Not a licence to call a measurement an acquittal.** A threshold breach is a fact; a threshold
|
|
314
|
+
passed is also a fact, and it is a fact about a proxy. `prose-lint` being quiet is not "the writing
|
|
315
|
+
is fine".
|
|
316
|
+
- **Not a claim that cross-family review would make a PASS mean much.** Borrowing ARIS's own honesty:
|
|
317
|
+
a cross-model PASS is a heterogeneous second opinion, not ground truth. It does not mean the work
|
|
318
|
+
is correct, novel or publishable. Same-family review does not even clear that bar.
|
|
319
|
+
|
|
320
|
+
## See also
|
|
321
|
+
|
|
322
|
+
- `review-ratchet.md` — what a caught overclaim costs, and the pass that pays it back.
|
|
323
|
+
- `eslint-rules/pipeline-status.mjs` (rule `pipeline/judge-recorded`; until 2026-08-26 in
|
|
324
|
+
`../scripts/pipeline-check.mjs`) — `single-family-jury` and `unattributed-verdict`, the mechanical
|
|
325
|
+
leg of this document.
|
|
326
|
+
- `../scripts/round-diff.mjs` — the per-round edit gate: a driving pass may only change what it
|
|
327
|
+
declared, and the whole document's growth is measured every round.
|
|
328
|
+
- the papers tree's own `CLAUDE.md` — the four-rung ladder, and the rule that a rule written in prose is
|
|
329
|
+
a construction somebody did not build.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# ACL-family venue rules — what applies to EVERY *ACL venue and workshop
|
|
2
|
+
|
|
3
|
+
**Scope.** ACL, EMNLP, NAACL, EACL, AACL **and their workshops**, because workshops inherit the
|
|
4
|
+
parent conference's author guidelines and template. Fetched from
|
|
5
|
+
`acl-org.github.io/ACLPUB/formatting.html` (2026-08-03) and the ACL author checklist. This file
|
|
6
|
+
exists so the same page is not re-fetched for every paper; **re-verify once per submission cycle**,
|
|
7
|
+
because ACL does change these between years.
|
|
8
|
+
|
|
9
|
+
Not applicable to ACM (CCS/AISec, sigconf), IEEE (S&P, Xplore) or LIPIcs venues — those have their
|
|
10
|
+
own rules and their own cards.
|
|
11
|
+
|
|
12
|
+
## The page-limit map — what counts and what does not
|
|
13
|
+
|
|
14
|
+
| part of the PDF | counts toward the limit? |
|
|
15
|
+
| ------------------------------------------- | ------------------------ |
|
|
16
|
+
| body, §1 to the conclusion | **yes** |
|
|
17
|
+
| **Limitations** | **no** |
|
|
18
|
+
| **Ethical considerations** / Broader impact | **no** |
|
|
19
|
+
| references | no |
|
|
20
|
+
| **appendices** | **no** |
|
|
21
|
+
|
|
22
|
+
Long/short page counts are set by the _venue_, not by ACL — see the venue card. Camera-ready
|
|
23
|
+
usually grants **one extra page**; that is where a figure cut for space goes, not into the
|
|
24
|
+
submission.
|
|
25
|
+
|
|
26
|
+
## 🔴 The appendix rule, and the trap inside it
|
|
27
|
+
|
|
28
|
+
Verbatim:
|
|
29
|
+
|
|
30
|
+
> «Appendices are material that can be read, and include lemmas, formulas, proofs, and tables that
|
|
31
|
+
> are **not critical to the reading and understanding of the paper**.»
|
|
32
|
+
|
|
33
|
+
> «The paper may refer to and cite the supplementary material and the supplementary material will be
|
|
34
|
+
> available to the reviewers, **they will not be asked to review the supplementary material**.»
|
|
35
|
+
|
|
36
|
+
**The reviewer is not obliged to open the appendix.** Everything else follows from that:
|
|
37
|
+
|
|
38
|
+
- **Body** — anything a claim stands on. Remove it and the claim dangles ⇒ it belongs in the body.
|
|
39
|
+
- **Appendix** — the proof a sceptic would go check: per-row tables, protocols, full enumerations,
|
|
40
|
+
robustness checks. Answers _"prove it"_, never _"what do you mean"_.
|
|
41
|
+
- **Artifact** (external host) — runnable code and raw data.
|
|
42
|
+
|
|
43
|
+
🔴 **The trap, hit for real on `compile-rules-2026` 2026-08-03.** Moving something to an appendix
|
|
44
|
+
does **not** discharge the obligation attached to a claim. A plan to move §5's _caveat_ to the
|
|
45
|
+
appendix while the flattering number it qualifies stayed in the body would have left the body
|
|
46
|
+
asserting a figure whose walk-back a reviewer is not required to read — in a paper arguing that a
|
|
47
|
+
claim must resolve to its backing. A refutation pass killed it.
|
|
48
|
+
|
|
49
|
+
**Test before moving anything out:** read the body straight through with the appendices closed.
|
|
50
|
+
Any _"wait, where does that come from?"_ means the cut was wrong.
|
|
51
|
+
|
|
52
|
+
Appendices must keep the **2-column format**, except math-heavy sections.
|
|
53
|
+
|
|
54
|
+
## Limitations and Ethics — free space with a hard restriction
|
|
55
|
+
|
|
56
|
+
- **Limitations is mandatory** at ACL venues: _"ACL currently requires all submissions to have a
|
|
57
|
+
section titled 'Limitations'"_. Unnumbered, after the conclusion, before references, no page break.
|
|
58
|
+
- **Ethical considerations is optional** and encouraged; same placement.
|
|
59
|
+
- 🔴 Both: _"It may not contain any additional experiments, figures or analysis."_
|
|
60
|
+
|
|
61
|
+
So they are free space for **honest qualification only**. Pushing an analysis there to win room in
|
|
62
|
+
the body violates the rule and reads as evasion. (Watch this one: it is tempting precisely when the
|
|
63
|
+
body is at the limit, which is exactly when the temptation should be refused.)
|
|
64
|
+
|
|
65
|
+
## Anonymity
|
|
66
|
+
|
|
67
|
+
Double-blind is the norm. Author names and affiliations omitted. **Preprints are generally allowed**
|
|
68
|
+
— _"Preprints (e.g., on arXiv) may be posted publicly at any time and do not violate the anonymity
|
|
69
|
+
policy, provided the submitted PDF does not link to de-anonymized author information."_ So a public
|
|
70
|
+
blog or arXiv version does **not** have to be hidden; only the PDF has to stay clean. Confirm per
|
|
71
|
+
venue, because the anonymity period differs.
|
|
72
|
+
|
|
73
|
+
## OpenReview mechanics (the usual ACL-family portal)
|
|
74
|
+
|
|
75
|
+
- 🔴 **An active profile is required to submit.** Verbatim: _"Submitting authors require an active
|
|
76
|
+
profile — a profile that's still pending moderation doesn't meet that requirement."_
|
|
77
|
+
- **Moderation can take up to two weeks.** Cases are reviewed daily. The documented accelerator is a
|
|
78
|
+
confirmed **institutional or company email** on the profile; a DBLP record also helps. An
|
|
79
|
+
independent author with neither has no expedite route and must go through support.
|
|
80
|
+
- **Plan the profile before the paper.** This is the one blocker no amount of writing can clear, and
|
|
81
|
+
it is invisible until you try to submit. On `compile-rules-2026` it became the sole critical-path
|
|
82
|
+
item with three days left.
|
|
83
|
+
- Check whether the venue's submission form has a **supplementary-material field** by fetching the
|
|
84
|
+
invitation schema from the API, not by reading the CFP page — the form is the source of truth.
|
|
85
|
+
If there is no field, the artifact must be hosted externally and anonymously with the URL in the
|
|
86
|
+
paper.
|
|
87
|
+
|
|
88
|
+
## 🔴 GenAI / LLM disclosure — there is NO gate on a direct workshop submission, and no required placement
|
|
89
|
+
|
|
90
|
+
**The policy text, verbatim** (ACL Rolling Review, cross-checked twice):
|
|
91
|
+
|
|
92
|
+
> _Their use for writing or coding, as well as its scope, **must be disclosed in the Responsible NLP
|
|
93
|
+
> Checklist**. Details **should be included in the Acknowledgements section**._
|
|
94
|
+
|
|
95
|
+
**Both destinations are ARR-process and/or camera-ready, and neither is reachable at a direct
|
|
96
|
+
workshop submission:**
|
|
97
|
+
|
|
98
|
+
- the **Responsible NLP Checklist** is an ARR form field. A direct workshop submission on OpenReview
|
|
99
|
+
has whatever fields the invitation declares and nothing else. Verify by fetching
|
|
100
|
+
`api2.openreview.net/invitations?id=<VENUE-PATH>/-/Submission` and reading the field list. For
|
|
101
|
+
REALM @ EMNLP 2026 the complete list was `title, authors, authorids, keywords, TLDR, abstract,
|
|
102
|
+
pdf, archival, cross_submission_to, serve_as_reviewer, venue, venueid` — **no checklist field**.
|
|
103
|
+
- **Acknowledgements cannot exist in an anonymous review version** — it is the canonical
|
|
104
|
+
deanonymisation vector. So the policy's stated home for the details is structurally unavailable
|
|
105
|
+
until camera-ready.
|
|
106
|
+
|
|
107
|
+
**Therefore:** nothing desk-rejects for the absence of an LLM-disclosure section, and no rule says
|
|
108
|
+
the disclosure must appear early, or in the body, or on page 1. Placement is an _authorial_ choice.
|
|
109
|
+
|
|
110
|
+
**What to actually do**, in order:
|
|
111
|
+
|
|
112
|
+
1. **Disclose it — but where disclosures live.** Limitations and Ethical considerations are both
|
|
113
|
+
outside the page limit, so the disclosure is free there and costs body words anywhere else.
|
|
114
|
+
2. **Do not lead a body section with it.** Naming the model as the agent of a measurement, in the
|
|
115
|
+
reader's first contact with that measurement, spends credibility for no compliance gain. Keep the
|
|
116
|
+
_method_ inline where it makes the numbers credible — a written codebook, a blind second pass,
|
|
117
|
+
released labels — and point at Limitations for who executed it.
|
|
118
|
+
3. **Make the Limitations version unmissable and complete**, including which sections it covers, so
|
|
119
|
+
a reader who reaches it cannot feel the earlier text concealed anything. A one-line back-reference
|
|
120
|
+
in the body ("Limitations for who did the labelling") is what makes it a pointer rather than a
|
|
121
|
+
burial.
|
|
122
|
+
4. **Never replace it with a false claim of human labour.** _by hand · a second person · two
|
|
123
|
+
annotators · manually_ — if a model did the work, those words are fabrications about method, and
|
|
124
|
+
they are the failure this rule was written from.
|
|
125
|
+
|
|
126
|
+
**Enforcement, if the paper has a numbers gate:** put the true method words in the guard's `requires`
|
|
127
|
+
column and the false ones in `forbids`. On `compile-rules-2026` the guard did the opposite for weeks
|
|
128
|
+
— it _required_ the word "hand" near the census figures — so the gate was mechanically holding a
|
|
129
|
+
false methodology claim in place, in a paper about rules that claim enforcement they do not have.
|
|
130
|
+
|
|
131
|
+
**Provenance.** Written 2026-08-06, one hour before the REALM deadline, after the assistant told the
|
|
132
|
+
author twice that "ACL mandates it" and then found the verified answer sitting in that paper's own
|
|
133
|
+
`SUBMIT-CHECKLIST.md`. The author's instinct — _"maybe the LLM note shouldn't be right on first page
|
|
134
|
+
given we have a disclaimer somewhere below"_ — was correct, and the assistant's confident memory was
|
|
135
|
+
not. Re-verify the form schema each cycle; ARR and workshop forms diverge, and they change year to
|
|
136
|
+
year.
|
|
137
|
+
|
|
138
|
+
## What is venue-specific and therefore NOT here
|
|
139
|
+
|
|
140
|
+
Page counts per track · archival vs non-archival · ARR commitment route and its deadline · the
|
|
141
|
+
submission portal URL and its form fields · anonymity period · attendance requirements · the review
|
|
142
|
+
criteria. All of that lives in `submit-paper/references/venues/<venue>.md`.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Anonymization & double-blind hygiene (single source of truth)
|
|
2
|
+
|
|
3
|
+
Double-blind hides **you** (the author), not the _subject_ of study. Identifying the artifact/tool you
|
|
4
|
+
evaluate is fine and often necessary; leaking the author is a desk-reject. Security venues add a second
|
|
5
|
+
duty: don't **punch down** on named third parties (anonymize the subjects too). Cite this file; don't
|
|
6
|
+
restate it. `submit-paper` and `camera-ready` point here; `pc-panel-review`'s artifact-runner greps by it.
|
|
7
|
+
|
|
8
|
+
## The deny-list (grep before every submission — PDF text AND every shipped file)
|
|
9
|
+
|
|
10
|
+
Author/identity strings to find and remove from anything a reviewer sees:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
# Your OWN list of identifiers — names, surnames, handles, repo names, tool names, email.
|
|
14
|
+
# It is CONSUMER DATA, so it lives in your repository, not in this package:
|
|
15
|
+
# .claude/skills/submit-paper/deanon-denylist.txt (one extended regex per line)
|
|
16
|
+
bash .claude/skills/submit-paper/check-deanon.sh <paper-dir> # PDF text + artifact/ + inside *.zip
|
|
17
|
+
grep -rIiE "$(grep -vE '^\s*(#|$)' .claude/skills/submit-paper/deanon-denylist.txt | paste -sd'|')" <targets>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Plus a **non-English script** in the source (an author-language fingerprint — Cyrillic in the example
|
|
21
|
+
below; use whatever script your own notes are written in) — but detect it UTF-8-aware, because
|
|
22
|
+
a naive `[А-Яа-я]` byte-class false-positives on em-dashes/smart-quotes in a C locale:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
rg -l '\p{Cyrillic}' <targets> # or: grep -rIlP '\p{Cyrillic}'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Both must return empty. Also scan the compiled PDF's text
|
|
29
|
+
(`python3 -c 'import fitz,sys; print("".join(p.get_text() for p in fitz.open(sys.argv[1])))' paper.pdf | grep -i …`,
|
|
30
|
+
with the same pymupdf the render step installs) and any
|
|
31
|
+
`.pyc`/`__pycache__` (they can embed your absolute repo path) — delete caches before zipping.
|
|
32
|
+
|
|
33
|
+
## What is and isn't a leak
|
|
34
|
+
|
|
35
|
+
- **Not a leak (keep):** naming/pinpointing the _studied_ artifact — a tool's exact star count, the
|
|
36
|
+
command you evaluate, the model tested. That's the object of study; it makes the claim meaningful.
|
|
37
|
+
- **Leak (remove):** your name, affiliation, repo/tool name, email, GitHub handle, absolute filesystem
|
|
38
|
+
paths, non-English source comments/docs, a public "twin" (blog/preprint) under your name with the same
|
|
39
|
+
distinctive numbers (a reviewer can Google it — don't cite it; check the venue's preprint policy).
|
|
40
|
+
- **Ethics (security venues especially):** if you evaluate real third-party code by named hobbyists,
|
|
41
|
+
**anonymize the subjects too** in the release (stable IDs, factual not pejorative tone) and keep full
|
|
42
|
+
provenance author-side. Disclose findings to the parties before any de-anonymized public release.
|
|
43
|
+
(AISec's top reject-vector was a released artifact that named 46 maintainers with handles + pejorative
|
|
44
|
+
notes — fixed by G01–G46 IDs + neutral tone + a release gate.)
|
|
45
|
+
|
|
46
|
+
## Submission hygiene
|
|
47
|
+
|
|
48
|
+
- Submit **PDF-only**; never zip the paper's source directory — sibling files (drafts, internal READMEs,
|
|
49
|
+
notes) leak identity. Only a scrubbed artifact bundle is safe.
|
|
50
|
+
- LaTeX: use the venue's anonymous class option (ACM `[sigconf,review,anonymous]`); author = "Anonymous
|
|
51
|
+
Author(s)"; strip identifying `%` comments from the `.tex` before any source upload.
|
|
52
|
+
- Host the artifact anonymized (OSF private project + anonymized view-only link, or 4open on a _private_
|
|
53
|
+
repo). **Verify in an incognito window**: files visible, contributors = "Anonymous," your name nowhere.
|
|
54
|
+
- A **release-gate script** that greps this deny-list, re-runs the harnesses, and zips only the artifact
|
|
55
|
+
dir is the belt-and-suspenders pattern (`<papers-root>/<paper>/check-release.sh` in the first
|
|
56
|
+
consumer of this pipeline).
|
|
57
|
+
|
|
58
|
+
## Reversing it (camera-ready)
|
|
59
|
+
|
|
60
|
+
On acceptance, `camera-ready` reverses all of the above: drop `review,anonymous`, restore real
|
|
61
|
+
author/affiliation/ORCID, un-blind self-citations and "our tool" naming, swap the anonymized link for a
|
|
62
|
+
public repo + archival DOI, and complete + log responsible disclosure.
|
|
63
|
+
|
|
64
|
+
## Provenance
|
|
65
|
+
|
|
66
|
+
AgenticDev: rounded an exact star count, deleted a source comment naming the author's own tool,
|
|
67
|
+
verified PDF+zip clean.
|
|
68
|
+
AISec: full RU→EN + handle-stripping of the provenance, an evaluator that stress-tested the release gate.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Reproduction-artifact checklist (single source of truth)
|
|
2
|
+
|
|
3
|
+
The single biggest accept-probability lever for an empirical/measurement paper: a reviewer who can run
|
|
4
|
+
it. `build-benchmark` produces it; `pc-panel-review`'s artifact-runner executes it; `submit-paper`
|
|
5
|
+
hosts it. Cite this file instead of restating it. Grounded in the two real artifacts this session:
|
|
6
|
+
the 140-run `reproduce.py` (AgenticDev) and the 46-guard `evaluate.py`/`mutate.py`/`reproduce.mjs`/
|
|
7
|
+
`ablation.mjs` (AISec).
|
|
8
|
+
|
|
9
|
+
## Non-negotiables
|
|
10
|
+
|
|
11
|
+
- **Self-checking.** A script that **recomputes every headline number from the raw data and exits
|
|
12
|
+
non-zero if any cell drifts** — PASS/FAIL per number, not "eyeball this table." A reviewer sees a
|
|
13
|
+
green run or a red one.
|
|
14
|
+
- **Recompute, never echo.** Derive each number from the base data fields. Do NOT print a stored/
|
|
15
|
+
precomputed summary field and call it "reproduced" — a sharp reviewer greps for that and calls it
|
|
16
|
+
circular. (AISec review caught exactly this; AgenticDev's first draft echoed 4 cells — both fixed by
|
|
17
|
+
deriving from base fields.)
|
|
18
|
+
- **Stdlib-only, no network, deterministic.** No NumPy/SciPy if avoidable (implement Welch t / the
|
|
19
|
+
Student-t CDF / paired-t CI from scratch); no API keys; no model calls at run time; identical output
|
|
20
|
+
every run. Runs in seconds on a clean machine.
|
|
21
|
+
- **Safe to run.** Never execute untrusted or destructive commands to measure them — **parse/transcribe**
|
|
22
|
+
(AISec's "parse, don't execute": statically apply each guard's predicate; `rm -rf /` is only ever a
|
|
23
|
+
string). The artifact must be safe to `unzip && run` on any laptop.
|
|
24
|
+
- **Honest scope.** If you ship per-arm aggregates, don't claim "raw N runs"; if the shipped guards are a
|
|
25
|
+
transcription of a compiled tool, say so. Name the badge you claim (Available / Functional / Results-
|
|
26
|
+
Reproduced, and scope Reproduced to the analysis layer if generation needs keys/models).
|
|
27
|
+
|
|
28
|
+
## Contents (mirror this file map)
|
|
29
|
+
|
|
30
|
+
- `reproduce.py` / the harness scripts — self-check, print `RESULT: PASS`, exit non-zero on drift.
|
|
31
|
+
- `data/…` — the raw measurements the numbers derive from.
|
|
32
|
+
- `README.md` — a **"what reproduces which paper number"** table (paper location → the line that prints
|
|
33
|
+
it), a scope/method note, and the run command.
|
|
34
|
+
- `LICENSE` — MIT (or similar); the "Available" badge often requires one. Anonymized author line for review.
|
|
35
|
+
- No `__pycache__` / `node_modules` / generated `*results*.json` in the shipped zip (`.pyc` can embed
|
|
36
|
+
your absolute repo path — a de-anon leak). Strip distinctive fingerprints (an exact star count, a
|
|
37
|
+
total-spend figure).
|
|
38
|
+
|
|
39
|
+
## Before shipping
|
|
40
|
+
|
|
41
|
+
- Run it once on a clean checkout → `PASS`, exit 0.
|
|
42
|
+
- De-anon scan the whole tree (see `anonymization.md`).
|
|
43
|
+
- Zip **only** the artifact dir (never sibling internal dirs). A release-gate script that greps for
|
|
44
|
+
identity + Cyrillic, re-runs the harnesses, and zips only the artifact is the pattern
|
|
45
|
+
(`<papers-root>/<paper>/check-release.sh` is a working example in the first consumer).
|
|
46
|
+
- Host it anonymized for double-blind review — see `submit-paper` §hosting and `osf-artifact-upload`.
|
|
47
|
+
|
|
48
|
+
## Provenance
|
|
49
|
+
|
|
50
|
+
AgenticDev `reproduce.py`: recomputes Table 1, Bonferroni survivors, pooled bill + paired-t CI, the
|
|
51
|
+
0.6%/20%/13% structural bound — all `PASS`, hand-verified by a reviewer to 7 digits. AISec: four
|
|
52
|
+
self-asserting harnesses; a reviewer re-ran them and stress-tested the release gate (planted a leak → the
|
|
53
|
+
gate caught it).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🔴 The check that was missing until 2026-08-06: is the data IN the bundle?
|
|
58
|
+
|
|
59
|
+
Every gate on an artifact inspects **what is present**. The anonymity gate asks whether anything
|
|
60
|
+
leaks. The numbers gate asks whether a printed figure matches its data file. An artifact reviewer
|
|
61
|
+
asks whether the code runs. **A missing directory passes all three** — nothing leaks, nothing
|
|
62
|
+
mismatches, and everything present still runs.
|
|
63
|
+
|
|
64
|
+
Observed: a paper's released bundle contained **no data at all** for the section its abstract leads
|
|
65
|
+
with. Six `harden-paper` passes and five review panels had not noticed. It surfaced because the
|
|
66
|
+
author asked a plain question — _"did we ever actually run the artifact?"_
|
|
67
|
+
|
|
68
|
+
**Run `paper-pipeline/scripts/artifact-coverage.mjs <paper-dir>` — wired into pre-commit and CI.**
|
|
69
|
+
Two checks, deliberately dumb:
|
|
70
|
+
|
|
71
|
+
1. every body section that prints a figure is named in the bundle's index (`NUMBERS.md`);
|
|
72
|
+
2. every path the index names exists in the bundle.
|
|
73
|
+
|
|
74
|
+
Its first run found **three** gaps: one real absence, and two experiments whose data shipped but
|
|
75
|
+
which the index never named — so a reviewer following the index would have concluded they were
|
|
76
|
+
unreleased. Absence and unfindability fail the same way for a reader.
|
|
77
|
+
|
|
78
|
+
## Running `aclpubcheck` locally
|
|
79
|
+
|
|
80
|
+
The official ACL format checker. `pip install aclpubcheck` fails in some sandboxes (`bibtexparser`
|
|
81
|
+
will not build a wheel). Working recipe:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone --depth 1 https://github.com/acl-org/aclpubcheck.git
|
|
85
|
+
pip install pdfplumber PyPDF2 termcolor numpy pylatexenc pybtex unidecode
|
|
86
|
+
mkdir -p stub/rebiber # rebiber is used ONLY by the optional author-name check
|
|
87
|
+
printf 'def construct_bib_db(*a, **k): return {}\n' > stub/rebiber/__init__.py
|
|
88
|
+
PYTHONPATH=stub python3 -m aclpubcheck --paper_type long <pdf>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
🔴 **Run it on a build WITHOUT line numbers.** Against a `[review]`-mode PDF it reports one margin
|
|
92
|
+
error per line number — about 2,000 of them, all spurious, because it is written for camera-ready
|
|
93
|
+
files. A checker whose output is 100% false positives gets muted the same day.
|