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