How to Create an EPUB File Without Carrying Encoding Errors Forward

Encoding repairs are safest when the original source, the repaired manuscript, and the exported book remain three separate artifacts. This walkthrough uses a retained STUDIO-403 fixture rather than an imagined dialog. The source was detected as Shift_JIS with LF line endings, three lines, and 36 characters. A differently named file was converted to UTF-8, reopened with the same LF, line, and character counts, and used to create an EPUB with zero recorded omissions and a valid local inspection.

The graphical boundary is equally important. This run did not observe red warning text or an autosave timer in Rune Studio. A command-line readback cannot establish either screen behavior. The steps below say exactly what the saved files prove and reserve the visual checks for a separate user-run test.

Identify the Source Before Opening It for Editing

The input is legacy-source-sjis.txt, a three-line Japanese specimen with one heading and one sentence. Running rune inspect text --file legacy-source-sjis.txt --json returned encoding=Shift_JIS, lineEnding=LF, characterCount=36, lineCount=3, and an empty unconvertible array. Those values describe this particular file, not every legacy manuscript.

Do not save a document merely because the visible text appears plausible. If a decoder has already substituted characters, saving may destroy the byte sequence needed for recovery. Treat the first copy as read-only and record its path, digest, detected encoding, line ending, character count, and line count. Appearance can help investigation, but it is not the identity record.

Convert to a Differently Named UTF-8 File

The retained command was iconv -f SHIFT_JIS -t UTF-8 legacy-source-sjis.txt -o repaired-utf8.md. The destination name is deliberate. It preserves the Shift_JIS source while creating a candidate that can be compared without ambiguity. The repaired file was 78 bytes and had SHA-256 5d53dad03fe7c9ef64e466517a5e45d629d3238849ec6bc460ff2646c70a357c.

An in-place conversion removes that safety margin. A wrong source-encoding argument can still create output, and the operator then has no clean reference. Keep the candidate separate until its contents and metadata pass. Only after acceptance should a workflow choose which name becomes the production manuscript.

Reopen and Compare Characters, Lines, and Content

The second inspection targeted repaired-utf8.md. It reported encoding=UTF-8, lineEnding=LF, characterCount=36, lineCount=3, and unconvertible=[]. The encoding changed as intended while the logical length and line structure stayed fixed. That tuple is the acceptance value for this fixture.

Matching character counts alone cannot prove identical text because one character can be substituted for another. Compare the heading, the sentence, punctuation, and line boundaries as well. Conversely, a byte-count change from the Shift_JIS file to its UTF-8 counterpart is expected. Separate byte identity, character identity, and visual appearance instead of asking one number to answer every question.

Recover from a Failed Conversion at the Source

Stop if the source argument is wrong, output is empty, the count moves away from 36, a line disappears, or replacement characters appear. Preserve the rejected candidate together with its command, exit status, standard error, and digest. Then inspect the untouched source again and confirm that its detected encoding agrees with the -f SHIFT_JIS argument.

Recovery creates another candidate from the original file. It does not hand-edit the damaged output and continue. Reopen the new candidate and repeat the UTF-8, LF, 36-character, three-line, and zero-unconvertible checks. This route keeps the authoritative bytes visible and lets a second operator reproduce the decision.

Export Only the Accepted Candidate

The fixed run selected repaired-utf8.md as the chapter, set the book metadata, and generated studio-403-260903.100000.epub. Its SHA-256 is b0a767edda849615767a91550587f578e57bf636e8a44cadeb0ac144d504364c. Reopening the ZIP reveals nine entries, with the manuscript in p001.xhtml.

The saved command rune inspect epub --path ... --json returned valid=true and issues=[]; the retained evidence records zero missing characters. The bounded conclusion is that this EPUB, generated from the accepted UTF-8 candidate, passed the local checks. It does not predict every distributor or reading system.

Keep Red Warnings and Autosave in a Separate UI Test

Published product material describes warning and saving behavior, but this interaction log contains no observed red range, warning text, or autosave interval. Therefore the article does not claim that a red mark appeared or that automatic saving stopped. A graphical test needs the application build, opened file, warning locations, disk digest before waiting, elapsed interval, and digest after waiting.

This 36-character specimen has unconvertible=[], so it is a normal case. A future warning test should use a dedicated negative fixture and compare the highlighted span with the inspection result. A separate autosave check should read the disk, not infer persistence from an unchanged editor window. Those checks remain open here.

Hand Off Three Receipts, Not One Success Message

The source receipt records Shift_JIS, LF, 36 characters, three lines, and the original digest. The conversion receipt records the exact command, different destination name, UTF-8, LF, 36 characters, three lines, and zero unconvertible items. The export receipt records the chosen input, EPUB digest, valid=true, issues=[], and zero omissions. Missing data on any receipt prevents acceptance.

Red display, autosave timing, and reader appearance belong to a fourth interface receipt that is still unmeasured. Passing file conversion must not fill those fields automatically. Preserving the source, reopening a named UTF-8 candidate, and exporting only that accepted file is the practical sequence for preventing an encoding defect from moving into the EPUB.

Archive the command output beside both text digests and the EPUB digest. A later file can reuse the same human-readable name, so the path alone is not durable identity. During handoff, ask the next operator to reopen each artifact and compare the recorded tuple before approving it. If one value differs, stop at that layer instead of repeating every step or accepting the newest timestamp.