Repository navigation
fix(validation): stop untranslated prose hiding behind reference context - #160
Merged
Merged
Conversation
JunjoSick
force-pushed
the
port/source-copy-revalidation
branch
from
October 20, 2026 23:17
03593b5 to
cee9333
Compare
JunjoSick
marked this pull request as ready for review
October 20, 2026 23:38
Port of the October source-copy fix (local remediation/audit-2026-08, ffc565e1), re-implemented on main's validator and findings model. source_copy_validation_error exempted whole sections titled like Notes, Bibliography or Index, any block starting with a page reference, and any text containing an "in English:" gloss, so long untranslated paragraphs passed validation. The exemptions now apply only below MIN_SOURCE_CHARS; longer text always gets the equality and near-copy checks. blocking_source_copy_error combines that check with batch severity grading, so cache reuse and resume revalidation hold stored output to the rule fresh batch output passes: titles, headings and short proper-noun lines stay warnings. - cache: a hit with a blocking copy becomes an ordinary miss - resume: saved provider copies move to needs_review through JobStore::mark_stored_translation_for_review before context rehydration; text, usage and provenance are untouched and the finding is appended rather than replacing existing ones - resume double-check: human-accepted segments are excluded. The EPUB is rebuilt from in-memory translations, so an automated rewrite could replace a correction in the output while the store kept it frozen Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JunjoSick
force-pushed
the
port/source-copy-revalidation
branch
from
October 20, 2026 23:45
cee9333 to
b410e30
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports the October 8–9 source-copy fix (
ffc565e1on the local, never-pushedremediation/audit-2026-08branch) onto currentmain. It's re-implemented rather than cherry-picked, becausemain's validator and findings model changed after Aug 25 (CJK near-copies, non-linguistic blocks, structured findings with warning/error severity, warning-only batch acceptance ine4efaac2).The defect on
main.source_copy_validation_errorreturned early, before any check ran, when:p. <n>.;in English:anywhere.So whole untranslated paragraphs in those places passed validation. Cache hits were never checked at all, and resume trusted earlier accepted output.
Changes
bookforge-llm/src/validation.rs): the three exemptions now apply only to blocks underMIN_SOURCE_CHARS(120). Longer text always goes through the equality and near-copy checks. Short reference lines keep exactly their current behavior, so this adds no noise on short citations.batch/rendering.rs): newblocking_source_copy_error= the copy check andmain's existingintentionally_unchanged_blockgrading. Titles, headings and short proper-noun lines stay warnings, as batch acceptance treats them, so cache and resume don't start rejecting what batches already accept.translate/cache.rs): a hit with a blocking copy becomes an ordinary miss; the source job is untouched.resume.rs,bookforge-store/src/db/translations.rs): after preflight and before context rehydration, saved provider output with a blocking copy moves toneeds_reviewthrough newJobStore::mark_stored_translation_for_review. It's an immediate transaction guarded by the expected text and byhuman_corrected = 0. Text, block rows, attempts, usage and provenance are untouched, and the finding is appended (the engine-findings writer would delete the segment's existing findings). Flagged segments aren't retranslated automatically.main:rebuild_block_translationslets in-memory translations override stored blocks, and resume's double-check edits those in-memory translations, accepted segments included. A reviewer's correction stayed frozen in SQLite but could be replaced in the rebuilt EPUB. Human-accepted segments are now kept out of the pass entirely, and with nothing to review no double-check provider is constructed.The trade-off to review
A verbatim citation of 120+ characters (a long bibliography entry kept unchanged) is now flagged and needs explicit acceptance with
bookforge correct. Shorter citations are unaffected. The October design chose this deliberately, after seeing a handful of such references on a real book, over guessing which text is a citation from author/year/punctuation patterns. A structural citation classifier is still open work.Validation
Notes,Endnotes,Bibliography,References,Works Cited,Index,Author's Note,Notes to Chapter 1, none) × prefix (none,p. 12.,in English:). Short citations stay exempt in reference sections. Correct translations of the old exemption test strings (an endnote, a bilingual gloss) are not flagged.deepseekis flagged with blocks/provider/usage/attempts unchanged, and the EPUB is still written. Afterbookforge correctacceptance, a resume with double-checkFullpointed at a closed local port with an unset API key completes without ever building that provider, and leaves the accepted row identical. Mutation-checked: with the human-correction filter disabled, this test fails (double-check failed: … environment variable … is not set), offline and in under a second. (mainsilently skips unknown double-check providers, so an unsupported provider name would not have tested anything.)RUSTFLAGS="-D warnings": clippy (all targets/features), fmt,git diff --check, release-security script, no-default-features check, dashboard JS tests and the 1.88 MSRV check all pass. Workspace tests: 1,435 passed, 1 failed, 9 ignored; examples: 13 passed.batch::tests::persistent_decode_error_bisects_an_oversized_batch_after_retry(request counts[2, 2], or a hang; documented in fix(ci): unbreak CI after Rust 1.99 and clear October RustSec advisories #159). This port can't reach it: the test's inputs are two short words, and the change only affects text of 120+ characters in reference contexts. Single-test reruns on this build went 12 ok / 2 hang / 1 fail of 15, against 26 / 1 / 3 of 30 onmain, with the same failure modes. The 54 validation and batch-rendering tests pass.🤖 Generated with Claude Code