paperlint 3.1.3 → 3.2.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 +12 -7
- package/CLAUDE.md +3 -3
- package/CONTRIBUTING.md +34 -5
- package/dist/adapters/banal/index.d.ts.map +1 -1
- package/dist/adapters/banal/index.js +9 -5
- package/dist/adapters/banal/index.js.map +1 -1
- package/dist/adapters/banal/invocation.d.ts +1 -1
- package/dist/adapters/node/files.io.d.ts.map +1 -1
- package/dist/adapters/node/files.io.js +2 -1
- package/dist/adapters/node/files.io.js.map +1 -1
- package/dist/adapters/node/process.io.d.ts +0 -5
- package/dist/adapters/node/process.io.d.ts.map +1 -1
- package/dist/adapters/node/process.io.js +4 -3
- package/dist/adapters/node/process.io.js.map +1 -1
- package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
- package/dist/adapters/pdfjs/fill.js +13 -7
- 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 -5
- package/dist/adapters/references/index.js.map +1 -1
- package/dist/adapters/references/pool.d.ts.map +1 -1
- package/dist/adapters/references/pool.js +4 -5
- package/dist/adapters/references/pool.js.map +1 -1
- package/dist/adapters/references/reach.io.d.ts.map +1 -1
- package/dist/adapters/references/reach.io.js +2 -1
- package/dist/adapters/references/reach.io.js.map +1 -1
- package/dist/build-engine.js +2 -2
- package/dist/build-engine.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +14 -11
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +31 -34
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +3 -2
- package/dist/doctor.js.map +1 -1
- package/dist/domain/lookup-cache.d.ts.map +1 -1
- package/dist/domain/lookup-cache.js +10 -8
- package/dist/domain/lookup-cache.js.map +1 -1
- package/dist/domain/text.d.ts +12 -0
- package/dist/domain/text.d.ts.map +1 -1
- package/dist/domain/text.js +17 -0
- package/dist/domain/text.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +4 -3
- package/dist/engine.js.map +1 -1
- package/dist/eslint-rules/bib-reachable-entry.d.ts +22 -0
- package/dist/eslint-rules/bib-reachable-entry.d.ts.map +1 -0
- package/dist/eslint-rules/bib-reachable-entry.js +75 -0
- package/dist/eslint-rules/bib-reachable-entry.js.map +1 -0
- package/dist/eslint-rules/install-path-literals.d.ts +80 -0
- package/dist/eslint-rules/install-path-literals.d.ts.map +1 -0
- package/dist/eslint-rules/install-path-literals.js +105 -0
- package/dist/eslint-rules/install-path-literals.js.map +1 -0
- package/dist/eslint-rules/latex-language.d.ts +136 -0
- package/dist/eslint-rules/latex-language.d.ts.map +1 -0
- package/dist/eslint-rules/latex-language.js +639 -0
- package/dist/eslint-rules/latex-language.js.map +1 -0
- package/dist/eslint-rules/paper-research-question.d.ts +31 -0
- package/dist/eslint-rules/paper-research-question.d.ts.map +1 -0
- package/dist/eslint-rules/paper-research-question.js +188 -0
- package/dist/eslint-rules/paper-research-question.js.map +1 -0
- package/dist/eslint-rules/paper-stages.d.ts +83 -0
- package/dist/eslint-rules/paper-stages.d.ts.map +1 -0
- package/dist/eslint-rules/paper-stages.js +358 -0
- package/dist/eslint-rules/paper-stages.js.map +1 -0
- package/dist/eslint-rules/paper-typography.d.ts +74 -0
- package/dist/eslint-rules/paper-typography.d.ts.map +1 -0
- package/dist/eslint-rules/paper-typography.js +404 -0
- package/dist/eslint-rules/paper-typography.js.map +1 -0
- package/dist/eslint-rules/papers.d.ts +42 -0
- package/dist/eslint-rules/papers.d.ts.map +1 -0
- package/dist/eslint-rules/papers.js +145 -0
- package/dist/eslint-rules/papers.js.map +1 -0
- package/dist/eslint-rules/pdf-last-page-balance.d.ts +72 -0
- package/dist/eslint-rules/pdf-last-page-balance.d.ts.map +1 -0
- package/dist/eslint-rules/pdf-last-page-balance.js +237 -0
- package/dist/eslint-rules/pdf-last-page-balance.js.map +1 -0
- package/dist/eslint-rules/review-frontmatter.d.ts +57 -0
- package/dist/eslint-rules/review-frontmatter.d.ts.map +1 -0
- package/dist/eslint-rules/review-frontmatter.js +126 -0
- package/dist/eslint-rules/review-frontmatter.js.map +1 -0
- package/dist/eslint-rules/review-frontmatter.schema.json +36 -0
- package/dist/eslint-rules/rule-context.d.ts +55 -0
- package/dist/eslint-rules/rule-context.d.ts.map +1 -0
- package/dist/eslint-rules/rule-context.js +9 -0
- package/dist/eslint-rules/rule-context.js.map +1 -0
- package/dist/eslint-rules/sibling-frontmatter.d.ts +25 -0
- package/dist/eslint-rules/sibling-frontmatter.d.ts.map +1 -0
- package/dist/eslint-rules/sibling-frontmatter.js +16 -0
- package/dist/eslint-rules/sibling-frontmatter.js.map +1 -0
- package/dist/eslint-rules/sibling-frontmatter.schema.json +14 -0
- package/dist/eslint-rules/temp-root-realpath.d.ts +71 -0
- package/dist/eslint-rules/temp-root-realpath.d.ts.map +1 -0
- package/dist/eslint-rules/temp-root-realpath.js +139 -0
- package/dist/eslint-rules/temp-root-realpath.js.map +1 -0
- package/dist/eslint-rules/tex-build.d.ts +35 -0
- package/dist/eslint-rules/tex-build.d.ts.map +1 -0
- package/dist/eslint-rules/tex-build.js +313 -0
- package/dist/eslint-rules/tex-build.js.map +1 -0
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +2 -1
- package/dist/facts-file.js.map +1 -1
- package/dist/hooks-settings.d.ts +1 -1
- package/dist/hooks-settings.d.ts.map +1 -1
- package/dist/hooks-settings.js +14 -9
- package/dist/hooks-settings.js.map +1 -1
- package/dist/init.d.ts +5 -5
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +15 -7
- package/dist/init.js.map +1 -1
- package/dist/latex-loop.d.ts +2 -2
- package/dist/latex-loop.d.ts.map +1 -1
- package/dist/latex-loop.js +2 -2
- package/dist/latex-loop.js.map +1 -1
- package/dist/lib/agent-cli-version.d.ts +65 -0
- package/dist/lib/agent-cli-version.d.ts.map +1 -0
- package/dist/lib/agent-cli-version.js +77 -0
- package/dist/lib/agent-cli-version.js.map +1 -0
- package/dist/lib/check.d.ts +19 -0
- package/dist/lib/check.d.ts.map +1 -0
- package/dist/lib/check.js +52 -0
- package/dist/lib/check.js.map +1 -0
- package/dist/lib/markdown.d.ts +180 -0
- package/dist/lib/markdown.d.ts.map +1 -0
- package/dist/lib/markdown.js +302 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/paper-config.d.ts +84 -0
- package/dist/lib/paper-config.d.ts.map +1 -0
- package/dist/lib/paper-config.js +142 -0
- package/dist/lib/paper-config.js.map +1 -0
- package/dist/lib/skill-eval-fixture.d.ts +29 -0
- package/dist/lib/skill-eval-fixture.d.ts.map +1 -0
- package/dist/lib/skill-eval-fixture.js +62 -0
- package/dist/lib/skill-eval-fixture.js.map +1 -0
- package/dist/link-skills.d.ts.map +1 -1
- package/dist/link-skills.js +5 -4
- package/dist/link-skills.js.map +1 -1
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +2 -2
- package/dist/new-paper.js.map +1 -1
- package/dist/paper-settings.d.ts.map +1 -1
- package/dist/paper-settings.js +5 -4
- package/dist/paper-settings.js.map +1 -1
- package/dist/pdf-facts.d.ts.map +1 -1
- package/dist/pdf-facts.js +2 -1
- package/dist/pdf-facts.js.map +1 -1
- package/dist/pdf-geometry.d.ts.map +1 -1
- package/dist/pdf-geometry.js +1 -1
- package/dist/pdf-geometry.js.map +1 -1
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +3 -2
- package/dist/presets.js.map +1 -1
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +11 -6
- package/dist/references.js.map +1 -1
- package/dist/rules-config.d.ts.map +1 -1
- package/dist/rules-config.js +6 -3
- package/dist/rules-config.js.map +1 -1
- package/dist/structure.js +1 -1
- package/dist/structure.js.map +1 -1
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +8 -3
- package/dist/tex-requirements.js.map +1 -1
- package/dist/toolchain.d.ts.map +1 -1
- package/dist/toolchain.js +21 -16
- package/dist/toolchain.js.map +1 -1
- package/dist/venue-rules.js +1 -1
- package/dist/venue-rules.js.map +1 -1
- package/docs/e2e.md +7 -7
- 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 +2 -2
- package/docs/testing.md +11 -8
- package/docs/toolchain.md +1 -1
- package/eslint-rules/{bib-reachable-entry.mjs → bib-reachable-entry.ts} +4 -3
- package/eslint-rules/install-path-literals.harness.mjs +1 -1
- package/eslint-rules/{install-path-literals.mjs → install-path-literals.ts} +16 -8
- package/eslint-rules/latex-language.harness.mjs +2 -2
- package/eslint-rules/latex-language.test.mjs +7 -1
- package/eslint-rules/{latex-language.mjs → latex-language.ts} +297 -109
- package/eslint-rules/paper-research-question.harness.mjs +3 -3
- package/eslint-rules/{paper-research-question.mjs → paper-research-question.ts} +34 -15
- package/eslint-rules/paper-stages.harness.mjs +2 -2
- package/eslint-rules/paper-stages.test.mjs +8 -2
- package/eslint-rules/{paper-stages.mjs → paper-stages.ts} +74 -29
- package/eslint-rules/paper-typography.test.mjs +3 -3
- package/eslint-rules/{paper-typography.mjs → paper-typography.ts} +132 -54
- package/eslint-rules/papers.harness.mjs +2 -2
- package/eslint-rules/{papers.mjs → papers.ts} +7 -4
- package/eslint-rules/pdf-last-page-balance.harness.mjs +3 -3
- package/eslint-rules/{pdf-last-page-balance.mjs → pdf-last-page-balance.ts} +88 -31
- package/eslint-rules/review-frontmatter.test.mjs +2 -2
- package/eslint-rules/{review-frontmatter.mjs → review-frontmatter.ts} +37 -15
- package/eslint-rules/rule-context.ts +62 -0
- package/eslint-rules/{sibling-frontmatter.mjs → sibling-frontmatter.ts} +1 -1
- package/eslint-rules/temp-root-realpath.harness.mjs +1 -1
- package/eslint-rules/{temp-root-realpath.mjs → temp-root-realpath.ts} +19 -6
- package/eslint-rules/tex-build.harness.mjs +2 -2
- package/eslint-rules/{tex-build.mjs → tex-build.ts} +4 -3
- package/eslint.config.mjs +139 -30
- package/fixtures/pdf-facts/README.md +2 -2
- package/fixtures/real-markdown-paper/{baseline.mjs → baseline.ts} +31 -10
- package/hooks/{hooks.harness.mjs → hooks.harness.ts} +51 -34
- package/hooks/paper-edit-guard.hook.mjs +1 -1
- package/hooks/{paper-edit-guard.test.mjs → paper-edit-guard.test.ts} +3 -7
- package/hooks/paper-skills-nudge.hook.mjs +1 -1
- package/hooks/{paper-skills-nudge.test.mjs → paper-skills-nudge.test.ts} +2 -6
- package/hooks/{paper-status-gates.test.mjs → paper-status-gates.test.ts} +2 -6
- package/lib/agent-cli-version.harness.mjs +1 -1
- package/lib/{agent-cli-version.mjs → agent-cli-version.ts} +32 -18
- package/lib/check.test.ts +14 -9
- package/lib/{check.mjs → check.ts} +22 -9
- package/lib/markdown.test.mjs +7 -7
- package/lib/{markdown.mjs → markdown.ts} +68 -29
- package/lib/paper-config.harness.mjs +8 -8
- package/lib/{paper-config.mjs → paper-config.ts} +19 -14
- package/lib/skill-checks.mjs +1 -1
- package/lib/skill-checks.test.mjs +1 -1
- package/lib/skill-corpus.mjs +1 -1
- package/lib/skill-eval-kit.mjs +1 -1
- package/package.json +42 -10
- package/scripts/{check.harness.mjs → check.harness.ts} +111 -10
- package/scripts/{check.test.mjs → check.test.ts} +13 -10
- package/scripts/{check.mjs → check.ts} +116 -42
- package/scripts/coverage-config.test.ts +80 -37
- package/scripts/eslint-report-guard.test.mjs +1 -1
- package/scripts/harness-api.frozen.json +14 -15
- package/scripts/harness-api.test.ts +8 -5
- package/scripts/layer-legacy-frozen.test.ts +17 -13
- package/scripts/{layer-legacy-frozen.mjs → layer-legacy-frozen.ts} +128 -39
- package/scripts/release-config.test.ts +12 -4
- package/scripts/rules-see-files.test.mjs +1 -1
- package/scripts/test.test.ts +78 -0
- package/scripts/test.ts +87 -0
- package/skills/grade-paper-writing/prose-lint.mjs +1 -1
- package/skills/grade-paper-writing/{prose-lint.test.mjs → prose-lint.test.ts} +2 -2
- package/skills/paper-pipeline/description-language.eval.mjs +1 -1
- package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +1 -1
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1 -1
- package/skills/paper-pipeline/pipeline-firing.eval.mjs +1 -1
- package/skills/paper-pipeline/pipeline-language.eval.mjs +1 -1
- package/skills/paper-pipeline/scripts/README.md +1 -1
- package/skills/paper-pipeline/scripts/announce.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/artifact-coverage.mjs +1 -1
- package/skills/paper-pipeline/scripts/{artifact-coverage.test.mjs → artifact-coverage.test.ts} +2 -2
- package/skills/paper-pipeline/scripts/consumer.mjs +1 -5
- package/skills/paper-pipeline/scripts/consumer.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +1 -1
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +1 -4
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/fixtures/{scorecard.mjs → scorecard.ts} +36 -7
- package/skills/paper-pipeline/scripts/{generated-code.test.mjs → generated-code.test.ts} +3 -3
- package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +2 -2
- package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +2 -2
- package/skills/paper-pipeline/scripts/pipeline-check.mjs +1 -4
- package/skills/paper-pipeline/scripts/population-map.mjs +1 -4
- package/skills/paper-pipeline/scripts/population-map.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/{round-diff.harness.mjs → round-diff.harness.ts} +45 -18
- package/skills/paper-pipeline/scripts/round-diff.mjs +1 -1
- package/skills/paper-pipeline/scripts/round-diff.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/status.test.mjs +1 -1
- package/skills/plan-paper-timeline/fixtures/{fake-google-calendar.mjs → fake-google-calendar.ts} +101 -70
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +3 -3
- package/skills/render-paper/{extract-pdf-facts.harness.mjs → extract-pdf-facts.harness.ts} +34 -9
- package/skills/render-paper/render-paper.harness.mjs +2 -2
- package/skills/tighten-paper/structure.mjs +1 -1
- package/skills/tighten-paper/{structure.test.mjs → structure.test.ts} +4 -3
- package/skills/verify-citations/scripts/{bib-authors.cli.test.mjs → bib-authors.cli.test.ts} +14 -4
- package/skills/verify-citations/scripts/bib-authors.d.mts +63 -0
- package/skills/verify-citations/scripts/bib-authors.mjs +1 -4
- package/skills/verify-citations/scripts/{verify-cites.cli.test.mjs → verify-cites.cli.test.ts} +32 -9
- package/skills/verify-citations/scripts/verify-cites.d.mts +58 -0
- package/src/CLAUDE.md +1 -1
- package/src/adapters/banal/index.test.ts +3 -6
- package/src/adapters/banal/index.ts +7 -4
- package/src/adapters/banal/invocation.test.ts +3 -1
- package/src/adapters/banal/invocation.ts +1 -1
- package/src/adapters/banal/output.test.ts +1 -1
- package/src/adapters/banal/run.test.ts +3 -3
- package/src/adapters/banal/xml.test.ts +1 -1
- package/src/adapters/curl/download.test.ts +4 -2
- package/src/adapters/node/files.io.ts +2 -2
- package/src/adapters/node/files.test.ts +3 -1
- package/src/adapters/node/process.io.ts +4 -3
- package/src/adapters/node/process.test.ts +1 -1
- package/src/adapters/node/workspace.test.ts +3 -1
- package/src/adapters/pdfjs/fill.test.ts +2 -2
- package/src/adapters/pdfjs/fill.ts +14 -7
- package/src/adapters/references/index.test.ts +31 -38
- package/src/adapters/references/index.ts +26 -58
- package/src/adapters/references/pool.ts +3 -5
- package/src/adapters/references/reach.io.ts +2 -1
- package/src/build-engine.harness.mjs +1 -1
- package/src/build-engine.test.ts +2 -2
- package/src/build-engine.ts +2 -2
- package/src/build.harness.mjs +2 -2
- package/src/build.test.ts +15 -14
- package/src/build.ts +28 -19
- package/src/cli.harness.mjs +6 -6
- package/src/cli.test.ts +13 -6
- package/src/cli.ts +39 -37
- package/src/doctor.harness.mjs +3 -3
- package/src/doctor.ts +3 -2
- package/src/domain/lookup-cache.ts +21 -11
- package/src/domain/result.test.ts +2 -2
- package/src/domain/text.test.ts +32 -0
- package/src/domain/text.ts +23 -0
- package/src/engine.harness.mjs +2 -2
- package/src/engine.ts +4 -3
- package/src/facts-file.test.ts +9 -7
- package/src/facts-file.ts +2 -1
- package/src/{hooks-settings.harness.mjs → hooks-settings.harness.ts} +39 -20
- package/src/hooks-settings.ts +20 -9
- package/src/init.test.ts +12 -9
- package/src/init.ts +22 -12
- package/src/{latex-log.harness.mjs → latex-log.harness.ts} +14 -14
- package/src/{latex-loop.harness.mjs → latex-loop.harness.ts} +64 -36
- package/src/latex-loop.ts +3 -3
- package/src/{link-skills.harness.mjs → link-skills.harness.ts} +19 -19
- package/src/link-skills.test.ts +3 -3
- package/src/link-skills.ts +5 -4
- package/src/lint-fix.test.ts +4 -6
- package/src/linted-set.test.ts +2 -2
- package/src/new-paper.harness.mjs +2 -2
- package/src/new-paper.test.ts +8 -10
- package/src/new-paper.ts +2 -2
- package/src/paper-files.test.ts +3 -5
- package/src/paper-settings-commands.test.ts +5 -4
- package/src/paper-settings.test.ts +5 -5
- package/src/paper-settings.ts +8 -9
- package/src/{pdf-facts.harness.mjs → pdf-facts.harness.ts} +9 -8
- package/src/pdf-facts.test.ts +10 -11
- package/src/pdf-facts.ts +2 -1
- package/src/{pdf-geometry.harness.mjs → pdf-geometry.harness.ts} +19 -12
- package/src/pdf-geometry.ts +3 -1
- package/src/presets.ts +3 -2
- package/src/references.test.ts +51 -43
- package/src/references.ts +14 -7
- package/src/{rules-config.harness.mjs → rules-config.harness.ts} +7 -13
- package/src/rules-config.ts +7 -4
- package/src/rules-off.test.ts +6 -4
- package/src/{structure.harness.mjs → structure.harness.ts} +26 -15
- package/src/structure.ts +1 -1
- package/src/{tex-requirements.harness.mjs → tex-requirements.harness.ts} +50 -22
- package/src/tex-requirements.ts +8 -5
- package/src/toolchain.harness.mjs +2 -2
- package/src/toolchain.test.ts +1 -1
- package/src/toolchain.ts +31 -17
- package/src/venue-rules.test.ts +62 -64
- package/src/venue-rules.ts +1 -1
- package/tsconfig.json +6 -3
- package/tsconfig.pkg.json +10 -0
- package/lib/check.d.mts +0 -17
- package/lib/paper-config.d.mts +0 -31
- package/scripts/layer-legacy-frozen.d.mts +0 -36
- package/scripts/rules-are-content-only.harness.mjs +0 -105
- package/scripts/rules-are-content-only.mjs +0 -148
- package/scripts/rules-are-content-only.test.mjs +0 -61
- package/scripts/test.mjs +0 -44
- package/scripts/test.test.mjs +0 -52
- /package/bin/{paperlint.test.mjs → paperlint.test.ts} +0 -0
- /package/lib/{skill-eval-fixture.mjs → skill-eval-fixture.ts} +0 -0
- /package/skills/grade-paper-writing/__snapshots__/{prose-lint.test.mjs.snap → prose-lint.test.ts.snap} +0 -0
- /package/skills/osf-artifact-upload/{osf-artifact-upload.harness.mjs → osf-artifact-upload.harness.ts} +0 -0
- /package/skills/tighten-paper/__snapshots__/{structure.test.mjs.snap → structure.test.ts.snap} +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npm test`'s runner: both suites run whatever the first returned, each failure is named, and
|
|
3
|
+
* the harness arguments reach the harness runner only.
|
|
4
|
+
*/
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { test } from "vitest";
|
|
7
|
+
import { runSuites, SUITES, type Spawn } from "./test.ts";
|
|
8
|
+
|
|
9
|
+
/** A spawn that records every call and exits with `status[file]` (`null` for a signal). */
|
|
10
|
+
const fake = (status: Record<string, number | null>) => {
|
|
11
|
+
const calls: string[][] = [];
|
|
12
|
+
const spawn: Spawn = (file, args) => {
|
|
13
|
+
calls.push([file, ...args]);
|
|
14
|
+
return { status: status[file] ?? null };
|
|
15
|
+
};
|
|
16
|
+
return { calls, spawn };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
test("a failing vitest does not skip the harnesses, and is named as the failure", () => {
|
|
20
|
+
const { calls, spawn } = fake({ vitest: 1, vigiles: 0 });
|
|
21
|
+
const said: string[] = [];
|
|
22
|
+
assert.equal(
|
|
23
|
+
runSuites(["--no-skip"], { spawn, err: (s) => said.push(s) }),
|
|
24
|
+
1,
|
|
25
|
+
);
|
|
26
|
+
assert.deepEqual(calls, [
|
|
27
|
+
["vitest", "run"],
|
|
28
|
+
["vigiles", "test", "--min=1", "--no-skip"],
|
|
29
|
+
]);
|
|
30
|
+
assert.deepEqual(said, [
|
|
31
|
+
"✗ vitest failed (exit 1) — its own report is above",
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("both passing is 0 and silent; a harness killed by a signal is exit 1, named", () => {
|
|
36
|
+
const ok = fake({ vitest: 0, vigiles: 0 });
|
|
37
|
+
assert.equal(runSuites([], { spawn: ok.spawn, err: assert.fail }), 0);
|
|
38
|
+
const killed = fake({ vitest: 0, vigiles: null });
|
|
39
|
+
const said: string[] = [];
|
|
40
|
+
assert.equal(
|
|
41
|
+
runSuites([], { spawn: killed.spawn, err: (s) => said.push(s) }),
|
|
42
|
+
1,
|
|
43
|
+
);
|
|
44
|
+
assert.deepEqual(said, [
|
|
45
|
+
"✗ harnesses failed (exit 1) — its own report is above",
|
|
46
|
+
]);
|
|
47
|
+
assert.deepEqual(
|
|
48
|
+
SUITES.map((s) => s.name),
|
|
49
|
+
["vitest", "harnesses"],
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("every suite runs the SOURCES: the paperlint-source condition is in NODE_OPTIONS, the caller's kept", () => {
|
|
54
|
+
const seen: (string | undefined)[] = [];
|
|
55
|
+
const spawn: Spawn = (_file, _args, options) => {
|
|
56
|
+
seen.push(options.env.NODE_OPTIONS);
|
|
57
|
+
return { status: 0 };
|
|
58
|
+
};
|
|
59
|
+
assert.equal(
|
|
60
|
+
runSuites([], {
|
|
61
|
+
spawn,
|
|
62
|
+
err: assert.fail,
|
|
63
|
+
env: { NODE_OPTIONS: "--import=./x.ts" },
|
|
64
|
+
}),
|
|
65
|
+
0,
|
|
66
|
+
);
|
|
67
|
+
assert.deepEqual(seen, [
|
|
68
|
+
"--conditions=paperlint-source --import=./x.ts",
|
|
69
|
+
"--conditions=paperlint-source --import=./x.ts",
|
|
70
|
+
]);
|
|
71
|
+
// Without a caller's NODE_OPTIONS there is no stray trailing space.
|
|
72
|
+
seen.length = 0;
|
|
73
|
+
runSuites([], { spawn, err: assert.fail, env: {} });
|
|
74
|
+
assert.deepEqual(seen, [
|
|
75
|
+
"--conditions=paperlint-source",
|
|
76
|
+
"--conditions=paperlint-source",
|
|
77
|
+
]);
|
|
78
|
+
});
|
package/scripts/test.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npm test`: the unit tests (vitest), then the harnesses (`vigiles test`). BOTH always run.
|
|
3
|
+
*
|
|
4
|
+
* Until #52 this was `vitest run && vigiles test --min=1`. Under `npm run coverage` a single
|
|
5
|
+
* failing vitest test then skipped every harness, and what the run printed last was c8's summary:
|
|
6
|
+
* lines, branches and functions each some six points below the floor. The one failing test sat
|
|
7
|
+
* above that, looking like a consequence rather than the cause. Running both suites keeps the
|
|
8
|
+
* coverage report whole, so a failing test is reported as itself and the coverage figures still
|
|
9
|
+
* mean what they say.
|
|
10
|
+
*
|
|
11
|
+
* Arguments are the harness runner's (`npm test -- --no-skip`), as they were before.
|
|
12
|
+
*
|
|
13
|
+
* Both suites run the SOURCES: every child gets `--conditions=paperlint-source`, so `#lib/*` and
|
|
14
|
+
* `#eslint-rules/*` resolve to `.ts`, not to `dist/`. This runner is the one owner of that
|
|
15
|
+
* setting. When only `npm run coverage` passed it, a plain `npm test` loaded the rules twice —
|
|
16
|
+
* `dist/` through `eslint.config.mjs`, `.ts` through the harness — and a harness comparing the two
|
|
17
|
+
* failed on macOS CI, the one job that runs `npm test` bare.
|
|
18
|
+
*/
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
|
+
import { isMain } from "../skills/paper-pipeline/scripts/consumer.mjs";
|
|
21
|
+
|
|
22
|
+
/** The two suites, in order: what a failure is named as, and the command. */
|
|
23
|
+
export interface Suite {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
/** The program, then its arguments. */
|
|
26
|
+
readonly command: readonly [string, ...string[]];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** What `runSuites` needs from a finished process: its exit status, `null` when a signal ended it. */
|
|
30
|
+
export type Spawn = (
|
|
31
|
+
file: string,
|
|
32
|
+
args: readonly string[],
|
|
33
|
+
options: { stdio: "inherit"; env: NodeJS.ProcessEnv },
|
|
34
|
+
) => { readonly status: number | null };
|
|
35
|
+
|
|
36
|
+
/** The condition that points package `imports` at the TypeScript sources instead of `dist/`. */
|
|
37
|
+
const SOURCE_CONDITION = "--conditions=paperlint-source";
|
|
38
|
+
|
|
39
|
+
/** `env` with the source condition first in NODE_OPTIONS, whatever the caller already had kept. */
|
|
40
|
+
export function withSources(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
41
|
+
const own = env.NODE_OPTIONS?.trim();
|
|
42
|
+
return {
|
|
43
|
+
...env,
|
|
44
|
+
NODE_OPTIONS: own ? `${SOURCE_CONDITION} ${own}` : SOURCE_CONDITION,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const SUITES: readonly Suite[] = [
|
|
49
|
+
{ name: "vitest", command: ["vitest", "run"] },
|
|
50
|
+
{ name: "harnesses", command: ["vigiles", "test", "--min=1"] },
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Run every suite, whatever the one before it returned, and name the ones that failed.
|
|
55
|
+
* @returns 0 when every suite passed; otherwise the first failing suite's exit code (1 for a signal).
|
|
56
|
+
*/
|
|
57
|
+
export function runSuites(
|
|
58
|
+
args: readonly string[],
|
|
59
|
+
{
|
|
60
|
+
spawn = spawnSync,
|
|
61
|
+
err = console.error,
|
|
62
|
+
suites = SUITES,
|
|
63
|
+
env = process.env,
|
|
64
|
+
}: {
|
|
65
|
+
spawn?: Spawn;
|
|
66
|
+
err?: (line: string) => void;
|
|
67
|
+
suites?: readonly Suite[];
|
|
68
|
+
env?: NodeJS.ProcessEnv;
|
|
69
|
+
} = {},
|
|
70
|
+
): number {
|
|
71
|
+
const failed = suites.flatMap(({ name, command }) => {
|
|
72
|
+
const [file, ...rest] = command;
|
|
73
|
+
const r = spawn(file, [...rest, ...(name === "harnesses" ? args : [])], {
|
|
74
|
+
stdio: "inherit",
|
|
75
|
+
env: withSources(env),
|
|
76
|
+
});
|
|
77
|
+
return r.status === 0 ? [] : [{ name, code: r.status ?? 1 }];
|
|
78
|
+
});
|
|
79
|
+
for (const f of failed)
|
|
80
|
+
err(
|
|
81
|
+
`✗ ${f.name} failed (exit ${String(f.code)}) — its own report is above`,
|
|
82
|
+
);
|
|
83
|
+
const [first] = failed;
|
|
84
|
+
return first === undefined ? 0 : first.code;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (isMain(import.meta.url)) process.exit(runSuites(process.argv.slice(2)));
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
stripFences,
|
|
71
71
|
requireMarkdown,
|
|
72
72
|
stripFrontmatter,
|
|
73
|
-
} from "
|
|
73
|
+
} from "#lib/markdown";
|
|
74
74
|
|
|
75
75
|
// Markup is parsed with a PARSER (`CLAUDE.md`, 2026-08-11). We fail rather than degrade, even
|
|
76
76
|
// though this file is advisory: without a parser the paper's body would collapse to empty, and from
|
|
@@ -8,14 +8,14 @@ import { join } from "node:path";
|
|
|
8
8
|
import { dirname } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { expect, test } from "vitest";
|
|
11
|
-
import { runNode, useTempDir, writeTree } from "../../test/support.
|
|
11
|
+
import { runNode, useTempDir, writeTree } from "../../test/support.ts";
|
|
12
12
|
|
|
13
13
|
const SCRIPT = join(dirname(fileURLToPath(import.meta.url)), "prose-lint.mjs");
|
|
14
14
|
const root = useTempDir("prose-lint-");
|
|
15
15
|
|
|
16
16
|
const LONG_CAPTION_SENTENCE = Array.from(
|
|
17
17
|
{ length: 45 },
|
|
18
|
-
(_, i) => `word${i}`,
|
|
18
|
+
(_, i) => `word${String(i)}`,
|
|
19
19
|
).join(" ");
|
|
20
20
|
const PAPER = `---
|
|
21
21
|
title: A title the linter must not read as a sentence
|
|
@@ -82,7 +82,7 @@ import { assertPromptDiversity, skillResolved, skip } from "vigiles";
|
|
|
82
82
|
import { paid_measureTriggerRate as measureTriggerRate } from "vigiles/eval";
|
|
83
83
|
import { existsSync, readFileSync } from "node:fs";
|
|
84
84
|
import { join } from "node:path";
|
|
85
|
-
import { frontmatterBlock } from "
|
|
85
|
+
import { frontmatterBlock } from "#lib/markdown";
|
|
86
86
|
import { parseFm } from "../../lib/skill-corpus.mjs";
|
|
87
87
|
import { installedSkills } from "./scripts/consumer.mjs";
|
|
88
88
|
|
|
@@ -250,7 +250,7 @@ import { assertPromptDiversity, skip } from "vigiles";
|
|
|
250
250
|
import { paid_measureTriggerRate as measureTriggerRate } from "vigiles/eval";
|
|
251
251
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
252
252
|
import { join } from "node:path";
|
|
253
|
-
import { frontmatterBlock } from "
|
|
253
|
+
import { frontmatterBlock } from "#lib/markdown";
|
|
254
254
|
import { parseFm } from "../../lib/skill-corpus.mjs";
|
|
255
255
|
import { installedSkills } from "./scripts/consumer.mjs";
|
|
256
256
|
|
|
@@ -375,7 +375,7 @@ import {
|
|
|
375
375
|
realpathSync,
|
|
376
376
|
} from "node:fs";
|
|
377
377
|
import { join } from "node:path";
|
|
378
|
-
import { frontmatterBlock } from "
|
|
378
|
+
import { frontmatterBlock } from "#lib/markdown";
|
|
379
379
|
import { parseFm } from "../../lib/skill-corpus.mjs";
|
|
380
380
|
import { installedSkills } from "./scripts/consumer.mjs";
|
|
381
381
|
import { execFileSync } from "node:child_process";
|
|
@@ -180,7 +180,7 @@ import {
|
|
|
180
180
|
import { paid_measureTriggerRate as measureTriggerRate } from "vigiles/eval";
|
|
181
181
|
import { existsSync, readFileSync } from "node:fs";
|
|
182
182
|
import { join } from "node:path";
|
|
183
|
-
import { frontmatterBlock } from "
|
|
183
|
+
import { frontmatterBlock } from "#lib/markdown";
|
|
184
184
|
import { parseFm } from "../../lib/skill-corpus.mjs";
|
|
185
185
|
import { installedSkills } from "./scripts/consumer.mjs";
|
|
186
186
|
|
|
@@ -137,7 +137,7 @@ import {
|
|
|
137
137
|
import { paid_measureTriggerRate as measureTriggerRate } from "vigiles/eval";
|
|
138
138
|
import { existsSync, readFileSync } from "node:fs";
|
|
139
139
|
import { join } from "node:path";
|
|
140
|
-
import { frontmatterBlock } from "
|
|
140
|
+
import { frontmatterBlock } from "#lib/markdown";
|
|
141
141
|
import { parseFm } from "../../lib/skill-corpus.mjs";
|
|
142
142
|
import { installedSkills } from "./scripts/consumer.mjs";
|
|
143
143
|
|
|
@@ -172,7 +172,7 @@ that fires on correct text is muted within a day, which is worse than one that m
|
|
|
172
172
|
| `generated-code.harness.mjs` | `generated-code.mjs` | an analysis script that draws randomness and never seeds it · one that hard-codes an absolute path · one that reads and then overwrites its own input (literal and `argv` forms). Plus every quiet case, which is where this checker lives or dies: a seed threaded through `--seed`, a lowercase Express route, a third party's relative path, a read-here-write-there script, a variable name reused across two loops — and the released bundle, which `check-anon.sh` cat. 5 owns and this one must not enter |
|
|
173
173
|
| `pipeline-check.harness.mjs` | `pipeline-check.mjs` | six defects, **one at a time**, asserting the exact finding set. 🔴 Since 2026-08-26 here only checks whose input is OUTSIDE the file (git · clock · `reviews/` · `process.env`); sixteen others moved to `eslint-rules/pipeline-status.mjs` and are checked by `eslint-rules/pipeline-status.harness.mjs` |
|
|
174
174
|
| `paper-lint.harness.mjs` | `paper-lint.mjs` | text moving under an unchanged scorecard · appendix outweighing the body · a shaved passage |
|
|
175
|
-
| `round-diff.harness.
|
|
175
|
+
| `round-diff.harness.ts` | `paper-pipeline/scripts/round-diff.mjs` | a section changed outside the round's declaration (and one added, and one **removed**) · a cite and a bare bibliography entry arriving mid-round · a numeric literal arriving mid-round, with restating an existing one asserted FREE · the body over its budget · **three rounds compounding past the sum of their budgets while the open round is inside its own** · hedge density rising · a `touches:` list covering the paper · a base that does not resolve · edits with every round closed. Plus the clean case: a legal round must produce total silence |
|
|
176
176
|
| `delivered-pdf.harness.mjs` | `repro/delivered_pdf.py` | a quantity deleted from the built page · **a superscript minus lost in typesetting, compiled and read back** · a value moved away from its claim · an occurrence whose prose the extractor lost · a missing, unreadable and stale PDF · and all six normalisation rules, one assertion each |
|
|
177
177
|
| `bound-numbers.harness.mjs` | `repro/paper_numbers.py`, `md2submission.py`, `latex-build.sh` | a digit in a `\newcommand` name · two registry keys mangling to one macro · an unescaped `%` in the generated values · a converter handling the digits again · a missing `\input` · an unbound name that must stop the build with **no PDF** · a failing pass that leaves its PDF on disk. Plus the CONTROL: a hand-typed literal still compiles, **asserted** so nobody writes that this makes a wrong number unrepresentable |
|
|
178
178
|
| `textidote.harness.mjs` | `repro/textidote_check.py` (TeXtidote v0.9) | a misspelling planted into real prose from the paper, live through the pinned jar · a coinage with a committed row staying silent in the same run · the flagged span truncated by one letter · the caret row leaking into the message · each of the three exclusions (`{{macro}}`, `` `code` ``, the reference list) · **an appendix AFTER `## References` still being judged** · a key that stops discriminating by rule, by word, or by case · a tolerated row moved 40 lines down and indented · the tolerated set, its reasons and the stale rows going unprinted · a missing jar or JRE answering with an empty findings array |
|
|
@@ -8,7 +8,7 @@ import { cpSync, readFileSync, rmSync } from "node:fs";
|
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { afterEach, test } from "vitest";
|
|
11
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
11
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
12
12
|
|
|
13
13
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
14
14
|
const SCRIPT = join(HERE, "announce.mjs");
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
headings as mdHeadings,
|
|
66
66
|
splitSections,
|
|
67
67
|
requireMarkdown,
|
|
68
|
-
} from "
|
|
68
|
+
} from "#lib/markdown";
|
|
69
69
|
|
|
70
70
|
// Markup is parsed with a parser (`CLAUDE.md`, 2026-08-11). We fail rather than degrade: without
|
|
71
71
|
// the parser NOT A SINGLE section would be found in the paper, and the check "every section with a
|
package/skills/paper-pipeline/scripts/{artifact-coverage.test.mjs → artifact-coverage.test.ts}
RENAMED
|
@@ -8,14 +8,14 @@ import assert from "node:assert/strict";
|
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { test } from "vitest";
|
|
11
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
11
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
12
12
|
|
|
13
13
|
const SCRIPT = join(
|
|
14
14
|
dirname(fileURLToPath(import.meta.url)),
|
|
15
15
|
"artifact-coverage.mjs",
|
|
16
16
|
);
|
|
17
17
|
const root = useTempDir("artifact-coverage-");
|
|
18
|
-
const run = (...args) => runNode(SCRIPT, args);
|
|
18
|
+
const run = (...args: string[]) => runNode(SCRIPT, args);
|
|
19
19
|
|
|
20
20
|
test("no argument prints the usage; a paper with no markdown source is a named skip", () => {
|
|
21
21
|
assert.deepEqual(run(), {
|
|
@@ -85,11 +85,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
85
85
|
|
|
86
86
|
// Re-exported, not re-declared — see the note in `lib/paper-config.mjs`. This file is not a hook
|
|
87
87
|
// and never needed its own copy.
|
|
88
|
-
import {
|
|
89
|
-
CONFIG_FILE,
|
|
90
|
-
CONFIG_KEY,
|
|
91
|
-
settingsOf,
|
|
92
|
-
} from "../../../lib/paper-config.mjs";
|
|
88
|
+
import { CONFIG_FILE, CONFIG_KEY, settingsOf } from "#lib/paper-config";
|
|
93
89
|
export { CONFIG_KEY, settingsOf };
|
|
94
90
|
|
|
95
91
|
/**
|
|
@@ -6,7 +6,7 @@ import assert from "node:assert/strict";
|
|
|
6
6
|
import { mkdirSync, symlinkSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { afterEach, test } from "vitest";
|
|
9
|
-
import { useTempDir, writeTree } from "../../../test/support.
|
|
9
|
+
import { useTempDir, writeTree } from "../../../test/support.ts";
|
|
10
10
|
import {
|
|
11
11
|
consumerContactEmail,
|
|
12
12
|
consumerTimezone,
|
|
@@ -71,10 +71,7 @@ import {
|
|
|
71
71
|
} from "node:fs";
|
|
72
72
|
import { createHash } from "node:crypto";
|
|
73
73
|
import { join, resolve, dirname, basename } from "node:path";
|
|
74
|
-
import {
|
|
75
|
-
headings as mdHeadings,
|
|
76
|
-
requireMarkdown,
|
|
77
|
-
} from "../../../lib/markdown.mjs";
|
|
74
|
+
import { headings as mdHeadings, requireMarkdown } from "#lib/markdown";
|
|
78
75
|
import { isMain } from "./consumer.mjs";
|
|
79
76
|
|
|
80
77
|
// Markup is parsed with a parser (`CLAUDE.md`, 2026-08-11). We fail rather than degrade: without
|
|
@@ -8,7 +8,7 @@ import { readFileSync, writeFileSync } from "node:fs";
|
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { test } from "vitest";
|
|
11
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
11
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
12
12
|
import {
|
|
13
13
|
buildFacts,
|
|
14
14
|
extractIds,
|
|
@@ -4,6 +4,34 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export const FAR = "2027-12-31";
|
|
6
6
|
|
|
7
|
+
/** What a test may replace in one row: any cell, and for a GATES row its `Requires` cell. */
|
|
8
|
+
export interface RowOverride {
|
|
9
|
+
readonly status?: string;
|
|
10
|
+
readonly date?: string;
|
|
11
|
+
readonly skill?: string;
|
|
12
|
+
readonly result?: string;
|
|
13
|
+
readonly requires?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Per-row overrides by row id, plus the four free-text parts of the file. */
|
|
17
|
+
export interface ScorecardOverrides {
|
|
18
|
+
readonly verdict?: string;
|
|
19
|
+
readonly deadline?: string;
|
|
20
|
+
readonly tail?: string;
|
|
21
|
+
readonly preamble?: string;
|
|
22
|
+
readonly [id: string]: RowOverride | string | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface Row extends RowOverride {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly status: string;
|
|
28
|
+
readonly date: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A row's overrides; the free-text keys never name a row, so a string here is none. */
|
|
32
|
+
const cellsOf = (v: RowOverride | string | undefined): RowOverride =>
|
|
33
|
+
typeof v === "object" ? v : {};
|
|
34
|
+
|
|
7
35
|
/**
|
|
8
36
|
* A scorecard with the four sections the template requires, all green. `over` replaces individual
|
|
9
37
|
* cells: `{ cites: { date: "2020-01-01" } }`, `{ verdict: "…" }`, `{ deadline: "2026-08-18" }`,
|
|
@@ -11,22 +39,23 @@ export const FAR = "2027-12-31";
|
|
|
11
39
|
* inserted BEFORE the first heading (the only way to plant a row under no heading at all).
|
|
12
40
|
*/
|
|
13
41
|
export function scorecard(
|
|
14
|
-
over = {},
|
|
15
|
-
today = new Date().toISOString().slice(0, 10),
|
|
16
|
-
) {
|
|
17
|
-
const r = (id, status = "☑", date = today) => ({
|
|
42
|
+
over: ScorecardOverrides = {},
|
|
43
|
+
today: string = new Date().toISOString().slice(0, 10),
|
|
44
|
+
): string {
|
|
45
|
+
const r = (id: string, status = "☑", date = today): Row => ({
|
|
18
46
|
id,
|
|
19
47
|
status,
|
|
20
48
|
date,
|
|
21
|
-
...(over[id]
|
|
49
|
+
...cellsOf(over[id]),
|
|
22
50
|
});
|
|
23
|
-
const row = (o, ...mid) =>
|
|
51
|
+
const row = (o: Row, ...mid: string[]): string =>
|
|
24
52
|
`| ${o.id} | work | ${o.skill ?? "skill"} | ${mid.length ? mid.join(" | ") + " | " : ""}${o.status} | ${o.date} | ${o.result ?? "result"} | — |`;
|
|
25
53
|
// The GATES `Requires` cell, canonical by default so the baseline is silent — `{ structure: {
|
|
26
54
|
// requires: "render" } }` plants a dropped edge. `harden` deliberately declares four of its five
|
|
27
55
|
// canonical inputs: the fifth (`priordelta`) has no row in this fixture, and the clean case asserts that the checker stays
|
|
28
56
|
// quiet about an edge there is nowhere to point at.
|
|
29
|
-
const req = (id, dflt) =>
|
|
57
|
+
const req = (id: string, dflt: string): string =>
|
|
58
|
+
cellsOf(over[id]).requires ?? dflt;
|
|
30
59
|
const verdict =
|
|
31
60
|
over.verdict ??
|
|
32
61
|
"Submit-ready — every gate green, artifact reproduces clean, nothing blocking.";
|
|
@@ -8,14 +8,14 @@ import { symlinkSync } from "node:fs";
|
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { test } from "vitest";
|
|
11
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
11
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
12
12
|
|
|
13
13
|
const SCRIPT = join(
|
|
14
14
|
dirname(fileURLToPath(import.meta.url)),
|
|
15
15
|
"generated-code.mjs",
|
|
16
16
|
);
|
|
17
17
|
const root = useTempDir("generated-code-");
|
|
18
|
-
const run = (...args) => runNode(SCRIPT, args);
|
|
18
|
+
const run = (...args: string[]) => runNode(SCRIPT, args);
|
|
19
19
|
|
|
20
20
|
test("no argument prints the usage; a directory that does not exist scanned nothing, and says so", () => {
|
|
21
21
|
assert.deepEqual(run(), {
|
|
@@ -41,7 +41,7 @@ test("repro/: a dangling link is passed over; skipped trees are named, more than
|
|
|
41
41
|
const dir = writeTree(join(root, "paper"), {
|
|
42
42
|
...deep,
|
|
43
43
|
"repro/.cache/x.py": "",
|
|
44
|
-
//
|
|
44
|
+
// A fixture directory the scan must skip, not an install location.
|
|
45
45
|
"repro/node_modules/x.js": "",
|
|
46
46
|
"repro/__pycache__/x.py": "",
|
|
47
47
|
// Draws randomness unseeded: a NO_SEED finding, which the reasonless row below waves through.
|
|
@@ -11,7 +11,7 @@ import { cpSync, rmSync, writeFileSync } from "node:fs";
|
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { afterEach, test } from "vitest";
|
|
14
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
14
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
15
15
|
|
|
16
16
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
17
17
|
const SCRIPT = join(HERE, "ledger.mjs");
|
|
@@ -10,10 +10,10 @@ import { utimesSync } from "node:fs";
|
|
|
10
10
|
import { dirname, join } from "node:path";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { test } from "vitest";
|
|
13
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
13
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
14
14
|
import { check, newestSourceDate, parseStatus } from "./pipeline-check.mjs";
|
|
15
15
|
import { readdirSync } from "node:fs";
|
|
16
|
-
import { scorecard } from "./fixtures/scorecard.
|
|
16
|
+
import { scorecard } from "./fixtures/scorecard.ts";
|
|
17
17
|
|
|
18
18
|
const SCRIPT = join(
|
|
19
19
|
dirname(fileURLToPath(import.meta.url)),
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* moved to `eslint-rules/pipeline-status.mjs`, and their cases — to `eslint-rules/pipeline-status.harness.mjs`.
|
|
6
6
|
* `npx vigiles test .claude/skills/paper-pipeline/scripts/pipeline-check.harness.mjs`.
|
|
7
7
|
*
|
|
8
|
-
* WHY THIS EXISTS ALONGSIDE THE FIXTURE TEST IN hooks.harness.
|
|
8
|
+
* WHY THIS EXISTS ALONGSIDE THE FIXTURE TEST IN hooks.harness.ts. That one runs the checker over
|
|
9
9
|
* `scripts/fixtures/dirty/`, a scorecard carrying every defect at once, and asserts each kind
|
|
10
10
|
* appears somewhere in the output. It cannot answer the question that matters when a check breaks:
|
|
11
11
|
* WHICH defect produced WHICH finding. A checker that reports `stale-continuous` for the wrong
|
|
@@ -40,7 +40,7 @@ import { tmpdir } from "node:os";
|
|
|
40
40
|
import { join, dirname } from "node:path";
|
|
41
41
|
import { fileURLToPath } from "node:url";
|
|
42
42
|
import { consumerRoot } from "./consumer.mjs";
|
|
43
|
-
import { scorecard as makeScorecard } from "./fixtures/scorecard.
|
|
43
|
+
import { scorecard as makeScorecard } from "./fixtures/scorecard.ts";
|
|
44
44
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
45
45
|
|
|
46
46
|
const ROOT = consumerRoot();
|
|
@@ -109,10 +109,7 @@ import { readFileSync, readdirSync, statSync, existsSync } from "node:fs";
|
|
|
109
109
|
import { dirname, join, resolve } from "node:path";
|
|
110
110
|
import { execFileSync } from "node:child_process";
|
|
111
111
|
import MarkdownIt from "markdown-it";
|
|
112
|
-
import {
|
|
113
|
-
headings as mdHeadings,
|
|
114
|
-
requireMarkdown,
|
|
115
|
-
} from "../../../lib/markdown.mjs";
|
|
112
|
+
import { headings as mdHeadings, requireMarkdown } from "#lib/markdown";
|
|
116
113
|
import { isMain } from "./consumer.mjs";
|
|
117
114
|
|
|
118
115
|
// Markup is parsed with a parser (`CLAUDE.md`, 2026-08-11). This script already parsed tables
|
|
@@ -48,10 +48,7 @@
|
|
|
48
48
|
*/
|
|
49
49
|
import { readFileSync, existsSync } from "node:fs";
|
|
50
50
|
import { join } from "node:path";
|
|
51
|
-
import {
|
|
52
|
-
headings as mdHeadings,
|
|
53
|
-
requireMarkdown,
|
|
54
|
-
} from "../../../lib/markdown.mjs";
|
|
51
|
+
import { headings as mdHeadings, requireMarkdown } from "#lib/markdown";
|
|
55
52
|
import { isMain } from "./consumer.mjs";
|
|
56
53
|
|
|
57
54
|
// Markup is parsed with a parser (`CLAUDE.md`, 2026-08-11). We fail rather than degrade: without
|
|
@@ -11,7 +11,7 @@ import assert from "node:assert/strict";
|
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { test } from "vitest";
|
|
14
|
-
import { runNode, useTempDir, writeTree } from "../../../test/support.
|
|
14
|
+
import { runNode, useTempDir, writeTree } from "../../../test/support.ts";
|
|
15
15
|
import { bodyOf, findings } from "./population-map.mjs";
|
|
16
16
|
|
|
17
17
|
const SCRIPT = join(
|