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,453 @@
|
|
|
1
|
+
// Compiled to SKILL.md by `vigiles compile`. Edit THIS file, never the markdown.
|
|
2
|
+
//
|
|
3
|
+
// Adopted 2026-08-17 (batch 3). Body carried over VERBATIM so the compiled diff shows
|
|
4
|
+
// only what the compiler adds. No `disallowedTools` fence yet — the field landed on
|
|
5
|
+
// `SkillSpec` in vigiles branch `claude/skill-disallowed-tools` and is not in a release
|
|
6
|
+
// this repo installs, so writing one here would not compile.
|
|
7
|
+
import { experimental_skill } from "vigiles/spec";
|
|
8
|
+
|
|
9
|
+
export default experimental_skill({
|
|
10
|
+
name: "grade-paper-writing",
|
|
11
|
+
description:
|
|
12
|
+
'Use when asking "does this paper read well?" / "is the writing any good?" / "it reads like a wall of text and jargon" / "grade the writing" on a draft. Grades WRITING CRAFT only — nine dimensions 1–5 (Title, Abstract, Intro architecture, Structure, Prose clarity, Jargon discipline, Landing-the-point, Figure economy, Honesty-without-hedge-stacking) against how the best-written papers read (Peyton Jones, McEnerney, Gopen & Swan; exemplars Trusting Trust, Carlini, Greshake), naming the offending sentence and the fix for each. Runs the PERSONA cold-read stall pass (a committed non-academic persona subagent, per-section) whose stall inventory — not the rubric number — is the readability gate other skills consume (pc-panel-review, paper-adversarial-review, harden-paper). Defaults to a blind multi-grader panel; after fixes, mandates the claims-preservation diff (row `claims`). NOT a content/defect review (paper-adversarial-review / pc-panel-review), NOT a structural cut plan (tighten-paper — run that first on a bloated draft), NOT venue-bar content strength (study-accepted-papers). Compose with harden-paper (which calls it), draft-paper (generative counterpart), render-paper.',
|
|
13
|
+
tools: [
|
|
14
|
+
"Read",
|
|
15
|
+
"Write",
|
|
16
|
+
"Edit",
|
|
17
|
+
"Grep",
|
|
18
|
+
"Glob",
|
|
19
|
+
"Agent",
|
|
20
|
+
"Skill",
|
|
21
|
+
"Bash(node .claude/skills/paper-pipeline/scripts/announce.mjs:*)",
|
|
22
|
+
"Bash(node .claude/skills/paper-pipeline/scripts/ledger.mjs:*)",
|
|
23
|
+
],
|
|
24
|
+
body: `
|
|
25
|
+
# grade-paper-writing — grade how the paper READS, then fix it sentence by sentence
|
|
26
|
+
|
|
27
|
+
## Run me
|
|
28
|
+
|
|
29
|
+
🔴 FIRST, before any other step:
|
|
30
|
+
|
|
31
|
+
\`\`\`
|
|
32
|
+
node .claude/skills/paper-pipeline/scripts/announce.mjs grade-paper-writing <paper-dir>
|
|
33
|
+
\`\`\`
|
|
34
|
+
|
|
35
|
+
An advisory pass cannot be observed failing — silence is both its error state and its normal
|
|
36
|
+
state — so starting is an event, and events get written down.
|
|
37
|
+
|
|
38
|
+
The review skills hunt scientific defects; \`study-accepted-papers\` checks whether the contribution clears
|
|
39
|
+
the venue's bar. Neither tells you the paper is a slog to read. This skill does exactly that: it grades
|
|
40
|
+
the **writing craft** against how the best-written papers actually read, and turns each low score into a
|
|
41
|
+
concrete, sentence-level fix. Its target failure mode is the common one — *"a wall of text and jargon that
|
|
42
|
+
doesn't drive home how crazy the situation is"* — which is a writing problem, not a science problem, and
|
|
43
|
+
which the defect-hunting skills will pass right over.
|
|
44
|
+
|
|
45
|
+
Grounding (do NOT re-derive — read it): \`../paper-pipeline/references/writing-craft.md\` holds the craft
|
|
46
|
+
rules, the exemplar lessons, and the full nine-dimension rubric with 1/5 anchors. This skill applies it.
|
|
47
|
+
|
|
48
|
+
## The frame to hold while grading (from the reference)
|
|
49
|
+
The papers that make a human care share three moves: **(1) open on a problem/assumption the reader already
|
|
50
|
+
holds; (2) break it with the single most visceral concrete instance, not an aggregate stat; (3) land one
|
|
51
|
+
repeatable sentence.** Grade the draft against that trio, plus McEnerney's test — *does this create value
|
|
52
|
+
for the reader, or just record the author's thinking?* — and Gopen/Swan's sentence mechanics (payload in
|
|
53
|
+
the stress position, subject next to verb, one idea per sentence).
|
|
54
|
+
|
|
55
|
+
## Execution model — run the graders as subagents (context forks), by default
|
|
56
|
+
The blind panel (≥3 graders) and the cold-read stall pass **run in fresh subagents, not inline** — for two
|
|
57
|
+
reasons: (a) grading dumps the whole paper + long stall inventories into context, which gunks up the main
|
|
58
|
+
thread (context rot); (b) fresh context is the *point* of blind grading — a grader that saw the drafting or
|
|
59
|
+
the "it improved from last draft" history anchors optimistic. **Spawn the graders in parallel** (one message,
|
|
60
|
+
multiple Agent calls), with an adversarial model (Fable) for at least one seat. The main thread only
|
|
61
|
+
**synthesizes the distilled scorecards** — it does not read the paper line-by-line for the grade itself.
|
|
62
|
+
(This is the writing-axis instance of the session working rule: delegate heavy/ context-heavy work to
|
|
63
|
+
subagents, keep the main thread for synthesis.)
|
|
64
|
+
|
|
65
|
+
## The stall pass — specification
|
|
66
|
+
|
|
67
|
+
This is the pass the author cannot run on himself, and it was the weakest thing in this skill: its
|
|
68
|
+
spec was a pointer to a file that does not exist. On 2026-08-05 it had run six times on one paper,
|
|
69
|
+
and the author then found eleven unreadable passages by eye in twenty minutes. Everything below is
|
|
70
|
+
derived from that gap.
|
|
71
|
+
|
|
72
|
+
### 🔴 Read the BUILT PDF, not the source
|
|
73
|
+
|
|
74
|
+
**The stall pass reads the typeset pages.** The source is for locating the fix afterwards, never for
|
|
75
|
+
judging the read. This was previously written as "read the \`.tex\`/\`.md\`, **or** run \`render-paper\`",
|
|
76
|
+
and that *or* is why the pass kept missing what the author saw immediately: he reads the PDF.
|
|
77
|
+
|
|
78
|
+
Things that exist only in the render, every one of which produces a real stall:
|
|
79
|
+
|
|
80
|
+
- a paragraph broken across a column or a page, so its second half arrives with no antecedent;
|
|
81
|
+
- a table or figure floated away from the sentence that introduces it — the caption is now the
|
|
82
|
+
reader's only context, and captions are written assuming the body;
|
|
83
|
+
- a wall of text, which is a **visual** property: nine lines of unbroken prose in a narrow column
|
|
84
|
+
reads as impassable at a width where six does not;
|
|
85
|
+
- a heading orphaned at the foot of a column;
|
|
86
|
+
- how much of page 1 is numbers, which is what a reviewer's first impression is actually made of;
|
|
87
|
+
- line numbers and two-column measure, which change where the eye stops.
|
|
88
|
+
|
|
89
|
+
\`repro/build-submission.sh\` produces the PDF; \`render-paper\` turns pages into images. Judge from
|
|
90
|
+
those. If only the source is available, say so in the report — a stall inventory taken from source
|
|
91
|
+
is a weaker artifact and must not be presented as the same thing.
|
|
92
|
+
|
|
93
|
+
### What the reader is given, and what is withheld
|
|
94
|
+
|
|
95
|
+
**Given:** the typeset text. **Withheld:** the title's meaning, the abstract as framing, the venue,
|
|
96
|
+
the research area, what the paper is trying to show, and every previous stall inventory.
|
|
97
|
+
|
|
98
|
+
🔴 **Withholding is the mechanism, not politeness.** A grader handed the paper *plus* the framing
|
|
99
|
+
reconstructs the idea from the surroundings and then reports that the sentence is clear. It cannot
|
|
100
|
+
un-know. That is precisely how six passes in a row missed *"the state to remove is not the rule but
|
|
101
|
+
its claim about itself"* — an expert reader supplies the missing idea for free and never notices
|
|
102
|
+
they supplied it.
|
|
103
|
+
|
|
104
|
+
Give the passage **as text in the prompt**, not as a file path. A path invites reading the
|
|
105
|
+
neighbours, and reading the neighbours is how this pass fails silently.
|
|
106
|
+
|
|
107
|
+
### The one question, per sentence
|
|
108
|
+
|
|
109
|
+
> **What does this sentence claim? Restate it in your own words.**
|
|
110
|
+
|
|
111
|
+
Not "did you stumble" — stumbling is a feeling, and a competent model does not feel it. Restatement
|
|
112
|
+
is a task with a pass/fail. If the reader cannot restate without guessing, that is \`CANNOT PARSE\`
|
|
113
|
+
and it is the finding.
|
|
114
|
+
|
|
115
|
+
### Stall classes — the taxonomy the pass was missing
|
|
116
|
+
|
|
117
|
+
The old pass logged only classes 1–3 and rated papers readable that were not. Classes 4–6 are where
|
|
118
|
+
every 2026-08-05 defect lived.
|
|
119
|
+
|
|
120
|
+
| # | class | test | real example |
|
|
121
|
+
|---|---|---|---|
|
|
122
|
+
| 1 | undefined term | a coined word used before any sentence says what it refers to | \`admission\` before the mechanism is described |
|
|
123
|
+
| 2 | orphan number | a figure with no denominator or no named population | "over 90 runs … none of 48 … 12 of 12" — three populations, no map |
|
|
124
|
+
| 3 | unreadable exhibit | a table cell or caption that needs the body to decode | — |
|
|
125
|
+
| 4 | 🔴 **means nothing** | every word is known, the sentence parses grammatically, and the reader still cannot say what it claims | *"the state to remove is not the rule but its claim about itself"* · *"constructions nobody built"* |
|
|
126
|
+
| 5 | 🔴 **sounds clever, carries nothing** | reads smoothly, feels like a payoff, and its content is a restatement or is borrowed from a section the reader has not read | *"nine deletions against four fixes is §5.1's cheap way out, winning again"* |
|
|
127
|
+
| 6 | 🔴 **vague heading** | a heading naming no concrete object — no linter, no configuration, no agent, no file | *"Three answers, all of them after the fact"* · *"The configuration nobody resolves"* |
|
|
128
|
+
|
|
129
|
+
Class 5 is the one a knowing reader always waves through, because it reads *well*. Ask for it by
|
|
130
|
+
name — "which sentences sound clever but say less than they appear to?" — or it will not be reported.
|
|
131
|
+
|
|
132
|
+
### Report shape
|
|
133
|
+
|
|
134
|
+
Per stall: **location · quoted trigger · class · the reader's actual question · a one-line fix.**
|
|
135
|
+
Then the **stall inventory + density per page**, which is the artifact other skills consume — not
|
|
136
|
+
the rubric number. Then, separately, the sentences the reader could not restate at all: that list is
|
|
137
|
+
the pass's headline, above any score.
|
|
138
|
+
|
|
139
|
+
### The fix rule
|
|
140
|
+
|
|
141
|
+
🔴 **A fix that removes the flagged wording and keeps the compression is not a fix.** Proven twice in
|
|
142
|
+
one hour on 2026-08-05: *"not through any defect in how we write it, but because that is what English
|
|
143
|
+
is"* → *"that is what English is for"* (tic gone, meaning inverted into nonsense); *"the agent turns
|
|
144
|
+
out not to be the weak link"* → *"The agent obeys"* (three words, every threshold green, the wrong
|
|
145
|
+
finding). **Rewrite the whole thought in plain words.** The construction is usually a symptom of a
|
|
146
|
+
compressed idea, and decompressing it removes the construction as a side effect. Then re-read the
|
|
147
|
+
replacement cold — the author is least able to judge his own repair exactly when he feels most sure.
|
|
148
|
+
|
|
149
|
+
### Scope: whole paper here, diff continuously
|
|
150
|
+
|
|
151
|
+
This pass covers the whole paper and is expensive, so it runs at gate time. The per-edit counterpart
|
|
152
|
+
is the \`cold-read-diff\` skill, which asks the same question of just-changed paragraphs and is cheap
|
|
153
|
+
enough to run every time. Running only this one leaves every sentence written after it unread, which
|
|
154
|
+
is what happened.
|
|
155
|
+
|
|
156
|
+
## How to run it
|
|
157
|
+
|
|
158
|
+
1. **Read the actual draft** (the \`.tex\`/\`.md\`, or run \`render-paper\` to read the built pages as a reader
|
|
159
|
+
would). Grade the writing as written — never from a summary.
|
|
160
|
+
2. **Run the cold-read stall pass FIRST — the full specification is below, under "The stall pass".**
|
|
161
|
+
It was previously a pointer to a reference section that did not exist, which is why the pass drifted
|
|
162
|
+
into "log where I stumbled" and stopped catching the class it exists for.
|
|
163
|
+
2. **Score all nine dimensions 1–5** using the anchors in the reference, on the **absolute scale** defined
|
|
164
|
+
there (5 = best-in-field, **3 = the default for a solid paper**; most dimensions are 2–3). Weight Prose
|
|
165
|
+
(#5), Jargon (#6), Landing (#7) ×2 — that's where "wall of jargon" lives. Report raw /45 + weighted /60.
|
|
166
|
+
**Do NOT trust a single grade.** A lone grader — especially one that just wrote or verified the paper —
|
|
167
|
+
anchors optimistic; a 52/60-looking number is suspect until confirmed. So **when the score matters, run a
|
|
168
|
+
blind panel: ≥3 independent graders (fresh subagents, ideally an adversarial model like Fable), each
|
|
169
|
+
blind to any prior score, to each other, and to the "it improved" framing — given only the current page
|
|
170
|
+
and the field's best.** Report the **distribution (per-dimension + overall min / median / max)**, not one
|
|
171
|
+
number; flag any dimension where graders disagree by >1 as genuinely ambiguous. (See "Scoring
|
|
172
|
+
calibration" in the reference; this is the writing-axis analogue of \`pc-panel-review\`.)
|
|
173
|
+
3. **For every dimension scoring ≤3, name the specific offending sentence or section** and write the fix —
|
|
174
|
+
not "tighten the prose" but the rewritten sentence, or "move the point from ¶3 to ¶1", or "gloss
|
|
175
|
+
\`operation-normalized\` in plain words at first use." Fixes must be applyable, not vibes.
|
|
176
|
+
4. **Find the paper's three-move opportunities:** what held assumption could open it? what is its single
|
|
177
|
+
most visceral concrete instance (lead with that, not the mean)? what one sentence should the reader
|
|
178
|
+
quote? If the draft is missing any, that's the highest-leverage fix.
|
|
179
|
+
5. **Flag the two prose traps by name:** (a) Attention-style dense contribution-less prose used where the
|
|
180
|
+
audience does NOT already care; (b) hedge-stacking ("may possibly in some cases potentially") — replace
|
|
181
|
+
each pile with one precise scope sentence.
|
|
182
|
+
6. 🔴 **Run \`prose-lint.mjs\` and treat every FLAG as a finding, not as context.** It is wired into
|
|
183
|
+
\`paper-lint\` on paper edits, so its output arrives whether or not this skill was invoked — but the
|
|
184
|
+
skill is what must ACT on it. Its thresholds are sourced; a FLAG means the text sits above a
|
|
185
|
+
published human or machine baseline, which is a defect with a number attached, not an opinion.
|
|
186
|
+
Two entries in \`THRESHOLDS\` exist because this skill previously ran five times without either
|
|
187
|
+
firing: the \`"not X, but Y"\` density had **no threshold at all** and printed as a neutral line
|
|
188
|
+
while standing at 50.8 per 10,000 words against an LLM baseline of 7.8, and the lexicon missed
|
|
189
|
+
both variants a reader spotted by eye — the bare inversion (*"Reading the file is not the weak
|
|
190
|
+
point; judging it is"*) and the appositive that reaches headings (*"Admission, not translation"*).
|
|
191
|
+
A number printed without a threshold is prose; that is this project's own thesis, and the linter
|
|
192
|
+
was violating it.
|
|
193
|
+
|
|
194
|
+
6a. 🔴 **\`prose-lint.mjs\` IS NO LONGER ALONE — seven of its twelve gating metrics moved
|
|
195
|
+
on 2026-08-26 into ESLint rules, and running only it shows you five twelfths.** A second
|
|
196
|
+
run is mandatory; without it, step 6 is incomplete:
|
|
197
|
+
|
|
198
|
+
\`\`\`
|
|
199
|
+
npx eslint "papers/*/paper.md" "papers/*/draft.md"
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
From there come: \`paper/citation-density\` · \`paper/unexplained-jargon\` ·
|
|
203
|
+
\`paper/multi-claim-sentence\` · \`paper/conceits\` · \`paper/hedge-density\` ·
|
|
204
|
+
\`paper/discourse-subject\` · \`paper/undefined-coinage\` (file — \`eslint-rules/paper-craft.mjs\`).
|
|
205
|
+
Gain from the move — \`file:line:col\` on each finding: the old report printed the sentence head,
|
|
206
|
+
and you had to find it in the article by eye. Everything step 6b says about
|
|
207
|
+
meaning regression applies to them just the same: this is diagnosis, not objective.
|
|
208
|
+
|
|
209
|
+
6b. 🔴 **A lint fix that costs meaning is a REGRESSION, and no linter can see it.** The metrics above
|
|
210
|
+
are diagnostics, never objectives. Optimising one directly is how a sentence gets worse while the
|
|
211
|
+
number gets better — and the number is exactly what makes it feel like progress.
|
|
212
|
+
|
|
213
|
+
Observed 2026-08-05, twice in one pass, both by the author of this rule:
|
|
214
|
+
- *"English cannot be exact — not through any defect in how we write it, but because that is what
|
|
215
|
+
English is"* became *"English cannot be exact; that is what English is for"*. The tic went. So
|
|
216
|
+
did the meaning: the new clause says English **exists in order to** be inexact, which is not a
|
|
217
|
+
claim anyone holds. The author's reaction was *«what the fuck does that even mean»*.
|
|
218
|
+
- *"Yet the agent turns out not to be the weak link"* became **"The agent obeys."** Three words,
|
|
219
|
+
zero flags, and the wrong finding — the experiment measured whether *writing a rule down* works,
|
|
220
|
+
while the replacement reads as a claim about agents being submissive.
|
|
221
|
+
|
|
222
|
+
**The procedure, and it is not optional:** after replacing a flagged sentence, read the
|
|
223
|
+
replacement as someone who has not read the paper. Does it still say the thing? Would they know
|
|
224
|
+
what it means? If the honest answer is no, the original was better and the flag stays open — an
|
|
225
|
+
open flag is a truthful state, and a passing metric over a sentence nobody can parse is not.
|
|
226
|
+
Prefer rewriting the whole **thought** in plain words to surgically excising the construction:
|
|
227
|
+
the tic is usually a symptom of a compressed idea, and decompressing it removes the tic as a
|
|
228
|
+
side effect.
|
|
229
|
+
|
|
230
|
+
7. 🔴 **Put \`WORST-SECTION: <section>\` on the FIRST LINE of the report.** Machine-readable, one
|
|
231
|
+
section, lowercase, no decoration. \`pipeline-check.mjs\` reads the last four reports and raises
|
|
232
|
+
\`repeat-finding\` when the same section is worst twice running. This exists because the abstract
|
|
233
|
+
was named worst **five consecutive times**, was faithfully recorded in the scorecard all five
|
|
234
|
+
times, and was never once the next task. A review loop that only appends findings converges on a
|
|
235
|
+
paper whose defects are all thoroughly documented and none of them fixed. **Naming the worst
|
|
236
|
+
section is not the deliverable — a fix for it, or a recorded decision to ship with it, is.**
|
|
237
|
+
|
|
238
|
+
8. **Run the avoid-list grep (mechanical).** Grep the source for the slop / web-slang / filler / hype words
|
|
239
|
+
in \`../paper-pipeline/references/writing-craft.md\` → "The avoid-list", and report every hit with its line number and a
|
|
240
|
+
replacement. These are scrutinize-words, not absolute bans — but each hit is a readability debit against
|
|
241
|
+
dimension #6 (Jargon) and the "engaging + human-readable" north star. (This session's miss that motivated
|
|
242
|
+
it: "listicle" survived into a submitted-ready AISec draft.)
|
|
243
|
+
7. **Wall-of-text sweep (see \`writing-craft.md\` → "The wall-of-text check").** Flag any paragraph running
|
|
244
|
+
>~15 source lines / ~150 words or covering >3 sub-points — a visual wall the reader's eye slides off
|
|
245
|
+
(distinct from stall density). Prescribe the fix: break into run-in-headed chunks. Caps dimension #4.
|
|
246
|
+
8. **Conclusion & quotability sweep (explicit — see \`writing-craft.md\` → "The conclusion & quotability
|
|
247
|
+
check").** Grade the CONCLUSION on its own, not just the intro: does it pay off in plain language, name the
|
|
248
|
+
stakes, point past the result, and hand the reader a concrete action — or is it a limp results-recap (a 2)?
|
|
249
|
+
Then check the abstract AND the conclusion each carry one extractable, quotable line (the "paste onto a
|
|
250
|
+
talk slide" test); if a surface has none, flag it and draft the candidate line. Report both explicitly —
|
|
251
|
+
these feed dimension #7 (which is graded on both surfaces). This is the axis that catches "the conclusion
|
|
252
|
+
isn't strong enough" and "nothing here is quotable."
|
|
253
|
+
|
|
254
|
+
## Output
|
|
255
|
+
1. **Scorecard** — nine dimensions with one-line justification each; raw /45 + weighted /60. When a blind
|
|
256
|
+
panel was run (the default when the score matters), report the **distribution** — per-dimension and
|
|
257
|
+
overall min / median / max across graders — not a single number, and name any dimension they split on.
|
|
258
|
+
Lead with the two or three dimensions dragging it down, ranked.
|
|
259
|
+
2. **Cold-read stall inventory** — the ranked list of "what does that even mean?" points (location → quoted
|
|
260
|
+
trigger → reader's question → fix) plus the stall density per page. This is the most directly actionable
|
|
261
|
+
output; a fix pass works straight off it.
|
|
262
|
+
2. **Sentence-level fix list** — for every ≤3 dimension: the offending text → the concrete rewrite/move.
|
|
263
|
+
Ordered by leverage (the fix that most improves how it reads first).
|
|
264
|
+
3. **The three-move audit** — the assumption to open on, the visceral instance to lead with, the one
|
|
265
|
+
repeatable sentence — supplied or flagged as missing.
|
|
266
|
+
4. **A one-paragraph verdict** — is this a pleasant read for a busy, skeptical reviewer yet, and the single
|
|
267
|
+
change that would move it most.
|
|
268
|
+
5. **SAVE the report colocated — don't let it evaporate.** A grade run in a subagent reports into a
|
|
269
|
+
transcript that is gone next session. Write the scorecard + stall inventory + fix list to
|
|
270
|
+
**\`<paper-dir>/reviews/<YYYY-MM-DD>-grade-paper-writing.md\`** and link it from the paper's
|
|
271
|
+
\`PIPELINE-STATUS.md\` (Wc row). Same rule as \`pc-panel-review\`'s ledger and \`analyze-sibling-paper\`'s
|
|
272
|
+
\`siblings/\` — review artifacts live colocated and ride with the paper to camera-ready/extension.
|
|
273
|
+
|
|
274
|
+
## Record the verdict
|
|
275
|
+
|
|
276
|
+
🔴 LAST step, once the deliverable exists:
|
|
277
|
+
|
|
278
|
+
\`\`\`
|
|
279
|
+
node .claude/skills/paper-pipeline/scripts/ledger.mjs record grade-paper-writing <paper-dir> FINDING <count> <report-path>
|
|
280
|
+
node .claude/skills/paper-pipeline/scripts/ledger.mjs record grade-paper-writing <paper-dir> ABSTAINED <reason> "<one line>"
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
**FINDING** — \`<count>\` is the number of entries in the PERSONA stall inventory, and \`<report-path>\`
|
|
284
|
+
is that inventory. Add \`--blocking\` when a dimension scored 1–2, or stall density is over its cap.
|
|
285
|
+
**ABSTAINED** — \`no-witness\`: the inventory came back empty. \`blocked\`: no persona reader was run,
|
|
286
|
+
so there is no inventory — which is not an empty inventory and must never be filed as one.
|
|
287
|
+
|
|
288
|
+
🔴 **There is no PASS**, and the distinction the two abstentions draw is the one that was being
|
|
289
|
+
lost: "a reader stalled nowhere" and "nobody read it" produced the same word.
|
|
290
|
+
|
|
291
|
+
🔴 **Record the stall count, never the rubric number.** The inventory is what \`pc-panel-review\`,
|
|
292
|
+
\`paper-adversarial-review\` and \`harden-paper\` consume; a 44/60 in the ledger would let a paper whose
|
|
293
|
+
readability gate is failing look clean to every skill downstream.
|
|
294
|
+
|
|
295
|
+
\`prose-lint.mjs\` files separately as \`grade-paper-writing/prose-lint\`. One check, one row.
|
|
296
|
+
|
|
297
|
+
## Rules
|
|
298
|
+
- Grade **writing, not science.** A correct paper can still score a 2 here; say so. Don't drift into
|
|
299
|
+
content/defect review — that's \`paper-adversarial-review\` / \`pc-panel-review\`.
|
|
300
|
+
- **Every low score comes with the offending sentence and its fix.** No abstract advice.
|
|
301
|
+
- **Preserve claims.** Suggested rewrites must not change any result, number, or hedge — only how it reads.
|
|
302
|
+
(This mirrors the constraint on any prose rewrite of a real submission.)
|
|
303
|
+
- **After applying sentence fixes, run the \`claims\` claim-preservation diff** (owner:
|
|
304
|
+
\`../paper-pipeline/references/writing-craft.md\` → "The claim-preservation diff") — an adversarial
|
|
305
|
+
(Fable) before/after diff verifying **no number moved, no hedge dropped, no claim strengthened, no
|
|
306
|
+
new absolute, no self-contradiction**. The fix pass is not done until it's clean; record it in the
|
|
307
|
+
\`claims\` row of the paper's \`PIPELINE-STATUS.md\`. This step is mandatory after EVERY rewrite, not optional.
|
|
308
|
+
- **Respect the page budget.** Prefer fixes that cut or hold length; a paper at its page ceiling can't grow.
|
|
309
|
+
- **Honesty over flattery.** If the abstract is a stat-wall, score it a 2 and show the five-move rewrite.
|
|
310
|
+
|
|
311
|
+
## 🔴 The tell that says a machine wrote it: three findings in one sentence
|
|
312
|
+
|
|
313
|
+
The single most reliable marker of LLM prose in a paper is **the citation tricolon** — separate
|
|
314
|
+
findings packed into one sentence with a reference hung off each:
|
|
315
|
+
|
|
316
|
+
> *Adherence has been measured directly more than once: it decays as a session proceeds [6], and
|
|
317
|
+
> agents that undertake to follow a process frequently do not [7] — while a factorial study of the
|
|
318
|
+
> file's own structure, varying size, position and ordering, found no effect at all [4].*
|
|
319
|
+
|
|
320
|
+
Three unrelated results, one sentence, 48 words, a colon, a comma-splice and an em-dash contrast. It
|
|
321
|
+
reads fluently and nothing survives it. Its cousin is the **noun pile with no verb**, which exists
|
|
322
|
+
only to carry citations:
|
|
323
|
+
|
|
324
|
+
> *Censuses, taxonomies and labellings of what these files contain [3, 11, 12, 18–20, 25, 34].*
|
|
325
|
+
|
|
326
|
+
**Rule: one finding, one sentence.** If three works said three things, that is three sentences, and
|
|
327
|
+
each says what the work found rather than that it exists. A citation group belongs to a claim, not to
|
|
328
|
+
a list. When the related work genuinely is a survey, say what the surveys share and cite them once.
|
|
329
|
+
|
|
330
|
+
Mechanical leg: \`paper-lint\`'s plain-language pass flags any sentence carrying three or more separate
|
|
331
|
+
citation groups, or five or more reference numbers in under 45 words. It cannot judge whether the
|
|
332
|
+
prose is *good*; it reliably catches this one shape, which is the shape that recurs.
|
|
333
|
+
|
|
334
|
+
**And the words themselves, not only the sentences.** *Adherence* means *following the rules*. The
|
|
335
|
+
"Jargon discipline" dimension below does not catch this, because the word looks perfectly at home —
|
|
336
|
+
judgment slides right past it. What catches it is a list: \`paper-lint\` carries ~30 words with a plain
|
|
337
|
+
English equivalent (adherence · utilise · demonstrates · constitutes · prior to · necessitates ·
|
|
338
|
+
facilitates · methodology · leverage · albeit · comprise · entail · in order to …) and names the
|
|
339
|
+
replacement in the nudge. Keep the list narrow — only words where the swap does not change meaning —
|
|
340
|
+
and never rewrite a cited work's title to obey it.
|
|
341
|
+
|
|
342
|
+
**Other markers of the same register, all cheap to check and all worth a pass:** nominalisation
|
|
343
|
+
density (*an honest accounting of what the construction costs* — abstract nouns doing the work verbs
|
|
344
|
+
should do), stock connectives (*furthermore*, *thereby*, *it is worth noting*), and statistics chained
|
|
345
|
+
through a paragraph instead of sitting in a table. Numbers belong in a table the moment there are more
|
|
346
|
+
than about six of them in one paragraph.
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
## 🔴 The class the rubric could not see, and why it kept coming back (2026-08-04)
|
|
350
|
+
|
|
351
|
+
The author of \`compile-rules-2026\` read the built abstract and wrote: *«what the f\\*** does that
|
|
352
|
+
even mean, no human would write it like that»*. He had said the same thing about the same paper
|
|
353
|
+
**repeatedly**. Nine rubric axes, a persona cold-read at 5.9 stalls/page, an AI-tells counter and
|
|
354
|
+
three tighten passes all scored the text and **none of them named the defect**, because every one of
|
|
355
|
+
them measures words and sentences. The defect is not in the words.
|
|
356
|
+
|
|
357
|
+
**The specimen, verbatim, and it passed every check we own:**
|
|
358
|
+
|
|
359
|
+
> "Two findings about the agent come first, because they bind whatever else you build. Asked the
|
|
360
|
+
> same question twice with identical inputs, a frontier model changes its verdict on 21.5% of rows,
|
|
361
|
+
> so no harness that has a model adjudicate its own instructions can use one as the gate."
|
|
362
|
+
|
|
363
|
+
Two separable failures:
|
|
364
|
+
|
|
365
|
+
### 1. The text talks about the text (metadiscourse)
|
|
366
|
+
|
|
367
|
+
*"Two findings come first, because they bind whatever else you build"* says nothing about rules
|
|
368
|
+
files, agents, or repositories. It is the paper **narrating its own structure** — the reader is
|
|
369
|
+
handed a table of contents where they expected a fact. This is Hyland's *frame marker*, and in this
|
|
370
|
+
corpus it is the single most reliable smell of machine-drafted expository prose: an
|
|
371
|
+
instruction-tuned model is rewarded for signposting, so it signposts where a writer would simply
|
|
372
|
+
say the thing.
|
|
373
|
+
|
|
374
|
+
**Countable.** Per section, count openers and connectives whose subject is the document rather than
|
|
375
|
+
the world: *this paper · this section · we now turn · comes first · in what follows · the rest of
|
|
376
|
+
this · as discussed above · it is worth noting · importantly*. Measured on this paper: **10 in the
|
|
377
|
+
body**, and the abstract's opener was one. Target for an abstract or conclusion: **zero**. Body:
|
|
378
|
+
under one per section, and every survivor must earn a reason.
|
|
379
|
+
|
|
380
|
+
**Rewrite heuristic:** delete the frame and start at the fact. *"Two findings come first, because
|
|
381
|
+
they bind whatever else you build. Asked the same question twice…"* → *"Asked the same question
|
|
382
|
+
twice with identical inputs, a frontier model changes its verdict on 21.5% of rows."* Nothing is
|
|
383
|
+
lost. The ordering was already visible — it is the order of the sentences.
|
|
384
|
+
|
|
385
|
+
### 2. The qualification eats the claim
|
|
386
|
+
|
|
387
|
+
*"…though that cell does not survive our own correction for multiplicity and we report it as
|
|
388
|
+
suggestive (Appendix A.2)"* is 20 words of hedge welded onto a 20-word finding. Each hedge was
|
|
389
|
+
added honestly, by a different review round, and none was wrong. Their **placement** is the defect, and no single round can see it.
|
|
390
|
+
|
|
391
|
+
🔴 **The obvious diagnosis is wrong, and it was measured.** Peer review does **not** ratchet hedge
|
|
392
|
+
words in. Keserlioglu, Kilicoglu & ter Riet (2019, *Research Integrity and Peer Review*, n = 446
|
|
393
|
+
manuscript–publication pairs across 28 journals) found hedge density moving 2.06% → 2.13% — and
|
|
394
|
+
non-significant after adjusting for journal characteristics. What review adds is **standalone
|
|
395
|
+
limitation sentences**: 2.48 → 3.87 per paper. So the published norm is that qualification enters a
|
|
396
|
+
good paper **as its own sentence**, not as particles inside a claim sentence. \`compile-rules-2026\`
|
|
397
|
+
ran at **0.37%** hedge words against that 2.13% norm — it was never over-hedged by count. It was
|
|
398
|
+
mis-**placed**: the caveat was welded into the result sentence, where it competes with the result for
|
|
399
|
+
the stress position and wins.
|
|
400
|
+
|
|
401
|
+
**Countable.** Caveats that are grammatically independent sentences versus caveats embedded as
|
|
402
|
+
subordinate clauses (*though · while · although · albeit*) inside a sentence that also states a
|
|
403
|
+
result. Target: all standalone. Also count sentences ending on a cross-reference, citation or hedge
|
|
404
|
+
while the sentence's own number sits earlier — Gopen & Swan's stress position, spent on a pointer.
|
|
405
|
+
|
|
406
|
+
**Rewrite heuristic — the order matters:** state the finding as a whole sentence, then qualify it in
|
|
407
|
+
the **next** sentence. Never inside it. *"Violations went from 17% to 100%, back to the rate with no
|
|
408
|
+
file at all. That is one cell of five, and it does not clear the multiplicity correction we
|
|
409
|
+
pre-registered (Appendix A.2)."* Same words, same honesty, and the claim survives the reading.
|
|
410
|
+
|
|
411
|
+
### 3. Phrases that reference an unstated alternative
|
|
412
|
+
|
|
413
|
+
*"So we left the sentences alone"* — the reader has not been told what else might have been done to
|
|
414
|
+
them, so "left alone" refers to nothing. Same author reaction, same day. **Check:** any *instead of ·
|
|
415
|
+
rather than · left alone · we did not · not X but Y* whose rejected alternative is not stated within
|
|
416
|
+
one sentence.
|
|
417
|
+
|
|
418
|
+
### 🎯 The abstract and the conclusion are graded on a different scale
|
|
419
|
+
|
|
420
|
+
They are the only two sections most readers finish, and the abstract is the only one every reviewer
|
|
421
|
+
reads before forming a view. Grade them **separately and harder**:
|
|
422
|
+
|
|
423
|
+
- **zero** frame markers, **zero** self-reference to the paper;
|
|
424
|
+
- first sentence is about the world, never about the document;
|
|
425
|
+
- no number arrives without the unit it counts (*"21.5% of rows"* — rows of what?);
|
|
426
|
+
- the last sentence of each is a **conclusion**, not an announcement of one;
|
|
427
|
+
- nothing may refer forward to a section the reader has not read.
|
|
428
|
+
|
|
429
|
+
A body section may be merely clear. These two have to be **sharp**, and if the abstract survives a
|
|
430
|
+
tighten pass marked \`KEEP\` three rounds running, that is evidence it was never really read — this
|
|
431
|
+
one did, and it was the worst section in the paper by measured density both times.
|
|
432
|
+
|
|
433
|
+
### What is NOT mechanizable here
|
|
434
|
+
|
|
435
|
+
Whether a frame marker is load-bearing (*"we claim nothing there"* genuinely scopes a claim) and
|
|
436
|
+
whether a hedge is honest or defensive. Count them, surface them, and leave the verdict to a reader.
|
|
437
|
+
The counter's job is that nobody can say afterwards they did not know.
|
|
438
|
+
|
|
439
|
+
## Compose with
|
|
440
|
+
- \`harden-paper\` — the multi-axis pre-submit gate calls this as its *writing* axis (the one a defect-hunt
|
|
441
|
+
and a threat-model check both miss).
|
|
442
|
+
- \`draft-paper\` — the generative counterpart (writes the prose); this grades it. Both cite the same
|
|
443
|
+
\`../paper-pipeline/references/writing-craft.md\`, so guidance and grading never diverge.
|
|
444
|
+
- \`paper-adversarial-review\` / \`pc-panel-review\` — run those for scientific defects; run this for readability. Complementary axes, not redundant.
|
|
445
|
+
- \`render-paper\` — build the PDF/PNGs first so you grade what the reviewer will actually see.
|
|
446
|
+
|
|
447
|
+
## Provenance
|
|
448
|
+
Built from the **AISec 2026 GateBench** polish run (2026-07): the author's verdict was "wall of text and
|
|
449
|
+
jargon that doesn't drive home how crazy the situation is — real humans will be reading this." The rubric
|
|
450
|
+
was grounded by dissecting Peyton Jones / McEnerney / Gopen & Swan and honestly grading exemplars
|
|
451
|
+
(Attention = impact-not-prose; Trusting Trust / Carlini / Greshake = the real craft models), then applied
|
|
452
|
+
as the instrument that graded the rewritten paper.`,
|
|
453
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In the egg extract, the availability of TFIIIA limits transcription of the 5S RNA genes. This is surprising because the same concentration of TFIIIA does not limit transcription in the oocyte nuclear extract. In the egg extract, transcription is not limited by RNA polymerase or other factors because transcription of tRNA genes indicates that these factors are in excess over available TFIIIA. When added to the nuclear extract, the egg extract affected the efficiency of transcription in two ways. First, it inhibited transcription generally; this inhibition could be alleviated in part by supplementing the mixture with high concentrations of RNA polymerase III. Second, the egg extract destabilized transcription complexes formed by oocyte but not by somatic 5S genes.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
The picture is one of mis-calibration by register in both directions: the models pour the figure on where it flatters a persuasive audience and withhold it where a peer would qualify a claim. A specificity check supports reading this as targeted rather than as general verbosity: across genres the models use fewer neutral connectives than humans (in oratory, 1.5 against 7.5 per 5 ten thousand words), so the oratorical spike is not mere marker-heaviness. Narrative makes the same point from the other side, since against a proper multi-work baseline the human rate is itself high (7.5) and the models fall below it. These ratios can be read as a single metric. Define the Epanorthosis Index of a text or corpus in genre g as its emphatic-epanorthosis density divided by the human baseline for that genre, EIg = Dg / Hg : an index of 1 is human-like calibration, above 1 is overshoot, below 1 undershoot. The “LLM / human” column of Table 1 is exactly this index, and its spread is the point: EI ≈ 2.2 in oratory and ≈ 0.2 in informal question-and-answer, a two-sided mis- calibration that a single raw-frequency number would hide. A corpus-level calibration error, the mean of |log EIg | across genres, condenses this into one number for how far a model sits from
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Ask a frontier model the same question twice, with identical inputs, and it changes its verdict on 21.5% of rows. So a harness that has a model adjudicate its own instructions cannot use one as its gate. Nor can a model certify the checker it has just written. Its own self-test refused none of the 21 checkers it synthesized; a gold set it had never seen refused 16 of them. Deleting an unenforced rule is not the safe move either. On the rule where it mattered most, violations rose from 17% to 100% — the rate we measure with no rule file at all. That last cell (Appendix A.2) does not survive our own correction for multiplicity, and we report it as suggestive.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Two findings about the agent come first, because they bind whatever else you build. Asked the same question twice with identical inputs, a frontier model changes its verdict on 21.5% of rows, so no harness that has a model adjudicate its own instructions can use one as the gate. And a model asked to write the missing checker cannot certify it: its own self-test refused none of 21 synthesized checkers, while a gold set it never saw refused 16. Deleting an unenforced rule is not the safe move either — on the rule where it mattered most, violations went from 17% to 100%, back to the no-file rate, though that cell does not survive our own correction for multiplicity and we report it as suggestive (Appendix A.2).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Fixture — planted defects for the two paragraph-level checks"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Abstract
|
|
6
|
+
|
|
7
|
+
Clean prose with nothing planted in it at all.
|
|
8
|
+
|
|
9
|
+
## 1. Introduction
|
|
10
|
+
|
|
11
|
+
PLANT-A: this paragraph stops the reader at five separate citation sites, which is above the
|
|
12
|
+
threshold [1], and the rest of it says very little [2] while continuing to cite things [3] and
|
|
13
|
+
then some more things [4] and finally one more [5, 6]. Note that the last site holds two numbers
|
|
14
|
+
and still counts once — that is the whole point of counting sites rather than numbers.
|
|
15
|
+
|
|
16
|
+
PLANT-B: watch the agent instead of the file, against a temporal logic, a policy language a
|
|
17
|
+
solver checks, or a learned model of what the repository does.
|
|
18
|
+
|
|
19
|
+
CLEAN-A: this paragraph carries one marker [7] and no unexplained vocabulary, so neither check
|
|
20
|
+
should have anything to say about it.
|
|
21
|
+
|
|
22
|
+
CLEAN-B: soundness alone in a sentence is one term, not a pile-up, and must stay quiet.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grade-paper-writing — the PAID tier: does this skill's description actually fire?
|
|
3
|
+
*
|
|
4
|
+
* COLOCATED ON PURPOSE (vigiles decides coverage by placement as of 2026-08-11).
|
|
5
|
+
* The prompts live in `.claude/lib/skill-trigger-cases.mjs` so all 21 cases
|
|
6
|
+
* are reviewed as one table where collisions between siblings are visible;
|
|
7
|
+
* copying them here would recreate the drift that rule exists to prevent.
|
|
8
|
+
*
|
|
9
|
+
* Measures recall (fires on its own territory) AND precision (stays quiet on a
|
|
10
|
+
* colliding sibling's territory), against the REAL `.claude` harness so the skill
|
|
11
|
+
* competes with every other installed description — an isolated run overstates
|
|
12
|
+
* recall and understates false positives.
|
|
13
|
+
*
|
|
14
|
+
* Costs money; not CI.
|
|
15
|
+
* node .claude/skills/grade-paper-writing/grade-paper-writing.eval.mjs [trials]
|
|
16
|
+
*/
|
|
17
|
+
import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
|
|
18
|
+
|
|
19
|
+
await runSkillTriggerEval("grade-paper-writing");
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grade-paper-writing — the free, deterministic tier. No model, no network.
|
|
3
|
+
*
|
|
4
|
+
* COLOCATED ON PURPOSE. vigiles decides coverage by PLACEMENT as of 2026-08-11:
|
|
5
|
+
* a test that merely names a surface no longer counts, because that tier was
|
|
6
|
+
* crediting surfaces nothing touched. So each skill needs a file inside its own
|
|
7
|
+
* directory — this one.
|
|
8
|
+
*
|
|
9
|
+
* The assertions live in `.claude/lib/skill-checks.mjs` and are CALLED here with
|
|
10
|
+
* this skill's name. They are not copied: 22 copies of the same checks is the drift that
|
|
11
|
+
* module exists to avoid. (Until 2026-08-11 this was an env-var side channel into a
|
|
12
|
+
* 614-line file named after no surface; it is a function call now.)
|
|
13
|
+
*
|
|
14
|
+
* What this proves: this skill's frontmatter parses as strict YAML, its declared
|
|
15
|
+
* tool contract is sane, its pipeline wiring points at scripts that exist, and it
|
|
16
|
+
* announces/records under ITS OWN identity rather than a sibling's.
|
|
17
|
+
*
|
|
18
|
+
* What it does NOT prove: that the skill fires, or that its guidance produces a
|
|
19
|
+
* good result. Those need a real model — see `grade-paper-writing.eval.mjs`.
|
|
20
|
+
*/
|
|
21
|
+
import { checkSkill } from "../../lib/skill-checks.mjs";
|
|
22
|
+
|
|
23
|
+
await checkSkill("grade-paper-writing");
|