Commit 2c3d624
Backfill bibliography entries for citations a sync introduces (#226)
* Backfill bibliography entries for citations a sync introduces
sync and forward translate {cite} roles, but the bibliography those keys
resolve against is a shared file that never crossed the boundary:
sync-orchestrator filters changed files to .endsWith('.md'), and the
engine had zero occurrences of .bib or bibtex anywhere in src/. It had no
bibliography concept at all — init only ever got one as a side effect of
copying every non-markdown file wholesale.
Under a strict build (-n -W) Sphinx promotes "could not find bibtex key"
to a hard failure, so the target stopped building on a file nobody
edited. Three manual repairs so far: four lectures in one resync wave,
then 70 keys (see QuantEcon/lecture-python.zh-cn#203), then 21 more on
2026-07-27.
The trigger is demand-driven, not diff-driven. lecture-python-intro's
msy_fishery.md cites five keys lecture-intro.zh-cn lacks and no source PR
touches the bib — the target simply has not translated that lecture yet.
A "did the source diff touch the .bib" design misses that class entirely.
Safety model: a key that already resolves in the target is never a
candidate, and appends never rewrite existing bytes, so an edition that
has localised an entry cannot have it clobbered. The observation that the
estate's bibs are currently strict subsets of their sources is not relied
on anywhere. Ambiguity is reported rather than guessed — a key declared
twice in the source, or differing from an existing target key only in
case, fails the run. Keys already dangling before the run are warnings,
not errors: the run did not introduce them.
Two measured details drive the implementation, both pinned by tests:
- The entry parser tolerates leading whitespace. Eight of the 501 entries
in quant-econ.bib are indented; an ^@-anchored parser finds 493 and
would re-append those eight, producing exactly the duplicate-key -W
failure this prevents.
- The citation walker is stack-based and selectively transparent,
descending into {note}/{exercise}/{warning}/{prf:*} while staying
opaque inside code cells. 71 of 922 citations in lecture-python.myst
(7.7%) live inside admonitions; a flat skip-all-fences walker misses
every one.
New `bibliography` input selects backfill (default), lint or off. An
unrecognised value fails the run — a disabled guard looks exactly like a
passing one.
Refs #117
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Fail closed on bibliography fetch errors, and correct a stale metric
Both from Copilot's review of #226.
1. `fetchBibliographies` swallowed every error from reading the target's
`_config.yml` as "this edition has no bibliography". A rate limit, a
5xx or a permissions failure therefore disabled the guard silently and
the run went green having skipped the check — the exact failure shape
this module exists to remove, and a contradiction of the fail-closed
discipline applied to the bibliography read one function lower. Only a
genuine 404 now means "not applicable"; every other status fails the
run with the status in the message.
The same bare catch guarded the source-side read. Copilot flagged one
instance; the principle covers both. A transient failure there would
have surfaced as a misleading "resolves in neither bibliography" error
attributed to the wrong cause.
2. The module header quoted 45 of 872 citations (5.2%) inside non-code
containers, from the design note. The figure measured against the
current corpus is 71 of 922 (7.7%), which is what the tests and the PR
body state. Corrected, anchored to the commit it was measured at, and
marked indicative — nothing depends on its exact value; it is quoted
to justify why the walker is stack-based rather than flat.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent c43a78f commit 2c3d624
12 files changed
Lines changed: 1666 additions & 17 deletions
File tree
- dist-action
- docs
- developer
- user
- src
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
60 | 70 | | |
61 | 71 | | |
62 | 72 | | |
| |||
0 commit comments