Files
Rainman f0c3faaffa fix: resolve all defects found in project review (#39)
* fix(glossary): include aliases in term_hash so alias edits trigger re-translation

Aliases are injected into the per-chunk term table (别名 column), but
term_hash only covered source/target/category. Adding or editing an alias
on a term whose source already appears in a chunk changed the prompt
contract without changing the recorded hash, so run_state.py plan reported
the chunk as unchanged — contradicting the SKILL.md promise that alias
edits re-translate affected chunks.

The alias segment is appended to the hash payload only when aliases exist,
so alias-less terms keep their historical hash and existing run_state.json
records stay valid across the upgrade.

Co-authored-by: Rainman <deusyu@users.noreply.github.com>

* fix(merge): reject blank or unreadable translated chunks instead of silently dropping them

A whitespace-only output_chunk*.md (non-zero bytes) passed the merge
validation's size==0 check, produced only a 'Suspiciously short' warning,
and then vanished during merge because merge_markdown_files skips content
that strips to empty — the chunk's entire source text was silently missing
from the final book while the build reported success.

- manifest.validate_for_merge now errors on blank (whitespace-only) and
  undecodable outputs, via the new read_output_text helper
- merge_markdown_files aborts on blank/unreadable outputs in both the
  manifest-ordered and legacy glob paths (read errors previously just
  printed and continued, which also dropped content silently)
- run_state.plan marks blank/unreadable outputs for re-translation
  (reasons: blank_output / unreadable_output) and record refuses to
  certify them

Co-authored-by: Rainman <deusyu@users.noreply.github.com>

* fix(convert): abort when temp dir was built from different source bytes

convert.py reused every cached artifact (input.html, input.md, chunks)
whenever it existed, with no check that the input file itself was still
the same book — replacing the source file with a same-named one silently
translated the old book's chunks.

A source_fingerprint.json (path/size/sha256) is now written into the temp
dir on every successful conversion. On re-run:
- fingerprint matches → resume as before
- fingerprint differs → abort with a clear message (delete the temp dir
  or use a fresh --temp-root)
- no fingerprint but cached artifacts exist (pre-upgrade temp dir) →
  adopt with a warning and fingerprint on the next successful run, so
  existing in-progress books stay resumable

Only content identity is compared, so moving or renaming the source file
does not invalidate the cache.

Also removes the dead is_legacy return value from
_find_existing_chunk_files — page* support was removed long ago.

Co-authored-by: Rainman <deusyu@users.noreply.github.com>

* chore(calibre_html_publish): remove dead logic and align style with the pipeline

- drop the SIGALRM timeout layer — subprocess.run(timeout=...) already
  enforces the same limit, and signal-based alarms are redundant
- remove the post-conversion image copy-back block: DOCX/EPUB/PDF embed
  images during conversion, and in pipeline use the copy target was the
  directory the images came from (rmtree + copytree round-trip)
- book-producer metadata 'Claude Translator' → 'translate-book'
- drop the unconditional '仿宋体 (FangSong)' font line printed even for
  non-Chinese output languages
- normalize emoji log prefixes to plain text like the other scripts
- delete the three skipped tests for extract_cover_from_epub — EPUB cover
  auto-extraction was declared out of scope (closed #3), so feature-gated
  tests for it are dead weight

Co-authored-by: Rainman <deusyu@users.noreply.github.com>

* docs+ci: document new validation guarantees; align CI Python with docs

- SKILL.md: list source_fingerprint.json in the temp dir contents, explain
  the mismatch abort / adopt-with-warning behavior, and extend the Step 5
  verification to blank (whitespace-only) outputs
- README.md / README.zh-CN.md (synced): source fingerprint description in
  Step 1, blank-output rejection in the merge validation list, alias edits
  called out in the selective re-translation note, and two new
  troubleshooting rows
- CI: Python 3.11 → 3.12, matching the documented 3.12+ environment

Co-authored-by: Rainman <deusyu@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Rainman <deusyu@users.noreply.github.com>
2026-07-02 16:19:24 +08:00
..