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,446 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* skill-trigger-cases.mjs — the per-skill trigger cases, in ONE place.
|
|
3
|
+
*
|
|
4
|
+
* WHY A SHARED MODULE AND NOT 21 FILES OF PROMPTS. Coverage is decided by
|
|
5
|
+
* placement (vigiles, 2026-08-11), so every skill needs a test file inside its own
|
|
6
|
+
* directory. That rule is right — a test that merely names a surface was crediting
|
|
7
|
+
* surfaces nothing touched — but satisfying it by copying prompts 21 times would
|
|
8
|
+
* recreate the drift the rule exists to prevent. So the colocated files are thin
|
|
9
|
+
* and the DATA lives here, reviewed as one table where collisions are visible.
|
|
10
|
+
*
|
|
11
|
+
* ── HOW TO READ A CASE ──────────────────────────────────────────────────────────
|
|
12
|
+
*
|
|
13
|
+
* skill the skill under test
|
|
14
|
+
* why the territory it owns, in one line — the thing a sibling must NOT take
|
|
15
|
+
* prompts should-fire. FOUR each, deliberately mixed (below)
|
|
16
|
+
* collides siblings whose own should-fire prompts become this case's
|
|
17
|
+
* irrelevantPrompts. That is how "the WRONG skill must not fire" is
|
|
18
|
+
* asserted, and it is symmetric: each side of a collision is measured
|
|
19
|
+
* from both directions.
|
|
20
|
+
*
|
|
21
|
+
* 🔴 THE PROMPTS ARE MIXED ON PURPOSE, AND THE MIX DECIDES THE NUMBER.
|
|
22
|
+
* `framing-vs-vocabulary.eval.mjs` measured the same skills two ways: prompts that
|
|
23
|
+
* NAME the action scored 78%, prompts that describe a SITUATION scored 25%. A set
|
|
24
|
+
* written only in the description's own verbs would report a flattering rate and
|
|
25
|
+
* measure how well the prompts were copied from the description. So each case
|
|
26
|
+
* carries both kinds — a couple that name the action, a couple that describe the
|
|
27
|
+
* situation the way the author actually types, in the language he actually types.
|
|
28
|
+
* Expect the aggregate to sit BELOW a same-vocabulary set. That is the point.
|
|
29
|
+
*
|
|
30
|
+
* Russian is over-represented on purpose too: `pipeline-language.eval.mjs`
|
|
31
|
+
* measured English 78.1% vs Russian 60.4% over 32 matched pairs (paired sign test
|
|
32
|
+
* p = 0.0074), and every description here is English while the author writes
|
|
33
|
+
* Russian. A set that quietly dropped the Russian prompts would hide the gap.
|
|
34
|
+
*
|
|
35
|
+
* The eight cases below marked HARVESTED were written for
|
|
36
|
+
* `paper-pipeline/pipeline-firing.eval.mjs` and moved here unchanged, so the two
|
|
37
|
+
* runners cannot drift apart. The thirteen marked NEW were added 2026-08-11 to
|
|
38
|
+
* finish the corpus; they have never been run, so their rates are UNKNOWN rather
|
|
39
|
+
* than assumed good.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
const PACKAGE_CASES = [
|
|
43
|
+
// ── HARVESTED (written for pipeline-firing.eval.mjs, measured) ───────────────
|
|
44
|
+
{
|
|
45
|
+
skill: "tighten-paper",
|
|
46
|
+
why: "structural bloat — cut/fold/merge, NOT sentence craft",
|
|
47
|
+
prompts: [
|
|
48
|
+
"статья раздулась, середина провисает — что резать?",
|
|
49
|
+
"this draft is 14 pages against a 9 page limit, what goes",
|
|
50
|
+
"после трёх раундов ревью там одна вода и хеджи, нужен план сокращения",
|
|
51
|
+
"sections 4 and 5 say the same thing twice, and nobody would skim any of it",
|
|
52
|
+
],
|
|
53
|
+
collides: ["grade-paper-writing", "argument-arc"],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
skill: "grade-paper-writing",
|
|
57
|
+
why: "prose craft — the sentence is the unit, NOT the section",
|
|
58
|
+
prompts: [
|
|
59
|
+
"оцени как написано — читается как стена жаргона",
|
|
60
|
+
"is the writing any good or does it read like shit",
|
|
61
|
+
"abstract звучит криво хотя по смыслу всё на месте, дай оценку прозе",
|
|
62
|
+
"grade the craft: title, abstract, sentence clarity, hedge stacking",
|
|
63
|
+
],
|
|
64
|
+
collides: ["tighten-paper", "argument-arc"],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
skill: "argument-arc",
|
|
68
|
+
why: "argument architecture — does one conclusion become inevitable",
|
|
69
|
+
prompts: [
|
|
70
|
+
"ревьюер второй раз пишет что мы кидаем в него идеи без связи",
|
|
71
|
+
"does the paper actually carry a reader to one conclusion or just list stuff",
|
|
72
|
+
"мы вводим пять именованных штук и три числа — по-моему это перебор",
|
|
73
|
+
"before the big rewrite I want one sentence per section, bottom up",
|
|
74
|
+
],
|
|
75
|
+
collides: ["tighten-paper", "grade-paper-writing"],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
skill: "paper-adversarial-review",
|
|
79
|
+
why: "ONE hostile reviewer, fast",
|
|
80
|
+
prompts: [
|
|
81
|
+
"red-team эту статью, чем будет бить reviewer 2",
|
|
82
|
+
"would reviewer 2 buy this claim about the hook finding",
|
|
83
|
+
"найди слабые места до сабмита — один злой но честный рецензент",
|
|
84
|
+
"what is our desk reject risk and where do we overclaim",
|
|
85
|
+
],
|
|
86
|
+
collides: ["pc-panel-review"],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
skill: "pc-panel-review",
|
|
90
|
+
why: "the WHOLE committee + an accept probability, not one reviewer",
|
|
91
|
+
prompts: [
|
|
92
|
+
"какая вероятность принятия у этой статьи, если честно",
|
|
93
|
+
"simulate the whole program committee, not one reviewer",
|
|
94
|
+
"что решат на PC discussion — accept или reject",
|
|
95
|
+
"нужно несколько независимых ревьюеров с разными линзами плюс мета-ревью от чейра",
|
|
96
|
+
],
|
|
97
|
+
collides: ["paper-adversarial-review"],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
skill: "cold-read-diff",
|
|
101
|
+
why: "fires AFTER a prose edit — the reader with no context",
|
|
102
|
+
prompts: [
|
|
103
|
+
"я переписал третий абзац intro — проверь что предложения вообще что-то значат",
|
|
104
|
+
"just edited the threats section, would a reader with no context get it",
|
|
105
|
+
"поправил формулировки в 4.2, прогони свежим читателем до того как я закрою правку",
|
|
106
|
+
"эти предложения короткие, правдивые и всё равно непонятно что они утверждают",
|
|
107
|
+
],
|
|
108
|
+
collides: ["grade-paper-writing", "tighten-paper"],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
skill: "verify-citations",
|
|
112
|
+
why: "are the cites REAL — a pre-submit metadata gate",
|
|
113
|
+
prompts: [
|
|
114
|
+
"проверь что все цитаты настоящие перед сабмитом",
|
|
115
|
+
"did we hallucinate any of these refs",
|
|
116
|
+
"сверь метаданные по каждому cite — год, венью, авторы, doi",
|
|
117
|
+
"one bibtex entry looks invented to me, check the whole bibliography",
|
|
118
|
+
],
|
|
119
|
+
collides: ["map-prior-work"],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
skill: "map-prior-work",
|
|
123
|
+
why: "who already did this — BEFORE drafting, reshapes the contribution",
|
|
124
|
+
prompts: [
|
|
125
|
+
"кто уже это сделал до нас — хочу знать до того как начну писать",
|
|
126
|
+
"sweep the landscape: everyone working on this, prior versus concurrent",
|
|
127
|
+
"нужен скелет related work и вердикт что мы ещё можем клеймить своим",
|
|
128
|
+
"find every competing group in this space and date them against our submission",
|
|
129
|
+
],
|
|
130
|
+
collides: ["verify-citations"],
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
// ── NEW 2026-08-11 (never run — rates UNKNOWN, not assumed good) ─────────────
|
|
134
|
+
{
|
|
135
|
+
skill: "analyze-sibling-paper",
|
|
136
|
+
why: "ONE named rival, deep-read — is our delta real or cosmetic",
|
|
137
|
+
prompts: [
|
|
138
|
+
"вышла статья почти про то же самое, надо понять насколько мы пересекаемся",
|
|
139
|
+
"рецензент пишет «это же уже сделано в X» — разбери X целиком",
|
|
140
|
+
"read this competitor end to end and tell me the strongest scoop they could claim",
|
|
141
|
+
"они препринт выложили раньше нас на месяц — это prior work или concurrent",
|
|
142
|
+
],
|
|
143
|
+
collides: ["map-prior-work", "verify-citations"],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
skill: "build-benchmark",
|
|
147
|
+
why: "design + RUN the study, and ship the artifact reviewers execute",
|
|
148
|
+
prompts: [
|
|
149
|
+
"надо спроектировать сам замер, а не описывать его — как считать честно",
|
|
150
|
+
"нужны парные прогоны, доверительные интервалы и поправка на множественные сравнения",
|
|
151
|
+
"build the artifact a reviewer can run that recomputes every number in the paper",
|
|
152
|
+
"у нас n маленькое и разброс большой — это результат или шум",
|
|
153
|
+
],
|
|
154
|
+
collides: ["research-ideate", "draft-paper"],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
skill: "camera-ready",
|
|
158
|
+
why: "AFTER accept — de-anonymize, archive, disclose",
|
|
159
|
+
prompts: [
|
|
160
|
+
"пришёл accept, что теперь делать до дедлайна финальной версии",
|
|
161
|
+
"надо снять анонимизацию и выложить артефакт уже под своим именем",
|
|
162
|
+
"we got in — swap the view-only artifact for a real repo and get a DOI",
|
|
163
|
+
"перед публичным релизом надо закрыть responsible disclosure по найденной дыре",
|
|
164
|
+
],
|
|
165
|
+
collides: ["submit-paper", "extend-paper"],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
skill: "draft-paper",
|
|
169
|
+
why: "numbers exist → WRITE it: sections, claim-sizing, threats",
|
|
170
|
+
prompts: [
|
|
171
|
+
"числа есть, пора писать текст",
|
|
172
|
+
"turn these findings into an actual submission",
|
|
173
|
+
"нужен abstract и intro, и явный абзац «чего мы НЕ утверждаем»",
|
|
174
|
+
"как сформулировать вклад чтобы он был точным, а не раздутым",
|
|
175
|
+
],
|
|
176
|
+
collides: ["argument-arc", "build-benchmark"],
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
skill: "extend-paper",
|
|
180
|
+
why: "accepted workshop paper → a SECOND, stronger publication",
|
|
181
|
+
prompts: [
|
|
182
|
+
"воркшопную статью приняли — как сделать из неё полноценную вторую",
|
|
183
|
+
"сколько нового материала нужно чтобы это не считалось дублем",
|
|
184
|
+
"we have one accepted short paper and I want a body of work, not a one-hit",
|
|
185
|
+
"куда подавать расширенную версию и не нарушу ли я правило про dual submission",
|
|
186
|
+
],
|
|
187
|
+
collides: ["camera-ready", "find-venue"],
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
skill: "find-venue",
|
|
191
|
+
why: "WHERE to send it — ranked by indexing and accept-probability",
|
|
192
|
+
prompts: [
|
|
193
|
+
"куда это вообще подавать",
|
|
194
|
+
"нужен список площадок с дедлайнами и понять какие индексируются",
|
|
195
|
+
"which workshop gives real peer review and lands in the ACM DL",
|
|
196
|
+
"успеваем ли мы куда-нибудь до конца осени и с какой вероятностью пройдём",
|
|
197
|
+
],
|
|
198
|
+
collides: ["plan-paper-timeline", "study-accepted-papers"],
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
skill: "harden-paper",
|
|
202
|
+
why: "the pre-submit GATE — a vector of gates, worst first",
|
|
203
|
+
prompts: [
|
|
204
|
+
"статья готова к сабмиту или нет",
|
|
205
|
+
"прогони финальную проверку перед загрузкой, всё ли закрыто",
|
|
206
|
+
"what is still missing before I upload this thing",
|
|
207
|
+
"хочу вердикт по всем осям сразу, а не одно ревью",
|
|
208
|
+
],
|
|
209
|
+
collides: ["pc-panel-review", "paper-adversarial-review"],
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
skill: "plan-paper-timeline",
|
|
213
|
+
why: "CFP dates → a scheduled, buffered plan on the calendar",
|
|
214
|
+
prompts: [
|
|
215
|
+
"дедлайн 15 сентября — разложи по датам что когда делать",
|
|
216
|
+
"поставь события в календарь: сабмит, дедлайн, камера-реди",
|
|
217
|
+
"build the schedule backwards from the deadline with buffer for the review passes",
|
|
218
|
+
"две статьи подряд получаются, разведи их чтобы не слиплись перед подачей",
|
|
219
|
+
],
|
|
220
|
+
collides: ["find-venue"],
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
skill: "render-paper",
|
|
224
|
+
why: "compile the LaTeX and produce readable page images",
|
|
225
|
+
prompts: [
|
|
226
|
+
"собери pdf и покажи страницы",
|
|
227
|
+
"хочу посмотреть как это выглядит вёрсткой с телефона",
|
|
228
|
+
"compile the tex and screenshot the pages so I can read them",
|
|
229
|
+
"сборка падает на шрифтах, а мне нужен свежий pdf",
|
|
230
|
+
],
|
|
231
|
+
collides: ["submit-paper"],
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
skill: "research-ideate",
|
|
235
|
+
why: "is this idea WORTH doing — go/no-go before any effort",
|
|
236
|
+
prompts: [
|
|
237
|
+
"есть идея — замерить, как часто агенты молча игнорируют правила из CLAUDE.md. стоит ли вообще за неё браться",
|
|
238
|
+
"это тянет на публикацию или это блог-пост",
|
|
239
|
+
"is there a fast MVP finding here that does not need a scary result",
|
|
240
|
+
"думаю переключиться на бенчмарк промпт-инъекций в MCP-серверах — не уведёт ли это нас из нашей линии в сторону",
|
|
241
|
+
],
|
|
242
|
+
collides: ["map-prior-work", "sweep-design-space"],
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
skill: "study-accepted-papers",
|
|
246
|
+
why: "mine the VENUE's accepted corpus for what makes papers strong there",
|
|
247
|
+
prompts: [
|
|
248
|
+
"посмотри что принимали на этой площадке и чем те статьи сильны",
|
|
249
|
+
"хочу дотянуть с accept до strong accept — что для этого нужно именно там",
|
|
250
|
+
"read a dozen accepted papers from this venue and diff our draft against them",
|
|
251
|
+
"какие приёмы у них заходят — артефакты, threat model, запоминающееся название",
|
|
252
|
+
],
|
|
253
|
+
collides: ["find-venue", "harden-paper"],
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
skill: "submit-paper",
|
|
257
|
+
why: "the actual upload — artifact hosting, HotCRP, double-blind hygiene",
|
|
258
|
+
prompts: [
|
|
259
|
+
"пора загружать, проведи по шагам",
|
|
260
|
+
"как захостить артефакт анонимно чтобы не спалить авторство",
|
|
261
|
+
"walk me through the hotcrp form and the double blind checks",
|
|
262
|
+
"в pdf не осталось ли моего имени в метаданных",
|
|
263
|
+
],
|
|
264
|
+
collides: ["camera-ready", "harden-paper"],
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
skill: "sweep-design-space",
|
|
268
|
+
why: "GENERATE mechanisms — when the last three ideas all rhymed",
|
|
269
|
+
prompts: [
|
|
270
|
+
"твои варианты стухли, предложи что-то из другой оперы",
|
|
271
|
+
"мы третий раз крутим одни и те же два решения",
|
|
272
|
+
"sweep the design space properly — type systems, capabilities, other professions",
|
|
273
|
+
"нужен механизм, а не ещё один замер того же самого",
|
|
274
|
+
],
|
|
275
|
+
collides: ["research-ideate"],
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
// ── NEW 2026-08-11 (second batch — the three the coverage sweep found) ───────
|
|
279
|
+
// These finish the paper lane. Same rule as the batch above: never run, so
|
|
280
|
+
// their rates are UNKNOWN, not assumed good.
|
|
281
|
+
{
|
|
282
|
+
skill: "paper-status",
|
|
283
|
+
why: "REPORT state — measured page count, git, which gates ran. Reports; does not grade or fix",
|
|
284
|
+
prompts: [
|
|
285
|
+
"что там по статье, что осталось",
|
|
286
|
+
"готова ли статья к сабмиту или ещё нет",
|
|
287
|
+
"what's the status of the paper right now",
|
|
288
|
+
"я вернулся после недели, напомни где мы остановились",
|
|
289
|
+
],
|
|
290
|
+
// harden-paper is the sharpest collision in the corpus: both answer a
|
|
291
|
+
// question shaped like "is it ready?", but one MEASURES and the other JUDGES.
|
|
292
|
+
// If the selector cannot separate these two, a status question triggers a
|
|
293
|
+
// 36-minute gate run.
|
|
294
|
+
collides: ["harden-paper", "paper-pipeline"],
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
skill: "osf-artifact-upload",
|
|
298
|
+
why: "PUSH a file to the OSF project over the API — the mechanics, not the decision to submit",
|
|
299
|
+
prompts: [
|
|
300
|
+
"залей новый artifact.zip на osf",
|
|
301
|
+
"я починил README в артефакте, нужно обновить версию на osf",
|
|
302
|
+
"replace the artifact file on the OSF project via the api",
|
|
303
|
+
"рецензентам нужна свежая версия артефакта по той же view-only ссылке",
|
|
304
|
+
],
|
|
305
|
+
collides: ["submit-paper"],
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
skill: "paper-pipeline",
|
|
309
|
+
why: "DRIVE the whole lifecycle — the conductor, when the ask is the whole arc not one step",
|
|
310
|
+
prompts: [
|
|
311
|
+
"хочу довести статью от идеи до принятия, веди меня по всему процессу",
|
|
312
|
+
"с чего вообще начинать новую статью",
|
|
313
|
+
"run the whole paper pipeline for this idea, not just one stage",
|
|
314
|
+
"непонятно в каком порядке всё это делать и что от чего зависит",
|
|
315
|
+
],
|
|
316
|
+
collides: ["paper-status", "plan-paper-timeline"],
|
|
317
|
+
},
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
// ═════════════════════════════════════════════════════════════════════════════════════════════
|
|
321
|
+
// THE CONSUMER'S OWN CASES — A FIFTH CARRIER, NOT A FORK (2026-09-12)
|
|
322
|
+
//
|
|
323
|
+
// The table above covers THIS PACKAGE'S skills. A consumer installs the package alongside skills
|
|
324
|
+
// of its own, and those collide with each other far harder than the paper skills do: the first
|
|
325
|
+
// consumer's three non-paper cases share the very wording of the request («write a message…»),
|
|
326
|
+
// which is exactly the confusion a trigger measurement exists to expose. Dropping them would not
|
|
327
|
+
// make the measurement smaller, it would make it WRONG — `irrelevantFor()` builds each case's
|
|
328
|
+
// false-positive set out of its colliders, so a missing collider silently turns a precision
|
|
329
|
+
// measurement into a recall measurement.
|
|
330
|
+
//
|
|
331
|
+
// 🔴 AND THEY CANNOT SIMPLY BE CARRIED HERE: the first consumer's cases name private skills and
|
|
332
|
+
// quote private prose. A package that ships one user's private vocabulary has one possible user —
|
|
333
|
+
// the same argument that moved `papersRoot()`, `ledgerPath()`, `citeChecks` and `scriptsRoot()`
|
|
334
|
+
// out of the code and into a declaration. This is the fifth of those carriers and reads the same
|
|
335
|
+
// key from the same file.
|
|
336
|
+
//
|
|
337
|
+
// // <consumer>/package.json
|
|
338
|
+
// "paperlint": { "triggerCases": ".claude/lib/skill-trigger-cases.local.mjs" }
|
|
339
|
+
//
|
|
340
|
+
// The module it names must export `CASES` in the shape documented at the top of this file.
|
|
341
|
+
//
|
|
342
|
+
// ⚠️ DECLARED-AND-MISSING THROWS; UNDECLARED IS SILENT. A consumer with no extra skills is the
|
|
343
|
+
// normal case and must not be nagged. A consumer that declared a path and typoed it is a
|
|
344
|
+
// keystroke away from measuring precision against half a corpus and never being told — the same
|
|
345
|
+
// distinction `scriptsRoot()` makes between `undefined` and `null`.
|
|
346
|
+
//
|
|
347
|
+
// ⚠️ A CONSUMER MAY NOT REDEFINE A PACKAGE CASE. Two tables answering "what should fire on this
|
|
348
|
+
// prompt" is two truths; the override would live in the consumer and the original would keep
|
|
349
|
+
// looking authoritative here. Throws, naming the skill.
|
|
350
|
+
import { readFileSync } from "node:fs";
|
|
351
|
+
import { join, resolve } from "node:path";
|
|
352
|
+
import { pathToFileURL } from "node:url";
|
|
353
|
+
import {
|
|
354
|
+
CONFIG_KEY,
|
|
355
|
+
consumerRoot,
|
|
356
|
+
settingsOf,
|
|
357
|
+
} from "../skills/paper-pipeline/scripts/consumer.mjs";
|
|
358
|
+
|
|
359
|
+
const DEFAULT_LOCAL_CASES = ".claude/lib/skill-trigger-cases.local.mjs";
|
|
360
|
+
|
|
361
|
+
async function consumerCases() {
|
|
362
|
+
const root = consumerRoot();
|
|
363
|
+
let declared;
|
|
364
|
+
try {
|
|
365
|
+
declared = settingsOf(
|
|
366
|
+
JSON.parse(readFileSync(join(root, "package.json"), "utf8")),
|
|
367
|
+
)?.triggerCases;
|
|
368
|
+
} catch {
|
|
369
|
+
declared = undefined;
|
|
370
|
+
}
|
|
371
|
+
const rel = declared === undefined ? DEFAULT_LOCAL_CASES : declared;
|
|
372
|
+
if (typeof rel !== "string" || rel.length === 0)
|
|
373
|
+
throw new TypeError(
|
|
374
|
+
`${CONFIG_KEY}: "triggerCases" must be a non-empty string, got ${JSON.stringify(rel)}`,
|
|
375
|
+
);
|
|
376
|
+
const abs = resolve(root, rel);
|
|
377
|
+
let mod;
|
|
378
|
+
try {
|
|
379
|
+
mod = await import(pathToFileURL(abs).href);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
if (declared === undefined && e?.code === "ERR_MODULE_NOT_FOUND") return [];
|
|
382
|
+
throw new Error(
|
|
383
|
+
`${CONFIG_KEY}: could not load the consumer's trigger cases from ${abs}` +
|
|
384
|
+
(declared === undefined
|
|
385
|
+
? ` (the default location; declare another in package.json under ` +
|
|
386
|
+
`"${CONFIG_KEY}": { "triggerCases": … } if the file lives elsewhere).`
|
|
387
|
+
: ` — it is declared in package.json as "triggerCases": ${JSON.stringify(declared)}.`) +
|
|
388
|
+
`
|
|
389
|
+
A missing case set does not shrink the measurement, it CHANGES it: ` +
|
|
390
|
+
`\`irrelevantFor()\` builds the false-positive set out of a case's colliders, so an ` +
|
|
391
|
+
`absent collider turns a precision number into a recall number with no sign that it did.` +
|
|
392
|
+
`
|
|
393
|
+
${String(e?.message ?? e)}`,
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
const extra = mod?.CASES;
|
|
397
|
+
if (!Array.isArray(extra))
|
|
398
|
+
throw new TypeError(
|
|
399
|
+
`${CONFIG_KEY}: ${abs} must export an array named CASES`,
|
|
400
|
+
);
|
|
401
|
+
const mine = new Set(PACKAGE_CASES.map((c) => c.skill));
|
|
402
|
+
for (const c of extra)
|
|
403
|
+
if (mine.has(c.skill))
|
|
404
|
+
throw new Error(
|
|
405
|
+
`${CONFIG_KEY}: ${abs} redefines the case for "${c.skill}", which this package already ` +
|
|
406
|
+
`owns. Two tables answering the same question is two truths; rename the skill or drop ` +
|
|
407
|
+
`the local case.`,
|
|
408
|
+
);
|
|
409
|
+
return extra;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/** This package's cases plus the consumer's own, as one table. */
|
|
413
|
+
export const CASES = [...PACKAGE_CASES, ...(await consumerCases())];
|
|
414
|
+
|
|
415
|
+
/** Case lookup by skill name — the colocated files' entry point. */
|
|
416
|
+
export const BY_SKILL = new Map(CASES.map((c) => [c.skill, c]));
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* The irrelevant set for a case: its colliders' should-fire prompts, sliced so no
|
|
420
|
+
* two cases receive an identical set. Near-duplicate sets pass the per-set
|
|
421
|
+
* diversity gate while making two cases' false-positive rates the same
|
|
422
|
+
* measurement twice.
|
|
423
|
+
*/
|
|
424
|
+
export function irrelevantFor(skill, want = 4) {
|
|
425
|
+
const c = BY_SKILL.get(skill);
|
|
426
|
+
if (!c) throw new Error(`unknown skill: ${skill}`);
|
|
427
|
+
// Take enough from EACH collider to reach `want` in total. Fixed 2026-08-11:
|
|
428
|
+
// this used to take a flat 2 per collider, which is 4 for a two-collider case
|
|
429
|
+
// and only 2 for a one-collider case — and the diversity gate needs at least
|
|
430
|
+
// `minPrompts` (4) in BOTH sets. Every one-collider skill therefore threw
|
|
431
|
+
// instead of measuring: map-prior-work, paper-adversarial-review,
|
|
432
|
+
// pc-panel-review, plan-paper-timeline, render-paper, sweep-design-space,
|
|
433
|
+
// verify-citations — seven of twenty-one, exactly the set with `collides.length
|
|
434
|
+
// === 1`. Two-collider cases are unaffected (ceil(4/2) === 2), so numbers
|
|
435
|
+
// measured before the fix stay comparable.
|
|
436
|
+
const per = Math.ceil(want / c.collides.length);
|
|
437
|
+
return c.collides
|
|
438
|
+
.flatMap((sib, i) => {
|
|
439
|
+
const s = BY_SKILL.get(sib);
|
|
440
|
+
if (!s) throw new Error(`${skill} collides with unknown skill "${sib}"`);
|
|
441
|
+
// Rotate by the collider's index so two cases sharing a collider do not
|
|
442
|
+
// receive byte-identical irrelevant sets.
|
|
443
|
+
return [...s.prompts.slice(i), ...s.prompts.slice(0, i)].slice(0, per);
|
|
444
|
+
})
|
|
445
|
+
.slice(0, want);
|
|
446
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* skill-trigger-cases.mutations.mjs — the non-vacuity proof for the carrier harness.
|
|
3
|
+
*
|
|
4
|
+
* Run: `node lib/skill-trigger-cases.mutations.mjs`
|
|
5
|
+
*
|
|
6
|
+
* Every case here removes ONE property the harness claims to hold and requires the harness to
|
|
7
|
+
* name that property rather than merely go red. Written with the carrier, not after it: a harness
|
|
8
|
+
* whose success state is a single printed line cannot be observed working, and this package's own
|
|
9
|
+
* `scripts/run-mutations.mjs` refuses a harness no battery can kill for exactly that reason.
|
|
10
|
+
*/
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { runMutations } from "./mutation-driver.mjs";
|
|
14
|
+
import { consumerRoot } from "../skills/paper-pipeline/scripts/consumer.mjs";
|
|
15
|
+
|
|
16
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const SRC = join(HERE, "skill-trigger-cases.mjs");
|
|
18
|
+
const HARNESS = join(HERE, "skill-trigger-cases.harness.mjs");
|
|
19
|
+
|
|
20
|
+
const MUTATIONS = [
|
|
21
|
+
[
|
|
22
|
+
"a typoed declaration falls back to the default instead of throwing",
|
|
23
|
+
[
|
|
24
|
+
[
|
|
25
|
+
SRC,
|
|
26
|
+
'if (declared === undefined && e?.code === "ERR_MODULE_NOT_FOUND") return [];',
|
|
27
|
+
'if (e?.code === "ERR_MODULE_NOT_FOUND") return [];',
|
|
28
|
+
],
|
|
29
|
+
],
|
|
30
|
+
"a typoed declaration loaded quietly",
|
|
31
|
+
"the undeclared/declared distinction — a mistyped path becomes a silently halved corpus",
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"the consumer may shadow a case this package owns",
|
|
35
|
+
[[SRC, "if (mine.has(c.skill))", "if (false && mine.has(c.skill))"]],
|
|
36
|
+
"a shadowing case was accepted",
|
|
37
|
+
"the one-truth rule: two tables answer «what should fire here» and the package's keeps looking authoritative",
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
"the consumer's cases are dropped entirely",
|
|
41
|
+
[
|
|
42
|
+
[
|
|
43
|
+
SRC,
|
|
44
|
+
"export const CASES = [...PACKAGE_CASES, ...(await consumerCases())];",
|
|
45
|
+
"export const CASES = [...PACKAGE_CASES];",
|
|
46
|
+
],
|
|
47
|
+
],
|
|
48
|
+
"the file at the default location was not merged",
|
|
49
|
+
"the merge itself — every consumer measures precision against the package's skills alone",
|
|
50
|
+
],
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
process.exit(
|
|
54
|
+
runMutations({
|
|
55
|
+
root: consumerRoot(),
|
|
56
|
+
runner: "vigiles",
|
|
57
|
+
cases: MUTATIONS.map(([name, edits, expect, disables]) => ({
|
|
58
|
+
name,
|
|
59
|
+
disables,
|
|
60
|
+
edits,
|
|
61
|
+
harness: HARNESS,
|
|
62
|
+
expect,
|
|
63
|
+
})),
|
|
64
|
+
}),
|
|
65
|
+
);
|