paperlint 3.2.0 → 4.1.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/workflows/ci.yml +16 -23
- package/CLAUDE.md +33 -13
- package/CONTRIBUTING.md +23 -7
- package/README.md +11 -8
- package/dist/adapters/banal/failure.d.ts +1 -7
- package/dist/adapters/banal/failure.d.ts.map +1 -1
- package/dist/adapters/banal/failure.js +5 -7
- package/dist/adapters/banal/failure.js.map +1 -1
- package/dist/adapters/banal/index.d.ts.map +1 -1
- package/dist/adapters/banal/index.js +8 -11
- package/dist/adapters/banal/index.js.map +1 -1
- package/dist/adapters/banal/install.d.ts.map +1 -1
- package/dist/adapters/banal/install.js +4 -3
- package/dist/adapters/banal/install.js.map +1 -1
- package/dist/adapters/banal/invocation.d.ts +10 -5
- package/dist/adapters/banal/invocation.d.ts.map +1 -1
- package/dist/adapters/banal/invocation.js +13 -1
- package/dist/adapters/banal/invocation.js.map +1 -1
- package/dist/adapters/banal/locate.d.ts +12 -9
- package/dist/adapters/banal/locate.d.ts.map +1 -1
- package/dist/adapters/banal/locate.js +19 -12
- package/dist/adapters/banal/locate.js.map +1 -1
- package/dist/adapters/banal/run.d.ts +10 -1
- package/dist/adapters/banal/run.d.ts.map +1 -1
- package/dist/adapters/banal/run.js +8 -4
- package/dist/adapters/banal/run.js.map +1 -1
- package/dist/adapters/banal/settings.d.ts +1 -1
- package/dist/adapters/banal/settings.d.ts.map +1 -1
- package/dist/adapters/banal/settings.js +2 -1
- package/dist/adapters/banal/settings.js.map +1 -1
- package/dist/adapters/latex/document-class.d.ts +22 -0
- package/dist/adapters/latex/document-class.d.ts.map +1 -0
- package/dist/adapters/latex/document-class.js +102 -0
- package/dist/adapters/latex/document-class.js.map +1 -0
- package/dist/adapters/latex/hidden.d.ts +16 -0
- package/dist/adapters/latex/hidden.d.ts.map +1 -0
- package/dist/adapters/latex/hidden.js +49 -0
- package/dist/adapters/latex/hidden.js.map +1 -0
- package/dist/adapters/latex/index.d.ts +29 -0
- package/dist/adapters/latex/index.d.ts.map +1 -0
- package/dist/adapters/latex/index.js +18 -0
- package/dist/adapters/latex/index.js.map +1 -0
- package/dist/adapters/latex/nodes.d.ts +54 -0
- package/dist/adapters/latex/nodes.d.ts.map +1 -0
- package/dist/adapters/latex/nodes.js +93 -0
- package/dist/adapters/latex/nodes.js.map +1 -0
- package/dist/adapters/latex/outline.d.ts +10 -0
- package/dist/adapters/latex/outline.d.ts.map +1 -0
- package/dist/adapters/latex/outline.js +39 -0
- package/dist/adapters/latex/outline.js.map +1 -0
- package/dist/adapters/latex/parse.d.ts +42 -0
- package/dist/adapters/latex/parse.d.ts.map +1 -0
- package/dist/adapters/latex/parse.js +94 -0
- package/dist/adapters/latex/parse.js.map +1 -0
- package/dist/adapters/latex/rendered.d.ts +10 -0
- package/dist/adapters/latex/rendered.d.ts.map +1 -0
- package/dist/adapters/latex/rendered.js +39 -0
- package/dist/adapters/latex/rendered.js.map +1 -0
- package/dist/adapters/memory/index.d.ts.map +1 -1
- package/dist/adapters/memory/index.js +8 -2
- package/dist/adapters/memory/index.js.map +1 -1
- package/dist/adapters/node/process.io.d.ts +6 -3
- package/dist/adapters/node/process.io.d.ts.map +1 -1
- package/dist/adapters/node/process.io.js.map +1 -1
- package/dist/adapters/node/workspace.io.d.ts.map +1 -1
- package/dist/adapters/node/workspace.io.js +4 -2
- package/dist/adapters/node/workspace.io.js.map +1 -1
- package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
- package/dist/adapters/pdfjs/fill.js +12 -12
- package/dist/adapters/pdfjs/fill.js.map +1 -1
- package/dist/adapters/references/index.d.ts.map +1 -1
- package/dist/adapters/references/index.js +4 -2
- package/dist/adapters/references/index.js.map +1 -1
- package/dist/build-engine.d.ts +1 -1
- package/dist/build-engine.d.ts.map +1 -1
- package/dist/build-engine.js +8 -1
- package/dist/build-engine.js.map +1 -1
- package/dist/build.d.ts +2 -3
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +9 -10
- package/dist/build.js.map +1 -1
- package/dist/caller-path.d.ts +3 -0
- package/dist/caller-path.d.ts.map +1 -0
- package/dist/caller-path.js +13 -0
- package/dist/caller-path.js.map +1 -0
- package/dist/cli.d.ts +10 -17
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +91 -17
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +12 -3
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +2 -1
- package/dist/doctor.js.map +1 -1
- package/dist/domain/paths.d.ts +8 -2
- package/dist/domain/paths.d.ts.map +1 -1
- package/dist/domain/paths.js +12 -1
- package/dist/domain/paths.js.map +1 -1
- package/dist/domain/ready.d.ts +24 -0
- package/dist/domain/ready.d.ts.map +1 -0
- package/dist/domain/ready.js +11 -0
- package/dist/domain/ready.js.map +1 -0
- package/dist/domain/record.d.ts +8 -0
- package/dist/domain/record.d.ts.map +1 -0
- package/dist/domain/record.js +8 -0
- package/dist/domain/record.js.map +1 -0
- package/dist/domain/sha256.d.ts.map +1 -1
- package/dist/domain/sha256.js +4 -2
- package/dist/domain/sha256.js.map +1 -1
- package/dist/domain/tex-document.d.ts +84 -0
- package/dist/domain/tex-document.d.ts.map +1 -0
- package/dist/domain/tex-document.js +43 -0
- package/dist/domain/tex-document.js.map +1 -0
- package/dist/engine.d.ts +23 -22
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js.map +1 -1
- package/dist/eslint-rules/bib-reachable-entry.d.ts +1 -1
- package/dist/eslint-rules/bib-reachable-entry.js.map +1 -1
- package/dist/eslint-rules/install-path-literals.d.ts +2 -2
- package/dist/eslint-rules/install-path-literals.js.map +1 -1
- package/dist/eslint-rules/paper-research-question.d.ts +1 -1
- package/dist/eslint-rules/paper-research-question.js.map +1 -1
- package/dist/eslint-rules/paper-stages.d.ts +2 -2
- package/dist/eslint-rules/paper-stages.js.map +1 -1
- package/dist/eslint-rules/paper-typography.d.ts +6 -6
- package/dist/eslint-rules/paper-typography.js.map +1 -1
- package/dist/eslint-rules/pdf-last-page-balance.d.ts +1 -1
- package/dist/eslint-rules/pdf-last-page-balance.js.map +1 -1
- package/dist/eslint-rules/review-frontmatter.d.ts +2 -2
- package/dist/eslint-rules/review-frontmatter.js.map +1 -1
- package/dist/eslint-rules/sibling-frontmatter.d.ts +1 -1
- package/dist/eslint-rules/sibling-frontmatter.d.ts.map +1 -1
- package/dist/eslint-rules/temp-root-realpath.d.ts +1 -1
- package/dist/eslint-rules/temp-root-realpath.js.map +1 -1
- package/dist/eslint-rules/tex-build.d.ts +2 -2
- package/dist/eslint-rules/tex-build.js.map +1 -1
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +31 -28
- package/dist/facts-file.js.map +1 -1
- package/dist/hooks-settings.d.ts.map +1 -1
- package/dist/hooks-settings.js +17 -2
- package/dist/hooks-settings.js.map +1 -1
- package/dist/init.d.ts +3 -4
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +18 -8
- package/dist/init.js.map +1 -1
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +1 -5
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/new-paper.d.ts +5 -0
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +8 -1
- package/dist/new-paper.js.map +1 -1
- package/dist/package-dirs.d.ts +5 -0
- package/dist/package-dirs.d.ts.map +1 -0
- package/dist/package-dirs.js +14 -0
- package/dist/package-dirs.js.map +1 -0
- package/dist/paper-files.d.ts +4 -4
- package/dist/paper-files.d.ts.map +1 -1
- package/dist/paper-files.js +6 -6
- package/dist/paper-files.js.map +1 -1
- package/dist/paper-settings.js +3 -3
- package/dist/paper-settings.js.map +1 -1
- package/dist/pdf-facts.d.ts +51 -1
- package/dist/pdf-facts.d.ts.map +1 -1
- package/dist/pdf-facts.js +23 -15
- package/dist/pdf-facts.js.map +1 -1
- package/dist/pdf-geometry.d.ts.map +1 -1
- package/dist/pdf-geometry.js +2 -3
- package/dist/pdf-geometry.js.map +1 -1
- package/dist/ports/latex.d.ts +24 -0
- package/dist/ports/latex.d.ts.map +1 -0
- package/dist/ports/latex.js +2 -0
- package/dist/ports/latex.js.map +1 -0
- package/dist/ports/tool-installer.d.ts +2 -14
- package/dist/ports/tool-installer.d.ts.map +1 -1
- package/dist/presets.d.ts +15 -2
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +35 -10
- package/dist/presets.js.map +1 -1
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +4 -4
- package/dist/references.js.map +1 -1
- package/dist/rules-config.d.ts +26 -1
- package/dist/rules-config.d.ts.map +1 -1
- package/dist/rules-config.js +9 -9
- package/dist/rules-config.js.map +1 -1
- package/dist/tex-requirements.d.ts +15 -0
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +28 -10
- package/dist/tex-requirements.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +83 -0
- package/dist/tex-venue-rules.d.ts.map +1 -0
- package/dist/tex-venue-rules.js +254 -0
- package/dist/tex-venue-rules.js.map +1 -0
- package/dist/types.d.ts +5 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/venue-rules.d.ts +1 -1
- package/dist/venue-rules.d.ts.map +1 -1
- package/dist/venue-rules.js +20 -7
- package/dist/venue-rules.js.map +1 -1
- package/docs/configuration.md +5 -4
- package/docs/e2e.md +69 -40
- package/docs/install.md +1 -1
- package/docs/prior-art/README.md +1 -1
- package/docs/prior-art/package-location.md +5 -5
- package/docs/prior-art/repro/README.md +1 -1
- package/docs/prior-art/test-tooling.md +21 -10
- package/docs/rules/tex/required-section.md +73 -0
- package/docs/rules/tex/template.md +62 -0
- package/docs/rules/tex/venue-leftover.md +71 -0
- package/docs/rules.md +70 -48
- package/docs/testing.md +17 -4
- package/docs/texlive-install-decision.md +1 -1
- package/docs/toolchain.md +2 -2
- package/eslint-rules/bib-reachable-entry.ts +1 -1
- package/eslint-rules/install-path-literals.ts +2 -2
- package/eslint-rules/paper-research-question.ts +1 -1
- package/eslint-rules/paper-stages.ts +2 -2
- package/eslint-rules/paper-typography.ts +2 -2
- package/eslint-rules/pdf-last-page-balance.ts +1 -1
- package/eslint-rules/review-frontmatter.ts +1 -1
- package/eslint-rules/temp-root-realpath.ts +1 -1
- package/eslint-rules/tex-build.ts +2 -2
- package/eslint.config.mjs +162 -15
- package/fixtures/build-e2e/acmart/expect.json +26 -0
- package/fixtures/build-e2e/aidc/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/aidc/expect.json +14 -0
- package/fixtures/build-e2e/aidc/paper.tex +46 -0
- package/fixtures/build-e2e/aidc/paperlint.json +1 -0
- package/fixtures/build-e2e/broken/expect.json +11 -0
- package/fixtures/build-e2e/cite/expect.json +27 -0
- package/fixtures/build-e2e/empty/expect.json +12 -0
- package/fixtures/build-e2e/fallback/expect.json +53 -0
- package/fixtures/build-e2e/guards/expect.json +6 -0
- package/fixtures/build-e2e/no-source/expect.json +10 -0
- package/fixtures/build-e2e/unbalanced/expect.json +60 -0
- package/fixtures/install-path-literals/clean.fixture.mjs +1 -1
- package/fixtures/install-path-literals/clean.md +2 -2
- package/fixtures/install-path-literals/defect.fixture.mjs +1 -1
- package/fixtures/install-path-literals/defect.md +2 -2
- package/fixtures/pdf-facts/README.md +1 -1
- package/fixtures/real-markdown-paper/baseline.ts +1 -1
- package/fixtures/render-paper/build-clean.sh +3 -5
- package/hooks/paper-status-gates.sh +9 -19
- package/lib/paper-config.harness.mjs +1 -1
- package/lib/paper-config.ts +1 -5
- package/lib/skill-checks.mjs +24 -381
- package/lib/skill-checks.test.mjs +63 -115
- package/lib/skill-corpus.mjs +10 -251
- package/lib/skill-corpus.test.mjs +2 -13
- package/lib/skill-trigger-cases.mjs +1 -1
- package/package.json +13 -2
- package/{skills/submit-paper/references/venues → presets}/acm-sigconf.jsonc +4 -1
- package/{skills/submit-paper/references/venues → presets}/agenticdev.jsonc +4 -0
- package/presets/aidc.jsonc +73 -0
- package/{skills/submit-paper/references/venues → presets}/aisec.jsonc +4 -0
- package/presets/ieee-conference.jsonc +66 -0
- package/{skills/submit-paper/references/venues → presets}/realm.jsonc +8 -1
- package/{skills/submit-paper/references/venues → presets/tex}/paper-guards.tex +1 -1
- package/{skills/submit-paper/references/venues → presets}/venue-profile.schema.json +30 -2
- package/scripts/check.harness.ts +64 -10
- package/scripts/check.test.ts +60 -13
- package/scripts/check.ts +83 -30
- package/scripts/coverage-config.test.ts +0 -1
- package/scripts/harness-api.frozen.json +0 -1
- package/scripts/test.test.ts +1 -1
- package/scripts/test.ts +1 -1
- package/skills/analyze-sibling-paper/SKILL.md +1 -39
- package/skills/analyze-sibling-paper/SKILL.md.spec.ts +0 -38
- package/skills/argument-arc/SKILL.md +2 -36
- package/skills/argument-arc/SKILL.md.spec.ts +1 -43
- package/skills/build-benchmark/SKILL.md +1 -41
- package/skills/build-benchmark/SKILL.md.spec.ts +0 -40
- package/skills/camera-ready/SKILL.md +1 -34
- package/skills/camera-ready/SKILL.md.spec.ts +0 -33
- package/skills/cold-read-diff/SKILL.md +1 -35
- package/skills/cold-read-diff/SKILL.md.spec.ts +0 -34
- package/skills/draft-paper/SKILL.md +2 -41
- package/skills/draft-paper/SKILL.md.spec.ts +1 -50
- package/skills/extend-paper/SKILL.md +2 -33
- package/skills/extend-paper/SKILL.md.spec.ts +1 -42
- package/skills/find-venue/SKILL.md +2 -38
- package/skills/find-venue/SKILL.md.spec.ts +1 -47
- package/skills/grade-paper-writing/SKILL.md +3 -38
- package/skills/grade-paper-writing/SKILL.md.spec.ts +2 -47
- package/skills/grade-paper-writing/prose-lint.mjs +2 -3
- package/skills/grade-paper-writing/prose-lint.test.ts +1 -1
- package/skills/harden-paper/SKILL.md +1 -39
- package/skills/harden-paper/SKILL.md.spec.ts +0 -38
- package/skills/map-prior-work/SKILL.md +1 -35
- package/skills/map-prior-work/SKILL.md.spec.ts +0 -34
- package/skills/osf-artifact-upload/osf-artifact-upload.harness.ts +3 -4
- package/skills/paper-adversarial-review/SKILL.md +2 -35
- package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -43
- package/skills/paper-pipeline/PIPELINE-MAP.md +2 -2
- package/skills/paper-pipeline/SKILL.md +3 -29
- package/skills/paper-pipeline/SKILL.md.spec.ts +2 -28
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1 -1
- package/skills/paper-pipeline/paper-pipeline.harness.mjs +25 -40
- package/skills/paper-pipeline/references/acceptance-gate.md +1 -6
- package/skills/paper-pipeline/references/pipeline-status-template.md +8 -35
- package/skills/paper-pipeline/scripts/README.md +30 -225
- package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +4 -8
- package/skills/paper-pipeline/scripts/consumer.d.mts +0 -2
- package/skills/paper-pipeline/scripts/consumer.harness.mjs +6 -104
- package/skills/paper-pipeline/scripts/consumer.mjs +24 -119
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +2 -3
- package/skills/paper-pipeline/scripts/population-map.harness.mjs +3 -3
- package/skills/paper-status/SKILL.md +2 -42
- package/skills/paper-status/SKILL.md.spec.ts +1 -41
- package/skills/pc-panel-review/SKILL.md +2 -46
- package/skills/pc-panel-review/SKILL.md.spec.ts +1 -45
- package/skills/plan-paper-timeline/SKILL.md +2 -36
- package/skills/plan-paper-timeline/SKILL.md.spec.ts +0 -36
- package/skills/render-paper/SKILL.md +2 -38
- package/skills/render-paper/SKILL.md.spec.ts +1 -37
- package/skills/render-paper/check-render.sh +16 -63
- package/skills/render-paper/render-paper.harness.mjs +17 -59
- package/skills/research-ideate/SKILL.md +2 -39
- package/skills/research-ideate/SKILL.md.spec.ts +1 -47
- package/skills/study-accepted-papers/SKILL.md +1 -34
- package/skills/study-accepted-papers/SKILL.md.spec.ts +0 -33
- package/skills/submit-paper/SKILL.md +1 -33
- package/skills/submit-paper/SKILL.md.spec.ts +0 -32
- package/skills/sweep-design-space/SKILL.md +1 -38
- package/skills/sweep-design-space/SKILL.md.spec.ts +0 -37
- package/skills/tighten-paper/SKILL.md +2 -39
- package/skills/tighten-paper/SKILL.md.spec.ts +1 -47
- package/skills/tighten-paper/structure.mjs +4 -11
- package/skills/verify-citations/SKILL.md +2 -38
- package/skills/verify-citations/SKILL.md.spec.ts +1 -37
- package/src/adapters/banal/failure.ts +9 -10
- package/src/adapters/banal/index.test.ts +3 -3
- package/src/adapters/banal/index.ts +8 -10
- package/src/adapters/banal/install.ts +9 -4
- package/src/adapters/banal/invocation.test.ts +20 -8
- package/src/adapters/banal/invocation.ts +24 -9
- package/src/adapters/banal/locate.test.ts +2 -2
- package/src/adapters/banal/locate.ts +27 -21
- package/src/adapters/banal/output.test.ts +1 -1
- package/src/adapters/banal/run.test.ts +3 -3
- package/src/adapters/banal/run.ts +16 -10
- package/src/adapters/banal/settings.ts +2 -2
- package/src/adapters/banal/xml.test.ts +1 -1
- package/src/adapters/curl/download.test.ts +4 -4
- package/src/adapters/latex/document-class.ts +147 -0
- package/src/adapters/latex/hidden.ts +70 -0
- package/src/adapters/latex/index.test.ts +361 -0
- package/src/adapters/latex/index.ts +55 -0
- package/src/adapters/latex/nodes.ts +141 -0
- package/src/adapters/latex/outline.ts +64 -0
- package/src/adapters/latex/parse.ts +136 -0
- package/src/adapters/latex/rendered.ts +59 -0
- package/src/adapters/memory/index.ts +4 -3
- package/src/adapters/node/files.test.ts +5 -3
- package/src/adapters/node/process.io.ts +9 -2
- package/src/adapters/node/process.test.ts +4 -4
- package/src/adapters/node/workspace.io.ts +9 -4
- package/src/adapters/pdfjs/fill.test.ts +1 -1
- package/src/adapters/pdfjs/fill.ts +18 -10
- package/src/adapters/references/index.ts +7 -2
- package/src/build-engine.test.ts +11 -6
- package/src/build-engine.ts +10 -5
- package/src/build.harness.mjs +5 -7
- package/src/build.test.ts +10 -11
- package/src/build.ts +12 -13
- package/src/caller-path.ts +13 -0
- package/src/cli.harness.mjs +1 -3
- package/src/cli.test.ts +21 -16
- package/src/cli.ts +115 -33
- package/src/doctor.test.ts +1 -1
- package/src/doctor.ts +14 -5
- package/src/domain/paths.test.ts +15 -0
- package/src/domain/paths.ts +20 -1
- package/src/domain/ready.ts +31 -0
- package/src/domain/record.test.ts +20 -0
- package/src/domain/record.ts +12 -0
- package/src/domain/sha256.ts +5 -3
- package/src/domain/tex-document.test.ts +80 -0
- package/src/domain/tex-document.ts +110 -0
- package/src/engine.harness.mjs +1 -1
- package/src/engine.ts +30 -2
- package/src/facts-file.test.ts +4 -7
- package/src/facts-file.ts +45 -30
- package/src/hooks-settings.harness.ts +17 -0
- package/src/hooks-settings.ts +28 -4
- package/src/init.test.ts +25 -5
- package/src/init.ts +26 -12
- package/src/latex-loop.harness.ts +1 -1
- package/src/new-paper.harness.mjs +7 -23
- package/src/new-paper.test.ts +28 -3
- package/src/new-paper.ts +15 -3
- package/src/package-dirs.ts +17 -0
- package/src/paper-files.test.ts +22 -19
- package/src/paper-files.ts +16 -27
- package/src/paper-settings-commands.test.ts +6 -1
- package/src/paper-settings.test.ts +2 -2
- package/src/paper-settings.ts +5 -5
- package/src/pdf-facts.test.ts +16 -5
- package/src/pdf-facts.ts +79 -22
- package/src/pdf-geometry.ts +5 -3
- package/src/ports/latex.ts +29 -0
- package/src/ports/tool-installer.ts +2 -17
- package/src/presets.test.ts +65 -4
- package/src/presets.ts +65 -28
- package/src/references.test.ts +25 -19
- package/src/references.ts +4 -5
- package/src/rule-cases.test.ts +474 -0
- package/src/rule-docs.test.ts +159 -0
- package/src/rules-config.ts +40 -11
- package/src/tex-requirements.harness.ts +13 -23
- package/src/tex-requirements.test.ts +21 -0
- package/src/tex-requirements.ts +64 -14
- package/src/tex-venue-rules.test.ts +659 -0
- package/src/tex-venue-rules.ts +429 -0
- package/src/toolchain.harness.mjs +1 -1
- package/src/toolchain.test.ts +9 -5
- package/src/toolchain.ts +2 -2
- package/src/types.ts +5 -3
- package/src/venue-rules.test.ts +104 -8
- package/src/venue-rules.ts +22 -12
- package/templates/paper/paper.tex +2 -1
- package/skills/paper-pipeline/scripts/announce.mjs +0 -67
- package/skills/paper-pipeline/scripts/announce.test.mjs +0 -102
- package/skills/paper-pipeline/scripts/fixtures/clean/PIPELINE-STATUS.md +0 -51
- package/skills/paper-pipeline/scripts/fixtures/dirty/PIPELINE-STATUS.md +0 -52
- package/skills/paper-pipeline/scripts/fixtures/dirty/paper.md +0 -6
- package/skills/paper-pipeline/scripts/fixtures/scorecard.ts +0 -100
- package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +0 -302
- package/skills/paper-pipeline/scripts/ledger.mjs +0 -623
- package/skills/paper-pipeline/scripts/ledger.test.mjs +0 -254
- package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +0 -474
- package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +0 -328
- package/skills/paper-pipeline/scripts/pipeline-check.mjs +0 -750
- package/skills/paper-pipeline/scripts/pipeline-edges.mjs +0 -169
- package/skills/paper-pipeline/scripts/pipeline-edges.test.mjs +0 -73
- package/skills/paper-pipeline/scripts/run-mechanical.mjs +0 -648
- package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +0 -468
- package/skills/paper-pipeline/scripts/status.mjs +0 -295
- package/skills/paper-pipeline/scripts/status.test.mjs +0 -232
- /package/{skills/submit-paper/references/venues → presets/tex}/agenticdev.tex +0 -0
- /package/{skills/submit-paper/references/venues → presets}/tex-base.jsonc +0 -0
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pipeline-check.harness.mjs — one planted defect at a time, on an otherwise-clean scorecard.
|
|
3
|
-
*
|
|
4
|
-
* 🔴 Since 2026-08-26 HERE ARE SIX CHECKS, NOT TWENTY-TWO. Sixteen, whose input is the document itself,
|
|
5
|
-
* moved to `eslint-rules/pipeline-status.mjs`, and their cases — to `eslint-rules/pipeline-status.harness.mjs`.
|
|
6
|
-
* `npx vigiles test .claude/skills/paper-pipeline/scripts/pipeline-check.harness.mjs`.
|
|
7
|
-
*
|
|
8
|
-
* WHY THIS EXISTS ALONGSIDE THE FIXTURE TEST IN hooks.harness.ts. That one runs the checker over
|
|
9
|
-
* `scripts/fixtures/dirty/`, a scorecard carrying every defect at once, and asserts each kind
|
|
10
|
-
* appears somewhere in the output. It cannot answer the question that matters when a check breaks:
|
|
11
|
-
* WHICH defect produced WHICH finding. A checker that reports `stale-continuous` for the wrong
|
|
12
|
-
* reason — say, because the date parser returns null and every row looks undated — passes that test
|
|
13
|
-
* forever. So each case below plants exactly ONE defect on a scorecard that is otherwise silent, and
|
|
14
|
-
* asserts the FULL SET of kinds, not merely that the expected one is present. Collateral findings
|
|
15
|
-
* are written into the expectation on purpose: they are part of the contract, and an unlisted one is
|
|
16
|
-
* a change in behaviour nobody asked for.
|
|
17
|
-
*
|
|
18
|
-
* 🔴 Assertions run at MODULE TOP LEVEL. `vigiles test` imports the file and treats "did not throw"
|
|
19
|
-
* as a pass — an earlier harness here exported a `tests` object, nothing ran, and the runner printed
|
|
20
|
-
* ✓ on a file whose only assertion was `assert.equal(1, 2)`.
|
|
21
|
-
*
|
|
22
|
-
* 🔴 The subprocess environment is SCRUBBED of OSF_TOKEN and GITHUB_TOKEN. The `credential-available`
|
|
23
|
-
* check fires when the session holds a credential that could clear a parked blocker, so with either
|
|
24
|
-
* token exported this suite would pass on a laptop and fail in CI, or the reverse. A test whose
|
|
25
|
-
* verdict depends on who is running it is not a test.
|
|
26
|
-
*
|
|
27
|
-
* Fixtures are throwaways in a temp dir; no real scorecard is read or written.
|
|
28
|
-
*/
|
|
29
|
-
import assert from "node:assert/strict";
|
|
30
|
-
import { parseStatus } from "./pipeline-check.mjs";
|
|
31
|
-
import { execFileSync } from "node:child_process";
|
|
32
|
-
import {
|
|
33
|
-
mkdtempSync,
|
|
34
|
-
mkdirSync,
|
|
35
|
-
writeFileSync,
|
|
36
|
-
rmSync,
|
|
37
|
-
realpathSync,
|
|
38
|
-
} from "node:fs";
|
|
39
|
-
import { tmpdir } from "node:os";
|
|
40
|
-
import { join, dirname } from "node:path";
|
|
41
|
-
import { fileURLToPath } from "node:url";
|
|
42
|
-
import { consumerRoot } from "./consumer.mjs";
|
|
43
|
-
import { scorecard as makeScorecard } from "./fixtures/scorecard.ts";
|
|
44
|
-
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
45
|
-
|
|
46
|
-
const ROOT = consumerRoot();
|
|
47
|
-
const SCRIPT = join(HERE, "pipeline-check.mjs");
|
|
48
|
-
const tmp = realpathSync(mkdtempSync(join(tmpdir(), "pipecheck-harness-")));
|
|
49
|
-
|
|
50
|
-
// The paper source is written NOW, so `newestSourceDate` returns today and the staleness comparison
|
|
51
|
-
// has something real to compare against. Every clean row therefore carries today's date: hard-coding
|
|
52
|
-
// a date would make this suite start failing on its own the following morning.
|
|
53
|
-
const TODAY = new Date().toISOString().slice(0, 10);
|
|
54
|
-
|
|
55
|
-
const ENV = { ...process.env };
|
|
56
|
-
delete ENV.OSF_TOKEN;
|
|
57
|
-
delete ENV.GITHUB_TOKEN;
|
|
58
|
-
|
|
59
|
-
const scorecard = (over = {}) => makeScorecard(over, TODAY);
|
|
60
|
-
|
|
61
|
-
/** Write a fixture and return the findings pipeline-check reports, verbatim. */
|
|
62
|
-
function findings(name, over = {}, today = TODAY) {
|
|
63
|
-
const d = join(tmp, name);
|
|
64
|
-
mkdirSync(d, { recursive: true });
|
|
65
|
-
writeFileSync(join(d, "PIPELINE-STATUS.md"), scorecard(over));
|
|
66
|
-
writeFileSync(join(d, "paper.md"), "## 1. Heading\n\nProse.\n");
|
|
67
|
-
const out = execFileSync("node", [SCRIPT, d, "--json", `--today=${today}`], {
|
|
68
|
-
cwd: ROOT,
|
|
69
|
-
encoding: "utf8",
|
|
70
|
-
env: ENV,
|
|
71
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
72
|
-
});
|
|
73
|
-
return JSON.parse(out);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** …and just the kinds, sorted. */
|
|
77
|
-
const kinds = (name, over = {}, today = TODAY) =>
|
|
78
|
-
findings(name, over, today)
|
|
79
|
-
.map((f) => f.kind)
|
|
80
|
-
.sort();
|
|
81
|
-
|
|
82
|
-
/** A SETUP-shaped (7-column) table head. */
|
|
83
|
-
const PLAIN_HEAD = [
|
|
84
|
-
"| id | Work | Skill | Status | Date | Result | Open |",
|
|
85
|
-
"|----|------|-------|--------|------|--------|------|",
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
/** Assert the EXACT set of kinds, so a check firing for the wrong reason cannot hide. */
|
|
89
|
-
const expect = (name, over, want, today = TODAY) =>
|
|
90
|
-
assert.deepEqual(
|
|
91
|
-
kinds(name, over, today),
|
|
92
|
-
[...want].sort(),
|
|
93
|
-
`${name}: wrong finding set`,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// ═══════════════════════════════════════════════════════════════════════════════════════
|
|
97
|
-
// 🔴 2026-08-26 — SIXTEEN CASES MOVED OUT ALONG WITH THEIR CHECKS.
|
|
98
|
-
//
|
|
99
|
-
// Checks whose input is ONE markdown document moved to `eslint-rules/pipeline-status.mjs`,
|
|
100
|
-
// and their cases — to the colocated `eslint-rules/pipeline-status.harness.mjs`. They were NOT
|
|
101
|
-
// left behind even "just in case": a test running a check that is not in the file is always green
|
|
102
|
-
// and therefore lies worse than its absence.
|
|
103
|
-
//
|
|
104
|
-
// undated-continuous · gate-missing-input · gate-stale-input · unknown-input ·
|
|
105
|
-
// unattributed-verdict · single-family-jury (+ mixed-family / non-judging / widened) ·
|
|
106
|
-
// scalar-verdict (+ owned) · study-before-frame · undeclared-input (+ superset) ·
|
|
107
|
-
// unrun-gate · no-verdict · weak-accept-unowned · ceiling-unplanned ·
|
|
108
|
-
// unattributed-row · unreadable-row · duplicate-id
|
|
109
|
-
//
|
|
110
|
-
// Six checks remain, and all six read input FROM OUTSIDE the file: git, clock, `reviews/`,
|
|
111
|
-
// `process.env`. Exactly those are checked below.
|
|
112
|
-
//
|
|
113
|
-
// ⚠️ TWO CASES ABOUT PARSING WERE REWRITTEN, NOT DELETED, and this is more important than keeping them.
|
|
114
|
-
// "Heading with trailing text" and "line `| Id |`" — parser regressions, found live
|
|
115
|
-
// on 2026-08-09, and before they were observed through `unrun-gate`, which no longer exists here. If they
|
|
116
|
-
// had simply been left expecting `[]`, they would have turned green BY CONSTRUCTION: empty set
|
|
117
|
-
// of findings appears both when the parser is right and when it silently ate the table. So both
|
|
118
|
-
// were rewritten to be observed through `stale-continuous` — the check that stayed here:
|
|
119
|
-
// parser did not see section ⇒ no line ⇒ no finding ⇒ assertion is red.
|
|
120
|
-
// ═══════════════════════════════════════════════════════════════════════════════════════
|
|
121
|
-
|
|
122
|
-
// ── 0. the baseline says nothing ───────────────────────────────────────────────────────
|
|
123
|
-
// Asserted first and asserted hard. Every case below is "the baseline plus one thing", so a noisy
|
|
124
|
-
// baseline would make all of them meaningless — and a checker that fires on a clean scorecard is
|
|
125
|
-
// muted within a day, which is worse than one that misses.
|
|
126
|
-
expect("clean", {}, []);
|
|
127
|
-
|
|
128
|
-
// ── 1. stale-continuous — a ☑ about text that has since been rewritten ─────────────────
|
|
129
|
-
// verify-citations was numbered like a one-shot step, so a citation added after the last run counted
|
|
130
|
-
// as verified. The project rule "we checked last cycle does not count" was already written down.
|
|
131
|
-
// INPUT FROM OUTSIDE THE FILE: the date of the last commit that touched the paper's text — that is why the check stayed.
|
|
132
|
-
expect("stale-continuous", { cites: { date: "2020-01-01" } }, [
|
|
133
|
-
"stale-continuous",
|
|
134
|
-
]);
|
|
135
|
-
|
|
136
|
-
// ── 2. submit-access — no portal account inside somebody else's moderation window ──────
|
|
137
|
-
// Found at T−4 days on a finished paper, as the sole item on the critical path: OpenReview profiles
|
|
138
|
-
// are moderated for up to two weeks and there is no expedite route without an institutional email.
|
|
139
|
-
// INPUT FROM OUTSIDE THE FILE: the clock.
|
|
140
|
-
expect(
|
|
141
|
-
"submit-access",
|
|
142
|
-
{ access: { status: "☐" }, deadline: "2026-09-01" },
|
|
143
|
-
["submit-access"],
|
|
144
|
-
"2026-08-20",
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
// ── 3. …and a far deadline with the same blank row is NOT urgent ───────────────────────
|
|
148
|
-
expect("submit-access-not-yet", { access: { status: "☐" } }, []);
|
|
149
|
-
|
|
150
|
-
// ── 4. a history section is evidence, not status ──────────────────────────────────────
|
|
151
|
-
// A superseded 2026-08-02 row saying the artifact was unhosted re-triggered the credential check on
|
|
152
|
-
// 2026-08-05, hours after the artifact went up. This project appends rather than rewrites, so every
|
|
153
|
-
// scorecard accumulates old rows, and parsing them makes every past state live again.
|
|
154
|
-
// Observed through `stale-continuous`: a row in history is dated 2020, and if the history
|
|
155
|
-
// slice did not work, it would have given it.
|
|
156
|
-
expect(
|
|
157
|
-
"history-is-not-status",
|
|
158
|
-
{
|
|
159
|
-
tail: [
|
|
160
|
-
"## History",
|
|
161
|
-
"",
|
|
162
|
-
"### CONTINUOUS",
|
|
163
|
-
...PLAIN_HEAD,
|
|
164
|
-
"| cites | any cite | verify-citations | ☑ | 2020-01-01 | old | — |",
|
|
165
|
-
].join("\n"),
|
|
166
|
-
},
|
|
167
|
-
[],
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
// ── 5. a heading may carry trailing text — the RELAXATION, still observable ────────────
|
|
171
|
-
// The old pattern was `/^###\s+([A-Z]+)\s*$/`: an all-caps Latin word and NOTHING after it. Papers
|
|
172
|
-
// annotate their headings (`### GATES (re-run 06.08)`), so the pattern failed on the real document
|
|
173
|
-
// and the section simply stayed unset — SILENTLY. Planted here as a CONTINUOUS row with an old date:
|
|
174
|
-
// the finding exists only if the annotated heading was recognised as a section.
|
|
175
|
-
expect(
|
|
176
|
-
"heading-with-trailing-text",
|
|
177
|
-
{
|
|
178
|
-
tail: [
|
|
179
|
-
"### CONTINUOUS (re-run 2026-08-09, after the cut)",
|
|
180
|
-
...PLAIN_HEAD,
|
|
181
|
-
"| refs | any ref moved | verify-refs | ☑ | 2020-01-01 | ok | — |",
|
|
182
|
-
].join("\n"),
|
|
183
|
-
},
|
|
184
|
-
["stale-continuous"],
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
// ── 6. the row `| Id |` is a ROW, and the header is whatever `thead` says it is ────────
|
|
188
|
-
// The old parser guessed the header with `/^\|\s*id\s*\|/i`, so the DATA row `| Id | …` — the
|
|
189
|
-
// research-ideate row, before the words-not-codes rename — matched the guess and was eaten on every
|
|
190
|
-
// scorecard in the repo, for as long as the template had existed. A row that parses as nothing, on
|
|
191
|
-
// every paper, forever. Planted as a stale CONTINUOUS row so its absence is visible: if the row were
|
|
192
|
-
// still being swallowed, the finding set would be EMPTY.
|
|
193
|
-
{
|
|
194
|
-
const f = findings("header-lookalike-row", {
|
|
195
|
-
tail: [
|
|
196
|
-
"### CONTINUOUS",
|
|
197
|
-
...PLAIN_HEAD,
|
|
198
|
-
"| Id | Header-lookalike | research-ideate | ☑ | 2020-01-01 | — | — |",
|
|
199
|
-
].join("\n"),
|
|
200
|
-
});
|
|
201
|
-
assert.deepEqual(
|
|
202
|
-
f.map((x) => x.kind),
|
|
203
|
-
["stale-continuous"],
|
|
204
|
-
"header-lookalike-row: wrong finding set",
|
|
205
|
-
);
|
|
206
|
-
assert.match(
|
|
207
|
-
f[0].msg,
|
|
208
|
-
/\bId\b/,
|
|
209
|
-
"header-lookalike-row: the swallowed row is not named in the finding",
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// ── 17. the cold-read report's filename: BOTH live spellings must count ───────────────────────────
|
|
214
|
-
// 2026-08-24: this gate announced "nobody without context has read this text" about a paper that had
|
|
215
|
-
// been cold-read TWICE that day. The report was filed as `…-coldread-worksheet.md`; the pattern knew
|
|
216
|
-
// only `cold-read`. Neither spelling is a typo — the skill is `cold-read-diff` while the scorecard
|
|
217
|
-
// row id, in the very file this checker parses, is `coldread` — so a gate keyed to one of two live
|
|
218
|
-
// spellings is guaranteed to miss. Its failure mode is the expensive one: a hole announced where
|
|
219
|
-
// none exists is how a gate stops being read, and then a real hole walks past it.
|
|
220
|
-
for (const fname of [
|
|
221
|
-
"2026-08-24-cold-read-report.md",
|
|
222
|
-
"2026-08-24-coldread-worksheet.md",
|
|
223
|
-
]) {
|
|
224
|
-
const name = "coldread-" + fname.replace(/[^a-z]/gi, "");
|
|
225
|
-
const d = join(tmp, name);
|
|
226
|
-
mkdirSync(join(d, "reviews"), { recursive: true });
|
|
227
|
-
writeFileSync(join(d, "PIPELINE-STATUS.md"), scorecard());
|
|
228
|
-
writeFileSync(join(d, "paper.md"), "## 1. Heading\n\nProse.\n");
|
|
229
|
-
writeFileSync(join(d, "reviews", fname), "# a reader with no context\n");
|
|
230
|
-
const out = execFileSync("node", [SCRIPT, d, "--json", `--today=${TODAY}`], {
|
|
231
|
-
cwd: ROOT,
|
|
232
|
-
encoding: "utf8",
|
|
233
|
-
env: ENV,
|
|
234
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
235
|
-
});
|
|
236
|
-
const ks = JSON.parse(out).map((f) => f.kind);
|
|
237
|
-
assert.ok(
|
|
238
|
-
!ks.includes("no-cold-read"),
|
|
239
|
-
`a real cold-read report named ${fname} was reported as missing — the pattern does not know this spelling`,
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
// …and the half that proves the check still works: reviews/ exists and holds nothing cold-read.
|
|
243
|
-
{
|
|
244
|
-
const d = join(tmp, "coldread-absent");
|
|
245
|
-
mkdirSync(join(d, "reviews"), { recursive: true });
|
|
246
|
-
writeFileSync(join(d, "PIPELINE-STATUS.md"), scorecard());
|
|
247
|
-
writeFileSync(join(d, "paper.md"), "## 1. Heading\n\nProse.\n");
|
|
248
|
-
writeFileSync(
|
|
249
|
-
join(d, "reviews", "2026-08-24-hotcrp-reviews.md"),
|
|
250
|
-
"# not a cold read\n",
|
|
251
|
-
);
|
|
252
|
-
const out = execFileSync("node", [SCRIPT, d, "--json", `--today=${TODAY}`], {
|
|
253
|
-
cwd: ROOT,
|
|
254
|
-
encoding: "utf8",
|
|
255
|
-
env: ENV,
|
|
256
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
257
|
-
});
|
|
258
|
-
assert.ok(
|
|
259
|
-
JSON.parse(out)
|
|
260
|
-
.map((f) => f.kind)
|
|
261
|
-
.includes("no-cold-read"),
|
|
262
|
-
"reviews/ with no cold-read report was NOT reported — widening the pattern silenced the gate",
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
267
|
-
console.log(
|
|
268
|
-
"✓ pipeline-check: 6 cases + two spellings of the cold-read report — one planted defect at a time, on six checks whose input is OUTSIDE the file (git · clock · reviews/ · env). The other sixteen moved to eslint-rules/pipeline-status.harness.mjs",
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
// ── THE HISTORY CUT ──────────────────────────────────────────────────────────
|
|
272
|
-
// Added 2026-09-19, and the reason it was added is the finding: `currentPart` had NO test at
|
|
273
|
-
// all. The word "History" appeared nowhere in this file, so the function that decides which
|
|
274
|
-
// half of a scorecard counts as current was running unwatched.
|
|
275
|
-
//
|
|
276
|
-
// 🔴 That is also why the cleanup it guards was unsafe until now. `HISTORY_MARK_RE` — a regex
|
|
277
|
-
// over the raw sentence «Всё, что ниже, — история» — was deleted in favour of the heading path
|
|
278
|
-
// alone, and neither the old branch nor the new one could be shown to work. Two attempts at a
|
|
279
|
-
// discriminator through the CLI returned the same answer for both inputs, which says nothing
|
|
280
|
-
// about the subject: same answer for different inputs means the probe is measuring itself.
|
|
281
|
-
// Going through the exported parser instead separates them in one call.
|
|
282
|
-
//
|
|
283
|
-
// Both halves: the buried row is gone under a marker heading, and PRESENT under one that is not
|
|
284
|
-
// a marker. Without the second, a parser that dropped every second section would pass.
|
|
285
|
-
{
|
|
286
|
-
const body = (heading) => `# Scorecard
|
|
287
|
-
|
|
288
|
-
### CONTINUOUS
|
|
289
|
-
| id | Trigger | Skill | Status | Date | Result | Open |
|
|
290
|
-
|----|---------|-------|--------|------|--------|------|
|
|
291
|
-
| live | x | s | ☑ | 2026-09-01 | current | — |
|
|
292
|
-
|
|
293
|
-
## ${heading}
|
|
294
|
-
|
|
295
|
-
### CONTINUOUS
|
|
296
|
-
| id | Trigger | Skill | Status | Date | Result | Open |
|
|
297
|
-
|----|---------|-------|--------|------|--------|------|
|
|
298
|
-
| buried | x | s | ☑ | 2001-01-01 | superseded snapshot | — |
|
|
299
|
-
`;
|
|
300
|
-
const ids = (t) =>
|
|
301
|
-
Object.values(parseStatus(t).sections)
|
|
302
|
-
.flat()
|
|
303
|
-
.map((r) => r.id);
|
|
304
|
-
|
|
305
|
-
for (const marker of [
|
|
306
|
-
"History",
|
|
307
|
-
"Archive",
|
|
308
|
-
"history",
|
|
309
|
-
"Archive of superseded rows",
|
|
310
|
-
]) {
|
|
311
|
-
const got = ids(body(marker));
|
|
312
|
-
assert.deepEqual(
|
|
313
|
-
got,
|
|
314
|
-
["live"],
|
|
315
|
-
`a row under the «${marker}» marker is still counted as current — a superseded snapshot ` +
|
|
316
|
-
`reads as today's status, which is the exact failure the cut exists to prevent: ${JSON.stringify(got)}`,
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// The other half. A heading that merely mentions neither word must NOT cut, or the check
|
|
321
|
-
// silently stops seeing whole sections and reports a clean scorecard it never read.
|
|
322
|
-
const kept = ids(body("Notes"));
|
|
323
|
-
assert.deepEqual(
|
|
324
|
-
kept,
|
|
325
|
-
["live", "buried"],
|
|
326
|
-
`an ordinary heading cut the document — sections after it vanish unnoticed: ${JSON.stringify(kept)}`,
|
|
327
|
-
);
|
|
328
|
-
}
|