Skip to content

The deterministic target-local-read guard is in neither the action bundle nor sync mode, and is blind to URL-form reads #253

Description

@mmcky

src/cli/target-local-reads.ts is the deterministic answer to the class of problem #182 describes in prompt-prose terms. It works. It is not in the code path that needs it, in three independent ways — so QuantEcon/lecture-intro.zh-cn#285 was clobbered by a sync while a purpose-built guard against exactly that clobber sat in the same repository.

Found while independently validating QuantEcon/data-lectures#51, which needed to answer "what detects an overwritten localisation?" The answer turned out to be "something that exists and never runs."

The guard is real and it works

src/cli/target-local-reads.ts extracts quoted data-file paths from {code-cell} fences, classifies each as exists in target, absent from source, pins the exact lines into the resync prompt via buildPreserveInstruction, and after finalize calls verifyPreservedReads to fail the file loudly rather than write an English revert. Its header cites the 2026-07-22 #107 validation wave and names the country_code_cn.csv / name_chinese case directly.

I bundled it and ran it against the current trees. It correctly returns ["country_code_cn.csv"] for both long_run_growth.md and business_cycle.md in lecture-intro.zh-cn. The logic is not the problem.

Gap 1 — it is not in the action bundle

build-action.mjs bundles only dist/index.js. Grepping the shipped dist-action/index.js at the v0 release:

Symbol Hits in dist-action/index.js
findTargetLocalReads 0
verifyPreservedReads 0
buildPreserveInstruction 0
classifyTargetLocalReads 0
extractDataFileReads 0

Whatever the wiring says, the code is not present in the artifact CI executes.

Gap 2 — it is not wired into sync, the only path repoints take

It is imported in exactly one place: src/cli/commands/forward.ts:43-45, used at :340, :357 and :415. That is the drift-recovery CLI. src/sync-orchestrator.ts never imports it, and nothing else outside __tests__ does.

Meanwhile lecture-python-intro/.github/workflows/sync-translations-zh-cn.yml runs QuantEcon/action-translation@v0 with mode: sync on every merged source PR — which is every repoint PR. So the guard is attached to the manual recovery path and absent from the automatic path that actually causes the damage.

Gap 3 — it cannot see a read expressed as a URL

DATA_PATH matches quoted literal paths and then explicitly skips URLs:

if (/^[a-z]+:\/\//i.test(ref)) continue; // URL, not a repo file

lecture-python.zh-cn expresses the identical #285 localisation class as a URL. lectures/pandas_panel.md:334-335:

map_url = 'https://raw.githubusercontent.com/QuantEcon/lecture-python.zh-cn/refs/heads/main/lectures/_static/country_map.csv'
country_map = pd.read_csv(map_url).set_index('English')['Chinese']

consumed at :348 to build every bar label. lectures/_static/country_map.csv is committed in the target and absent from the English source — textbook target-local read — and findTargetLocalReads returns NONE DETECTED for it purely because the path is written as a URL. Running the guard on this file today gives a clean bill on the one file in the estate most likely to be clobbered next.

Why this is worth fixing before the next repoint set

A sweep of the remaining migration tracks against every translated edition found 15 collision rows, 4 high — posted in full at QuantEcon/workspace-lectures#26. The worst is the high_dim_data fold (P3), which must rewrite four lines in lecture-intro.zh-cn/lectures/heavy_tails.md, three of whose four affected cells carry in-cell localisations.

Two of those revert silently. #285 was caught only because a downstream cell indexed name_chinese and raised KeyError; heavy_tails.md:867 defines country_names = ['美国','日本','印度','意大利'] consumed at :881 as label=country_names[i], and the English source has plain label=c — so the revert produces working code with English legends on the Chinese site and no error anywhere.

Suggested shape of a fix

  1. Import the guard into the sync path (sync-orchestrator.ts / FileProcessor), not only forward.
  2. Add it to the action bundle, and add a build-time assertion that the shipped bundle contains it — the bundling gap is the kind that silently reappears.
  3. Extend DATA_PATH to resolve same-repo raw URLs to repo paths before the URL skip, so gap 3 closes rather than being documented.

Related but distinct: #182 covers the prompt-prose i18n-preservation rule and the font-config class. This issue is about the deterministic guard that already exists for the data-read class. Fixing #182 does not fix this, and vice versa.

Scope note on what the guard would still not cover, even fully wired: translated captions and axis labels, translated code comments and docstrings, localised {download} link text, and font rcParams — rows 1, 3, 5, 6, 7, 8, 9 and 10 of the ws#26 table. The prompt-level rules in src/localization-rules.ts (code-comments, figure-labels, i18n-font-config) are wired only into cli/index.ts and cli/commands/init.ts, not the sync path either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghigh-priorityAddress soon

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions