paperlint 3.1.0 → 3.1.2
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 +28 -41
- package/.github/workflows/dependabot-automerge.yml +1 -1
- package/CLAUDE.md +21 -105
- package/CONTRIBUTING.md +23 -25
- package/README.md +11 -7
- package/bin/paperlint.test.mjs +45 -0
- package/dist/adapters/node/files.io.d.ts +2 -0
- package/dist/adapters/node/files.io.d.ts.map +1 -1
- package/dist/adapters/node/files.io.js +3 -2
- package/dist/adapters/node/files.io.js.map +1 -1
- package/dist/adapters/pdfjs/fill.d.ts +15 -4
- package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
- package/dist/adapters/pdfjs/fill.js +31 -21
- package/dist/adapters/pdfjs/fill.js.map +1 -1
- package/dist/adapters/references/clock.io.d.ts +5 -0
- package/dist/adapters/references/clock.io.d.ts.map +1 -0
- package/dist/adapters/references/clock.io.js +7 -0
- package/dist/adapters/references/clock.io.js.map +1 -0
- package/dist/adapters/references/index.d.ts +24 -2
- package/dist/adapters/references/index.d.ts.map +1 -1
- package/dist/adapters/references/index.js +131 -12
- package/dist/adapters/references/index.js.map +1 -1
- package/dist/adapters/references/pool.d.ts +8 -0
- package/dist/adapters/references/pool.d.ts.map +1 -0
- package/dist/adapters/references/pool.js +19 -0
- package/dist/adapters/references/pool.js.map +1 -0
- package/dist/build.d.ts +14 -2
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +17 -11
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts +27 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +71 -55
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +27 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +4 -3
- package/dist/doctor.js.map +1 -1
- package/dist/domain/lookup-cache.d.ts +75 -0
- package/dist/domain/lookup-cache.d.ts.map +1 -0
- package/dist/domain/lookup-cache.js +137 -0
- package/dist/domain/lookup-cache.js.map +1 -0
- package/dist/domain/result.d.ts +0 -2
- package/dist/domain/result.d.ts.map +1 -1
- package/dist/domain/result.js +0 -4
- package/dist/domain/result.js.map +1 -1
- package/dist/hooks-settings.d.ts +8 -5
- package/dist/hooks-settings.d.ts.map +1 -1
- package/dist/hooks-settings.js +32 -32
- package/dist/hooks-settings.js.map +1 -1
- package/dist/init.d.ts +8 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +3 -3
- package/dist/init.js.map +1 -1
- package/dist/latex-log.d.ts +0 -2
- package/dist/latex-log.d.ts.map +1 -1
- package/dist/latex-log.js +7 -13
- package/dist/latex-log.js.map +1 -1
- package/dist/link-skills.d.ts +15 -2
- package/dist/link-skills.d.ts.map +1 -1
- package/dist/link-skills.js +36 -20
- package/dist/link-skills.js.map +1 -1
- package/dist/paper-files.d.ts.map +1 -1
- package/dist/paper-files.js +6 -4
- package/dist/paper-files.js.map +1 -1
- package/dist/pdf-facts.d.ts +11 -0
- package/dist/pdf-facts.d.ts.map +1 -1
- package/dist/pdf-facts.js +16 -18
- package/dist/pdf-facts.js.map +1 -1
- package/dist/pdf-geometry.js +1 -1
- package/dist/pdf-geometry.js.map +1 -1
- package/dist/ports/check-references.d.ts +12 -2
- package/dist/ports/check-references.d.ts.map +1 -1
- package/dist/ports/check-references.js +0 -5
- package/dist/ports/check-references.js.map +1 -1
- package/dist/presets.d.ts +2 -0
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +3 -1
- package/dist/presets.js.map +1 -1
- package/dist/references.d.ts +11 -3
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +63 -15
- package/dist/references.js.map +1 -1
- package/dist/tex-requirements.d.ts +8 -0
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +6 -5
- package/dist/tex-requirements.js.map +1 -1
- package/dist/toolchain.d.ts +3 -2
- package/dist/toolchain.d.ts.map +1 -1
- package/dist/toolchain.js +4 -5
- package/dist/toolchain.js.map +1 -1
- package/dist/venue-rules.d.ts.map +1 -1
- package/dist/venue-rules.js +11 -9
- package/dist/venue-rules.js.map +1 -1
- package/docs/prior-art/README.md +11 -10
- package/docs/prior-art/citation-checkers.md +174 -0
- package/docs/prior-art/test-tooling.md +7 -30
- package/docs/references.md +126 -0
- package/docs/testing.md +118 -0
- package/docs/toolchain.md +6 -4
- package/eslint-rules/install-path-literals.harness.mjs +17 -1
- package/eslint-rules/latex-language.harness.mjs +3 -3
- package/eslint-rules/latex-language.mjs +12 -9
- package/eslint-rules/latex-language.test.mjs +200 -0
- package/eslint-rules/paper-research-question.harness.mjs +73 -7
- package/eslint-rules/paper-stages.harness.mjs +9 -14
- package/eslint-rules/paper-stages.test.mjs +135 -0
- package/eslint-rules/paper-typography.mjs +9 -2
- package/eslint-rules/paper-typography.test.mjs +146 -1
- package/eslint-rules/pdf-last-page-balance.harness.mjs +63 -7
- package/eslint-rules/review-frontmatter.mjs +2 -1
- package/eslint-rules/review-frontmatter.test.mjs +37 -1
- package/eslint-rules/temp-root-realpath.harness.mjs +49 -0
- package/eslint-rules/tex-build.mjs +13 -13
- package/eslint.config.mjs +6 -2
- package/hooks/hooks.harness.mjs +6 -11
- package/hooks/paper-edit-guard.hook.mjs +2 -2
- package/hooks/paper-edit-guard.test.mjs +61 -0
- package/hooks/paper-skills-nudge.hook.mjs +2 -2
- package/hooks/paper-skills-nudge.test.mjs +38 -0
- package/hooks/paper-status-gates.test.mjs +42 -0
- package/lib/agent-cli-version.harness.mjs +7 -0
- package/lib/check.d.mts +17 -0
- package/lib/check.mjs +50 -0
- package/lib/check.test.ts +67 -0
- package/lib/markdown.mjs +16 -69
- package/lib/markdown.test.mjs +246 -0
- package/lib/paper-config.harness.mjs +28 -9
- package/lib/paper-config.mjs +7 -2
- package/lib/skill-checks.mjs +18 -46
- package/lib/skill-checks.test.mjs +297 -0
- package/lib/skill-corpus.mjs +11 -13
- package/lib/skill-corpus.test.mjs +54 -0
- package/lib/skill-trigger-cases.harness.mjs +57 -4
- package/package.json +6 -5
- package/scripts/check.harness.mjs +4 -10
- package/scripts/check.mjs +45 -42
- package/scripts/check.test.mjs +104 -0
- package/scripts/coverage-config.test.ts +406 -0
- package/scripts/eslint-report-guard.test.mjs +48 -0
- package/scripts/harness-api.frozen.json +0 -2
- package/scripts/layer-legacy-frozen.d.mts +9 -1
- package/scripts/layer-legacy-frozen.mjs +28 -11
- package/scripts/layer-legacy-frozen.test.ts +143 -1
- package/scripts/rules-are-content-only.harness.mjs +3 -11
- package/scripts/rules-are-content-only.mjs +29 -19
- package/scripts/rules-are-content-only.test.mjs +61 -0
- package/scripts/rules-see-files.mjs +11 -9
- package/scripts/rules-see-files.test.mjs +71 -0
- package/scripts/test.mjs +44 -0
- package/scripts/test.test.mjs +52 -0
- package/skills/grade-paper-writing/__snapshots__/prose-lint.test.mjs.snap +57 -0
- package/skills/grade-paper-writing/prose-lint.mjs +31 -12
- package/skills/grade-paper-writing/prose-lint.test.mjs +153 -0
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +3 -3
- package/skills/paper-pipeline/references/artifact-checklist.md +7 -7
- package/skills/paper-pipeline/scripts/README.md +13 -132
- package/skills/paper-pipeline/scripts/announce.test.mjs +102 -0
- package/skills/paper-pipeline/scripts/artifact-coverage.test.mjs +86 -0
- package/skills/paper-pipeline/scripts/consumer.d.mts +8 -1
- package/skills/paper-pipeline/scripts/consumer.harness.mjs +3 -3
- package/skills/paper-pipeline/scripts/consumer.mjs +13 -25
- package/skills/paper-pipeline/scripts/consumer.test.mjs +113 -0
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +9 -4
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +380 -0
- package/skills/paper-pipeline/scripts/fixtures/scorecard.mjs +71 -0
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +4 -4
- package/skills/paper-pipeline/scripts/generated-code.mjs +3 -2
- package/skills/paper-pipeline/scripts/generated-code.test.mjs +62 -0
- package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +302 -0
- package/skills/paper-pipeline/scripts/ledger.mjs +1 -1
- package/skills/paper-pipeline/scripts/{ledger.selftest.mjs → ledger.test.mjs} +44 -76
- package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +474 -0
- package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +2 -63
- package/skills/paper-pipeline/scripts/pipeline-check.mjs +37 -21
- package/skills/paper-pipeline/scripts/pipeline-edges.mjs +2 -2
- package/skills/paper-pipeline/scripts/pipeline-edges.test.mjs +73 -0
- package/skills/paper-pipeline/scripts/population-map.harness.mjs +4 -47
- package/skills/paper-pipeline/scripts/population-map.mjs +12 -2
- package/skills/paper-pipeline/scripts/population-map.test.mjs +154 -0
- package/skills/paper-pipeline/scripts/provenance.harness.mjs +26 -0
- package/skills/paper-pipeline/scripts/round-diff.harness.mjs +1 -2
- package/skills/paper-pipeline/scripts/round-diff.mjs +13 -6
- package/skills/paper-pipeline/scripts/round-diff.test.mjs +159 -0
- package/skills/paper-pipeline/scripts/run-mechanical.mjs +30 -6
- package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +468 -0
- package/skills/paper-pipeline/scripts/status.mjs +2 -2
- package/skills/paper-pipeline/scripts/status.test.mjs +232 -0
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +2 -2
- package/skills/render-paper/checkers-requirements.txt +30 -19
- package/skills/render-paper/ensure-checkers.sh +20 -4
- package/skills/render-paper/extract-pdf-facts.harness.mjs +56 -7
- package/skills/tighten-paper/__snapshots__/structure.test.mjs.snap +133 -0
- package/skills/tighten-paper/structure.test.mjs +116 -0
- package/skills/verify-citations/SKILL.md +30 -14
- package/skills/verify-citations/SKILL.md.spec.ts +29 -13
- package/skills/verify-citations/scripts/__snapshots__/verify-cites.net.test.mjs.snap +253 -0
- package/skills/verify-citations/scripts/bib-authors.check.test.mjs +274 -0
- package/skills/verify-citations/scripts/bib-authors.cli.test.mjs +178 -0
- package/skills/verify-citations/scripts/bib-authors.mjs +6 -6
- package/skills/verify-citations/scripts/verify-cites.cli.test.mjs +160 -0
- package/skills/verify-citations/scripts/verify-cites.mjs +360 -215
- package/skills/verify-citations/scripts/verify-cites.net.test.mjs +588 -0
- package/skills/verify-citations/scripts/verify-cites.test.mjs +151 -5
- package/src/adapters/banal/failure.test.ts +70 -1
- package/src/adapters/banal/index.test.ts +16 -0
- package/src/adapters/banal/output.test.ts +5 -0
- package/src/adapters/curl/download.test.ts +43 -1
- package/src/adapters/memory/index.test.ts +25 -0
- package/src/adapters/node/files.io.ts +3 -2
- package/src/adapters/node/files.test.ts +13 -1
- package/src/adapters/node/process.test.ts +38 -0
- package/src/adapters/pdfjs/fill.test.ts +34 -0
- package/src/adapters/pdfjs/fill.ts +44 -25
- package/src/adapters/references/clock.io.ts +8 -0
- package/src/adapters/references/index.test.ts +560 -0
- package/src/adapters/references/index.ts +203 -19
- package/src/adapters/references/pool.test.ts +31 -0
- package/src/adapters/references/pool.ts +24 -0
- package/src/build-engine.harness.mjs +3 -7
- package/src/build-engine.test.ts +137 -0
- package/src/build.harness.mjs +5 -9
- package/src/build.test.ts +362 -0
- package/src/build.ts +23 -12
- package/src/cli.harness.mjs +10 -17
- package/src/cli.test.ts +584 -0
- package/src/cli.ts +112 -66
- package/src/doctor.harness.mjs +3 -8
- package/src/doctor.test.ts +64 -0
- package/src/doctor.ts +12 -4
- package/src/domain/lookup-cache.test.ts +178 -0
- package/src/domain/lookup-cache.ts +202 -0
- package/src/domain/result.test.ts +4 -0
- package/src/domain/result.ts +0 -5
- package/src/engine.harness.mjs +27 -7
- package/src/facts-file.test.ts +110 -0
- package/src/hooks-settings.harness.mjs +43 -13
- package/src/hooks-settings.ts +41 -35
- package/src/init.test.ts +308 -5
- package/src/init.ts +3 -3
- package/src/latex-log.harness.mjs +32 -7
- package/src/latex-log.ts +6 -13
- package/src/latex-loop.harness.mjs +8 -7
- package/src/link-skills.harness.mjs +3 -8
- package/src/link-skills.test.ts +105 -0
- package/src/link-skills.ts +75 -21
- package/src/new-paper.harness.mjs +3 -7
- package/src/new-paper.test.ts +31 -1
- package/src/paper-files.test.ts +12 -0
- package/src/paper-files.ts +9 -5
- package/src/paper-settings.test.ts +20 -0
- package/src/pdf-facts.harness.mjs +3 -6
- package/src/pdf-facts.test.ts +144 -0
- package/src/pdf-facts.ts +17 -19
- package/src/pdf-geometry.harness.mjs +3 -7
- package/src/pdf-geometry.ts +1 -1
- package/src/ports/check-references.ts +16 -2
- package/src/presets.test.ts +2 -0
- package/src/presets.ts +7 -1
- package/src/references.test.ts +257 -10
- package/src/references.ts +93 -17
- package/src/rules-config.harness.mjs +10 -8
- package/src/structure.harness.mjs +3 -7
- package/src/tex-requirements.harness.mjs +34 -7
- package/src/tex-requirements.ts +12 -6
- package/src/toolchain.harness.mjs +3 -7
- package/src/toolchain.test.ts +280 -0
- package/src/toolchain.ts +8 -7
- package/src/venue-rules.test.ts +60 -0
- package/src/venue-rules.ts +13 -11
- package/action.mutations.mjs +0 -162
- package/eslint-rules/install-path-literals.mutations.mjs +0 -62
- package/eslint-rules/latex-language.mutations.mjs +0 -196
- package/eslint-rules/paper-research-question.mutations.mjs +0 -127
- package/eslint-rules/paper-stages.mutations.mjs +0 -81
- package/eslint-rules/papers.mutations.mjs +0 -186
- package/eslint-rules/temp-root-realpath.mutations.mjs +0 -99
- package/eslint-rules/tex-build.mutations.mjs +0 -258
- package/hooks/hooks.mutations.mjs +0 -337
- package/lib/agent-cli-version.mutations.mjs +0 -109
- package/lib/mutation-driver.harness.mjs +0 -227
- package/lib/mutation-driver.mjs +0 -397
- package/lib/mutation-driver.mutations.mjs +0 -68
- package/lib/paper-config.mutations.mjs +0 -143
- package/lib/skill-trigger-cases.mutations.mjs +0 -65
- package/scripts/check.mutations.mjs +0 -110
- package/scripts/exclusive.mjs +0 -138
- package/scripts/mutation-batteries-frozen.harness.mjs +0 -204
- package/scripts/mutation-batteries-frozen.mjs +0 -238
- package/scripts/mutation-batteries.frozen.json +0 -108
- package/scripts/rules-are-content-only.mutations.mjs +0 -81
- package/scripts/rules-see-files.mutations.mjs +0 -131
- package/scripts/run-mutations.mjs +0 -100
- package/skills/paper-pipeline/scripts/artifact-coverage.mutations.mjs +0 -218
- package/skills/paper-pipeline/scripts/consumer.mutations.mjs +0 -190
- package/skills/paper-pipeline/scripts/extract-ref-facts.mutations.mjs +0 -54
- package/skills/paper-pipeline/scripts/generated-code.mutations.mjs +0 -254
- package/skills/paper-pipeline/scripts/pipeline-check.mutations.mjs +0 -54
- package/skills/paper-pipeline/scripts/population-map.mutations.mjs +0 -65
- package/skills/paper-pipeline/scripts/population-map.selftest.mjs +0 -122
- package/skills/paper-pipeline/scripts/provenance.mutations.mjs +0 -59
- package/skills/paper-pipeline/scripts/round-diff.mutations.mjs +0 -276
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.mutations.mjs +0 -65
- package/skills/skill-contract.mutations.mjs +0 -179
- package/src/build.mutations.mjs +0 -196
- package/src/cli.mutations.mjs +0 -414
- package/src/doctor.mutations.mjs +0 -175
- package/src/hooks-settings.mutations.mjs +0 -99
- package/src/link-skills.mutations.mjs +0 -140
- package/src/new-paper.mutations.mjs +0 -65
- package/src/structure.mutations.mjs +0 -83
|
@@ -42,8 +42,7 @@ function applyState(ops, fn, args, s) {
|
|
|
42
42
|
/** Every drawn character, in content order, with the fill it was drawn in. */
|
|
43
43
|
export function drawnCharacters(ops, list) {
|
|
44
44
|
const s = { cur: { fill: { kind: "unknown" }, mode: 0 }, stack: [] };
|
|
45
|
-
const
|
|
46
|
-
const fills = [];
|
|
45
|
+
const drawn = [];
|
|
47
46
|
list.fnArray.forEach((fn, i) => {
|
|
48
47
|
const args = list.argsArray[i];
|
|
49
48
|
if (applyState(ops, fn, args, s))
|
|
@@ -51,22 +50,25 @@ export function drawnCharacters(ops, list) {
|
|
|
51
50
|
if (fn !== ops.showText && fn !== ops.showSpacedText)
|
|
52
51
|
return;
|
|
53
52
|
const fill = s.cur.mode === 3 ? { kind: "invisible" } : s.cur.fill;
|
|
54
|
-
for (const ch of squeeze(glyphText(args)))
|
|
55
|
-
|
|
56
|
-
fills.push(fill);
|
|
57
|
-
}
|
|
53
|
+
for (const ch of squeeze(glyphText(args)))
|
|
54
|
+
drawn.push({ ch, fill });
|
|
58
55
|
});
|
|
59
|
-
return
|
|
56
|
+
return drawn;
|
|
60
57
|
}
|
|
61
58
|
/** How far ahead the walk looks for an item it cannot find where it expects it. */
|
|
62
59
|
export const LOOKAHEAD = 4000;
|
|
63
|
-
/**
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Where `want` starts in `drawn`, at or after `from` within the look-ahead, and the fill it was
|
|
62
|
+
* drawn in — or null. The fill comes from the matched element itself, not a second lookup.
|
|
63
|
+
*/
|
|
64
|
+
function findRun(drawn, want, from) {
|
|
65
|
+
const window = drawn.slice(from, from + LOOKAHEAD);
|
|
66
|
+
for (const [i, d] of window.entries()) {
|
|
67
|
+
const at = from + i;
|
|
68
|
+
if (want.every((ch, k) => drawn[at + k]?.ch === ch))
|
|
69
|
+
return { at, fill: d.fill };
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
70
72
|
}
|
|
71
73
|
/**
|
|
72
74
|
* The fill of each text item. pdf.js's text content carries no colour, so the operator list is
|
|
@@ -75,17 +77,25 @@ function findRun(chars, want, from) {
|
|
|
75
77
|
* a missed match can keep light text, never drop dark text.
|
|
76
78
|
*/
|
|
77
79
|
export function fillsOf(ops, list, items) {
|
|
78
|
-
|
|
80
|
+
return fillsFor(ops, list, items, (text) => text).map((p) => p.fill);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Each item paired with its fill — `fillsOf` for items that are not bare strings, so a caller never
|
|
84
|
+
* matches the two lists up by index.
|
|
85
|
+
*/
|
|
86
|
+
export function fillsFor(ops, list, items, textOf) {
|
|
87
|
+
const drawn = drawnCharacters(ops, list);
|
|
79
88
|
let at = 0;
|
|
80
|
-
|
|
89
|
+
const fillOf = (text) => {
|
|
81
90
|
const want = [...squeeze(text)];
|
|
82
91
|
if (want.length === 0)
|
|
83
92
|
return { kind: "unknown" };
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
93
|
+
const hit = findRun(drawn, want, at);
|
|
94
|
+
if (hit === null)
|
|
86
95
|
return { kind: "unknown" };
|
|
87
|
-
at =
|
|
88
|
-
return
|
|
89
|
-
}
|
|
96
|
+
at = hit.at + want.length;
|
|
97
|
+
return hit.fill;
|
|
98
|
+
};
|
|
99
|
+
return items.map((item) => ({ item, fill: fillOf(textOf(item)) }));
|
|
90
100
|
}
|
|
91
101
|
//# sourceMappingURL=fill.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fill.js","sourceRoot":"","sources":["../../../src/adapters/pdfjs/fill.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"fill.js","sourceRoot":"","sources":["../../../src/adapters/pdfjs/fill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The clock, for the lookup cache: the day an answer was fetched, in UTC. */
|
|
2
|
+
export declare const todayUtc: () => string;
|
|
3
|
+
/** Wait `ms` — DBLP's pace between requests. */
|
|
4
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
|
5
|
+
//# sourceMappingURL=clock.io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.io.d.ts","sourceRoot":"","sources":["../../../src/adapters/references/clock.io.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,eAAO,MAAM,QAAQ,QAAO,MAA+C,CAAC;AAE5E,gDAAgD;AAChD,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CAG3C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** The clock, for the lookup cache: the day an answer was fetched, in UTC. */
|
|
2
|
+
export const todayUtc = () => new Date().toISOString().slice(0, 10);
|
|
3
|
+
/** Wait `ms` — DBLP's pace between requests. */
|
|
4
|
+
export const sleep = (ms) => new Promise((r) => {
|
|
5
|
+
setTimeout(r, ms);
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=clock.io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.io.js","sourceRoot":"","sources":["../../../src/adapters/references/clock.io.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAW,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAE5E,gDAAgD;AAChD,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CACjD,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;IAChB,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
|
@@ -2,12 +2,34 @@
|
|
|
2
2
|
* The online reference checks, as the `CheckReferences` port: `verify-cites` (the cited work
|
|
3
3
|
* exists, the title matches — Crossref, OpenAlex, Semantic Scholar, arXiv) and `bib-authors` (the
|
|
4
4
|
* authors are the published version's — DBLP). Both ship in this package's verify-citations skill;
|
|
5
|
-
* this adapter only runs them
|
|
5
|
+
* this adapter only runs them, shapes their answers, and serves them from the paper's lookup cache.
|
|
6
|
+
*
|
|
7
|
+
* 🔴 THE CACHE HOLDS ANSWERS, AND ONLY THE CHECKERS' OWN SEAMS TOUCH IT. verify-cites takes a
|
|
8
|
+
* `cache` object keyed per resolver × identifier and stores only successful responses; it is
|
|
9
|
+
* handed the paper's cached responses and whatever it adds is new. bib-authors takes a `lookup`
|
|
10
|
+
* (title → DBLP hits) and a `pause`; the lookup is wrapped to answer from the cache, and the pause
|
|
11
|
+
* is skipped after a cached answer — DBLP's 900 ms pace and its retries run only for titles never
|
|
12
|
+
* answered. Neither checker's logic changes. Verdicts are derived from the answers on every build
|
|
13
|
+
* (`domain/lookup-cache.ts` says why).
|
|
6
14
|
*
|
|
7
15
|
* "Not checked" is decided up front, by one request: when Crossref cannot be reached at all, the
|
|
8
16
|
* checkers would degrade every entry to `unresolvable` / `unchecked`, which reads like a result.
|
|
9
|
-
* Saying `not-checked` with the reason is the honest record.
|
|
17
|
+
* Saying `not-checked` with the reason is the honest record. That request is skipped when every
|
|
18
|
+
* question this bibliography would ask is already answered in the cache: a warm build is offline.
|
|
10
19
|
*/
|
|
11
20
|
import type { CheckReferences } from "../../ports/check-references.ts";
|
|
21
|
+
/**
|
|
22
|
+
* The key a DBLP answer is stored under in the lookup cache: the title's identity (verify-cites'
|
|
23
|
+
* `titleIdentity` — the same rule its own title keys use, so the two caches cannot drift), hashed.
|
|
24
|
+
* A re-cased or re-braced title keeps its answer; `C` and `C++` do not share one.
|
|
25
|
+
*/
|
|
26
|
+
export declare const dblpTitleKey: (title: string) => string;
|
|
27
|
+
export interface ReferencesCheckerOptions {
|
|
28
|
+
/** The day a new answer is stamped with, YYYY-MM-DD. */
|
|
29
|
+
readonly today: () => string;
|
|
30
|
+
}
|
|
31
|
+
/** The checker, with its clock injected; `onlineReferences` is the one the CLI wires. */
|
|
32
|
+
export declare const referencesChecker: ({ today }: ReferencesCheckerOptions) => CheckReferences;
|
|
33
|
+
/** The checker the CLI wires: the real clock. */
|
|
12
34
|
export declare const onlineReferences: CheckReferences;
|
|
13
35
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/references/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/references/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,iCAAiC,CAAC;AA+HzC;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MACiC,CAAC;AAE/E,MAAM,WAAW,wBAAwB;IACvC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;CAC9B;AAsED,yFAAyF;AACzF,eAAO,MAAM,iBAAiB,GAC3B,WAAW,wBAAwB,KAAG,eAgDtC,CAAC;AAEJ,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,EAAE,eAE7B,CAAC"}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import { freshPart, } from "../../domain/lookup-cache.js";
|
|
2
|
+
import { sha256Hex } from "../../domain/sha256.js";
|
|
3
|
+
import { mapLimit } from "./pool.js";
|
|
1
4
|
import { unreachable } from "./reach.io.js";
|
|
5
|
+
import { sleep, todayUtc } from "./clock.io.js";
|
|
6
|
+
/** Citations looked up at once (#107). */
|
|
7
|
+
const LOOKUPS_IN_FLIGHT = 6;
|
|
2
8
|
// @ts-expect-error — a skill script in .mjs, it has no types
|
|
3
9
|
import * as cites from "../../../skills/verify-citations/scripts/verify-cites.mjs";
|
|
4
10
|
// @ts-expect-error — a skill script in .mjs, it has no types
|
|
@@ -17,12 +23,20 @@ const authorsOf = (key, a) => a.findings.some((f) => f.key === key)
|
|
|
17
23
|
: a.matched.includes(key)
|
|
18
24
|
? "match"
|
|
19
25
|
: "skipped";
|
|
26
|
+
/**
|
|
27
|
+
* Why a work was not confirmed: verify-cites' reason, then — when some registry refused — which
|
|
28
|
+
* one, so "unresolvable" is not read as "every registry looked and found nothing". Nothing for a
|
|
29
|
+
* confirmed work: a refusal after a confirmation changed nothing.
|
|
30
|
+
*/
|
|
31
|
+
const unconfirmed = (c) => c && c.verdict !== "true"
|
|
32
|
+
? [c.reason, ...(c.refused ?? []).map((r) => `not asked: ${r}`)]
|
|
33
|
+
: [];
|
|
20
34
|
/** One entry's verdict from the two checkers' answers. */
|
|
21
35
|
function entryVerdict(key, found, a) {
|
|
22
36
|
const c = found.find((x) => x.id === key);
|
|
23
37
|
const mismatch = a.findings.find((f) => f.key === key);
|
|
24
38
|
const why = [
|
|
25
|
-
c
|
|
39
|
+
...unconfirmed(c),
|
|
26
40
|
mismatch ? describeAuthors(mismatch) : undefined,
|
|
27
41
|
a.unchecked.find((u) => u.key === key)?.why,
|
|
28
42
|
]
|
|
@@ -35,21 +49,126 @@ function entryVerdict(key, found, a) {
|
|
|
35
49
|
...(why ? { why } : {}),
|
|
36
50
|
};
|
|
37
51
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
/** Whether bib-authors will ask DBLP about this entry — the filter its `checkAuthors` applies. */
|
|
53
|
+
const asksDblp = (e) => Boolean(e.title && e.author) &&
|
|
54
|
+
authors.claimsPublished(e) &&
|
|
55
|
+
!authors.truncated(e.author);
|
|
56
|
+
/** Is every question this bibliography would ask already answered in `cache`? */
|
|
57
|
+
async function fullyCached(citations, entries, cache, store) {
|
|
58
|
+
const asks = await Promise.all(citations.map((c) => cites.wouldAsk(c, store)));
|
|
59
|
+
return (!asks.includes(true) &&
|
|
60
|
+
entries.filter(asksDblp).every((e) => cache.dblp.has(dblpTitleKey(e.title))));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The key a DBLP answer is stored under in the lookup cache: the title's identity (verify-cites'
|
|
64
|
+
* `titleIdentity` — the same rule its own title keys use, so the two caches cannot drift), hashed.
|
|
65
|
+
* A re-cased or re-braced title keeps its answer; `C` and `C++` do not share one.
|
|
66
|
+
*/
|
|
67
|
+
export const dblpTitleKey = (title) => sha256Hex(new TextEncoder().encode(cites.titleIdentity(title))).slice(0, 16);
|
|
68
|
+
/**
|
|
69
|
+
* bib-authors' `lookup` and `pause`, answering from the cached DBLP hits first.
|
|
70
|
+
*
|
|
71
|
+
* 🔴 DBLP IS ASKED UNTIL IT REFUSES ONCE, THEN NOT AT ALL FOR THE REST OF THE RUN (#120). A 429, an
|
|
72
|
+
* HTML page where JSON was asked, a timeout: bib-authors would retry each title three times with
|
|
73
|
+
* backoff, and move on to the next title to do it again — 51 titles × 3 × up to 15 s. After the
|
|
74
|
+
* first refusal every lookup fails at once with the reason, and no pause is waited, so each entry
|
|
75
|
+
* lands in bib-authors' `unchecked` bucket ("never a pass") for the price of ONE request.
|
|
76
|
+
*
|
|
77
|
+
* The 900 ms pace protects DBLP, so it is kept only after an answer DBLP actually gave: not after a
|
|
78
|
+
* cached answer, and not once DBLP is off.
|
|
79
|
+
*/
|
|
80
|
+
function cachedDblp(cache, today) {
|
|
81
|
+
const dblp = new Map(cache.dblp);
|
|
82
|
+
let lastWasCached = false;
|
|
83
|
+
let refused = null;
|
|
84
|
+
return {
|
|
85
|
+
dblp,
|
|
86
|
+
lookup: async (title) => {
|
|
87
|
+
const hit = dblp.get(dblpTitleKey(title));
|
|
88
|
+
lastWasCached = hit !== undefined;
|
|
89
|
+
if (hit)
|
|
90
|
+
return hit.hits;
|
|
91
|
+
if (refused !== null)
|
|
92
|
+
throw new Error(`DBLP refused earlier in this run (${refused})`);
|
|
93
|
+
try {
|
|
94
|
+
const hits = (await authors.dblpHits(title));
|
|
95
|
+
dblp.set(dblpTitleKey(title), { fetched: today(), title, hits });
|
|
96
|
+
return hits;
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
refused = e.message;
|
|
100
|
+
throw new Error(`DBLP refused earlier in this run (${refused})`);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
pause: (ms) => lastWasCached || refused !== null ? Promise.resolve() : sleep(ms),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The cache after a run: the old answers with every new one laid over them, dated today — or the
|
|
108
|
+
* very object passed in when nothing was fetched, so the caller can tell there is nothing to write.
|
|
109
|
+
* "New" is measured against `usable`, the part the run answered from: an answer too old to use was
|
|
110
|
+
* asked again, and its fresh copy replaces the old one. An old answer the run could not refresh
|
|
111
|
+
* (the service refused) stays, and is asked again next build.
|
|
112
|
+
*/
|
|
113
|
+
function grown(loaded, run, today) {
|
|
114
|
+
const { cache, usable } = loaded;
|
|
115
|
+
const { store, dblp } = run;
|
|
116
|
+
const fresh = Object.entries(store).filter(([k]) => !usable.citations.has(k));
|
|
117
|
+
const freshDblp = [...dblp].filter(([k]) => !usable.dblp.has(k));
|
|
118
|
+
if (fresh.length === 0 && freshDblp.length === 0)
|
|
119
|
+
return cache;
|
|
120
|
+
const dated = fresh.map(([k, response]) => [
|
|
121
|
+
k,
|
|
122
|
+
{ fetched: today(), response: response },
|
|
123
|
+
]);
|
|
124
|
+
return {
|
|
125
|
+
citations: new Map([...cache.citations, ...dated]),
|
|
126
|
+
dblp: new Map([...cache.dblp, ...freshDblp]),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** The checker, with its clock injected; `onlineReferences` is the one the CLI wires. */
|
|
130
|
+
export const referencesChecker = ({ today }) => async (bib, cache) => {
|
|
131
|
+
// Answers past MAX_AGE_DAYS are left out, so the run asks them again (and `grown` re-dates them).
|
|
132
|
+
const usable = freshPart(cache, today());
|
|
133
|
+
const citations = cites.parseBib(bib).filter((c) => c.id);
|
|
134
|
+
const parsed = authors.parseBib(bib);
|
|
135
|
+
const store = Object.fromEntries([...usable.citations].map(([k, v]) => [k, v.response]));
|
|
136
|
+
if (!(await fullyCached(citations, parsed, usable, store))) {
|
|
137
|
+
const why = await unreachable();
|
|
138
|
+
if (why !== null)
|
|
139
|
+
return { check: { kind: "not-checked", why }, cache };
|
|
140
|
+
}
|
|
141
|
+
// 🔴 #107: the lookups run LOOKUPS_IN_FLIGHT at a time, and the DBLP author pass runs beside
|
|
142
|
+
// them. Each citation's own requests go to four different services one after another, so a
|
|
143
|
+
// pool of 6 is at most 6 requests to any one of them. The store is shared: two citations with
|
|
144
|
+
// the same identifier may both miss it and ask twice — an extra request, never a different
|
|
145
|
+
// answer.
|
|
146
|
+
// One breaker for the run: a service that refuses is not asked again, not once per citation
|
|
147
|
+
// (#120). Requests already in flight when it starts refusing still land — at most six.
|
|
148
|
+
const breaker = cites.createBreaker();
|
|
149
|
+
const d = cachedDblp(usable, today);
|
|
150
|
+
const [found, a] = await Promise.all([
|
|
151
|
+
mapLimit(citations, LOOKUPS_IN_FLIGHT, (c) => cites.verifyCitationLive(c, {
|
|
152
|
+
cache: store,
|
|
153
|
+
breaker,
|
|
154
|
+
})),
|
|
155
|
+
authors.checkAuthors(parsed, {
|
|
156
|
+
lookup: d.lookup,
|
|
157
|
+
pause: d.pause,
|
|
158
|
+
}),
|
|
159
|
+
]);
|
|
48
160
|
const keys = new Set([
|
|
49
161
|
...found.map((c) => c.id),
|
|
50
162
|
...a.findings.map((f) => f.key),
|
|
51
163
|
]);
|
|
52
164
|
const entries = [...keys].map((key) => entryVerdict(key, found, a));
|
|
53
|
-
return {
|
|
165
|
+
return {
|
|
166
|
+
check: { kind: "checked", entries },
|
|
167
|
+
cache: grown({ cache, usable }, { store, dblp: d.dblp }, today),
|
|
168
|
+
};
|
|
54
169
|
};
|
|
170
|
+
/** The checker the CLI wires: the real clock. */
|
|
171
|
+
export const onlineReferences = referencesChecker({
|
|
172
|
+
today: todayUtc,
|
|
173
|
+
});
|
|
55
174
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/references/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/references/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fn` over `items` with at most `limit` calls in flight, results in `items`' order — a promise
|
|
3
|
+
* pool, the one piece of concurrency this adapter needs, so it is written here rather than
|
|
4
|
+
* depended on. A rejection rejects the whole map, as `Promise.all` would: callers that must not
|
|
5
|
+
* lose the other results catch inside `fn`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mapLimit<T, R>(items: readonly T[], limit: number, fn: (item: T) => Promise<R>): Promise<R[]>;
|
|
8
|
+
//# sourceMappingURL=pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../../src/adapters/references/pool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAAE,CAAC,EACjC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,EAAE,CAAC,CAad"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fn` over `items` with at most `limit` calls in flight, results in `items`' order — a promise
|
|
3
|
+
* pool, the one piece of concurrency this adapter needs, so it is written here rather than
|
|
4
|
+
* depended on. A rejection rejects the whole map, as `Promise.all` would: callers that must not
|
|
5
|
+
* lose the other results catch inside `fn`.
|
|
6
|
+
*/
|
|
7
|
+
export async function mapLimit(items, limit, fn) {
|
|
8
|
+
const out = new Array(items.length);
|
|
9
|
+
let next = 0;
|
|
10
|
+
const worker = async () => {
|
|
11
|
+
while (next < items.length) {
|
|
12
|
+
const i = next++;
|
|
13
|
+
out[i] = await fn(items[i]);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../../src/adapters/references/pool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAmB,EACnB,KAAa,EACb,EAA2B;IAE3B,MAAM,GAAG,GAAQ,IAAI,KAAK,CAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACvC,OAAO,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAM,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC;IACF,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAC9D,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/build.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { getParser } from "@unified-latex/unified-latex-util-parse";
|
|
2
3
|
import { type PdfReader } from "./pdf-facts.ts";
|
|
3
4
|
import type { Files } from "./ports/files.ts";
|
|
4
5
|
import type { MeasureGeometry } from "./ports/measure-geometry.ts";
|
|
@@ -64,11 +65,19 @@ export interface BuildStep {
|
|
|
64
65
|
};
|
|
65
66
|
run(ctx: BuildContext): StepOutcome | Promise<StepOutcome>;
|
|
66
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* unified-latex's own AST types, reached through the parser this package declares. The types
|
|
70
|
+
* package behind it is a transitive dependency, and importing it by name would be depending on it
|
|
71
|
+
* without declaring it.
|
|
72
|
+
*/
|
|
73
|
+
type LatexRoot = ReturnType<ReturnType<typeof getParser>["parse"]>;
|
|
67
74
|
/**
|
|
68
75
|
* `\documentclass[opts]{name}`, read by the unified-latex parser the lint rules already use —
|
|
69
76
|
* so a `\documentclass` inside a comment is a comment, not a class.
|
|
70
77
|
*/
|
|
71
|
-
export declare function parseDocumentclass(tex: string
|
|
78
|
+
export declare function parseDocumentclass(tex: string, { parse }?: {
|
|
79
|
+
parse?: (tex: string) => LatexRoot;
|
|
80
|
+
}): PaperFacts["documentclass"];
|
|
72
81
|
export declare function readFacts(paperDir: string): PaperFacts;
|
|
73
82
|
/**
|
|
74
83
|
* `TEXINPUTS` with `dirs` in front. With nothing set before, the value ENDS in the separator, and
|
|
@@ -106,6 +115,10 @@ export declare const measureStep: BuildStep;
|
|
|
106
115
|
* authors are the published version's (bib-authors) — and record the verdicts in
|
|
107
116
|
* `_build/references.json` for the offline lint rules (`reference-rules.ts`). OPTIONAL and NEVER
|
|
108
117
|
* FAILING: without network the PDF is still built, and the record says `not-checked`.
|
|
118
|
+
*
|
|
119
|
+
* What the services answered is read from and added to `<paper>/repro/references-cache.json`
|
|
120
|
+
* (`references.ts`, `domain/lookup-cache.ts`), committed with the paper, so only a new or edited
|
|
121
|
+
* entry is asked, and an unchanged bibliography is checked with no network at all (#107).
|
|
109
122
|
*/
|
|
110
123
|
export declare const referencesStep: BuildStep;
|
|
111
124
|
/** The build, in order. A new step is one entry here. */
|
|
@@ -167,7 +180,6 @@ export declare function papersIn(root: string, markers?: readonly string[]): str
|
|
|
167
180
|
* paper.pdf removed — a stale PDF must not pass for this build
|
|
168
181
|
*/
|
|
169
182
|
export declare function formatResult(r: BuildResult): string;
|
|
170
|
-
export declare function formatResults(results: readonly BuildResult[]): string;
|
|
171
183
|
/**
|
|
172
184
|
* 🔴 "Nothing to compile" COUNTS AS A REFUSAL on a par with a failed build. Failing to tell these
|
|
173
185
|
* two apart is what once produced a green run over a paper no job had built.
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAyCA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
CHANGED
|
@@ -85,12 +85,14 @@ function argText(arg) {
|
|
|
85
85
|
.map((n) => n.type === "string" ? n.content : n.type === "whitespace" ? " " : "")
|
|
86
86
|
.join("");
|
|
87
87
|
}
|
|
88
|
-
/** A unified-latex AST, or null when the text does not parse. */
|
|
89
|
-
function parseTex(tex) {
|
|
88
|
+
/** A unified-latex AST, or null when the text does not parse. `parse` is unified-latex's parser. */
|
|
89
|
+
function parseTex(tex, parse = (t) => getParser().parse(t)) {
|
|
90
90
|
try {
|
|
91
|
-
return
|
|
91
|
+
return parse(tex);
|
|
92
92
|
}
|
|
93
93
|
catch {
|
|
94
|
+
// The parser recurses per group: ~20 000 nested `{` exhaust the stack (RangeError). Such a
|
|
95
|
+
// file has no class to report, and must not fail the build at `facts` for it.
|
|
94
96
|
return null;
|
|
95
97
|
}
|
|
96
98
|
}
|
|
@@ -98,8 +100,8 @@ function parseTex(tex) {
|
|
|
98
100
|
* `\documentclass[opts]{name}`, read by the unified-latex parser the lint rules already use —
|
|
99
101
|
* so a `\documentclass` inside a comment is a comment, not a class.
|
|
100
102
|
*/
|
|
101
|
-
export function parseDocumentclass(tex) {
|
|
102
|
-
return documentclassOf(parseTex(tex));
|
|
103
|
+
export function parseDocumentclass(tex, { parse } = {}) {
|
|
104
|
+
return documentclassOf(parseTex(tex, parse));
|
|
103
105
|
}
|
|
104
106
|
function documentclassOf(ast) {
|
|
105
107
|
const node = (ast?.content ?? []).find((n) => isMacro(n, "documentclass"));
|
|
@@ -395,6 +397,10 @@ export const measureStep = {
|
|
|
395
397
|
* authors are the published version's (bib-authors) — and record the verdicts in
|
|
396
398
|
* `_build/references.json` for the offline lint rules (`reference-rules.ts`). OPTIONAL and NEVER
|
|
397
399
|
* FAILING: without network the PDF is still built, and the record says `not-checked`.
|
|
400
|
+
*
|
|
401
|
+
* What the services answered is read from and added to `<paper>/repro/references-cache.json`
|
|
402
|
+
* (`references.ts`, `domain/lookup-cache.ts`), committed with the paper, so only a new or edited
|
|
403
|
+
* entry is asked, and an unchanged bibliography is checked with no network at all (#107).
|
|
398
404
|
*/
|
|
399
405
|
export const referencesStep = {
|
|
400
406
|
name: "references",
|
|
@@ -456,9 +462,12 @@ dryRun = false, readPdf = pdfjsReader, projectRoot = env["CLAUDE_PROJECT_DIR"] |
|
|
|
456
462
|
return { run, cwd, env, steps, log, dryRun, readPdf, projectRoot };
|
|
457
463
|
}
|
|
458
464
|
/** Without a checker the record says so — never a pass. The CLI wires the real one. */
|
|
459
|
-
const notWired = async () => ({
|
|
460
|
-
|
|
461
|
-
|
|
465
|
+
const notWired = async (_bib, cache) => ({
|
|
466
|
+
check: {
|
|
467
|
+
kind: "not-checked",
|
|
468
|
+
why: "no reference checker was wired into this build",
|
|
469
|
+
},
|
|
470
|
+
cache,
|
|
462
471
|
});
|
|
463
472
|
/** banal as the measurer, wired from the build's environment: the one piece of root work left here (#76). */
|
|
464
473
|
function defaultMeasurer(b) {
|
|
@@ -610,9 +619,6 @@ function formatRefusal(r) {
|
|
|
610
619
|
const refused = ` ✗ nothing to compile: no ${MAIN}`;
|
|
611
620
|
return r.staleRemoved ? `${refused}\n ${PDF_REMOVED}` : refused;
|
|
612
621
|
}
|
|
613
|
-
export function formatResults(results) {
|
|
614
|
-
return results.map(formatResult).join("\n");
|
|
615
|
-
}
|
|
616
622
|
/**
|
|
617
623
|
* 🔴 "Nothing to compile" COUNTS AS A REFUSAL on a par with a failed build. Failing to tell these
|
|
618
624
|
* two apart is what once produced a green run over a paper no job had built.
|