diff --git a/.github/workflows/translation-guard.yml b/.github/workflows/translation-guard.yml index 4c1a397b819..460e677f37f 100644 --- a/.github/workflows/translation-guard.yml +++ b/.github/workflows/translation-guard.yml @@ -184,6 +184,8 @@ jobs: echo "" >> "$GITHUB_STEP_SUMMARY" echo "**State of the engine (#15198, #10038):** \`translation-sync.yml\` is on a manual-maintainer hold since 2026-08-12 -- it no longer runs per-PR, so editing the FR source does **not** refresh the derived file until the hold is lifted. While the hold stands, the auditable exit for a legitimate derived-file change is the dual-key override (#10332), never a silent hand-edit." >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" + echo "**Counterpart organ (#20232):** the hot-subset ratchet (\`scripts/translation/tests/test_hot_subset_ratchet.py\`, #13551) requires a **per-cell CSV resync** after an FR edit -- exactly the derived files flagged here. The dual-key override above is the auditable path for that resync; the two organs name each other on purpose." >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" echo '```bash' >> "$GITHUB_STEP_SUMMARY" echo "git checkout origin/main -- $CHANGED" >> "$GITHUB_STEP_SUMMARY" echo '```' >> "$GITHUB_STEP_SUMMARY" @@ -198,6 +200,13 @@ jobs: # cliquet is not disarmed. The decision lives in # `scripts/ci/translation_override_required.py` (testable, injectable # fetchers -- unit tests never touch the network). + # + # Counterpart organ (#20232): the hot-subset ratchet + # (`scripts/translation/tests/test_hot_subset_ratchet.py`, #13551) + # requires a per-cell CSV resync after an FR edit -- i.e. the derived + # files this guard flags. The two organs name each other on purpose: + # the ratchet points here and to this dual-key; this guard points to + # the ratchet. Do not silence one by weakening the other. - name: Resolve translation-guard override (#10332) id: override if: steps.check.outputs.violated == 'true' diff --git a/scripts/translation/tests/test_hot_subset_ratchet.py b/scripts/translation/tests/test_hot_subset_ratchet.py index 904faaf219b..63050084efd 100644 --- a/scripts/translation/tests/test_hot_subset_ratchet.py +++ b/scripts/translation/tests/test_hot_subset_ratchet.py @@ -83,6 +83,14 @@ def test_hot_subset_is_zero(): If this fails: an FR notebook edit landed on a cell that has a translation, without resyncing its CSV row. Fix per-cell (see the issue procedure) — do NOT run a global re-extraction, it orphans translations. + + The per-cell resync edits ``translations/**/*.csv``, which + ``translation-guard.yml`` flags as a translation-owned hand-edit. Both + organs are sound; the contradiction is resolved by the guard's dual-key + override (#10332): comment marker ``[TRANSLATION-OVERRIDE] `` AND + label ``translation-override``. With ``translation-sync.yml`` on maintainer + hold since 2026-08-12 (#15198, #10038), the override is the only open path + while the hold stands — never a silent hand-edit. """ translations = REPO_ROOT / "translations" notebooks = REPO_ROOT / "MyIA.AI.Notebooks" @@ -94,6 +102,10 @@ def test_hot_subset_is_zero(): assert hot == [], ( f"{len(hot)} hot cell(s): SRC_DRIFT on rows with deposited " f"translations — resync per-cell (never global extraction, #13551). " + f"That resync edits translations/**, which translation-guard.yml " + f"flags: take its dual-key override (label `translation-override` + " + f"comment marker `[TRANSLATION-OVERRIDE] `, #10332) while " + f"translation-sync.yml is on hold (#15198/#10038). " f"First offenders: {[ (a['notebook'], a['cell_id']) for a in hot[:5] ]}" )