diff --git a/docs/SAFETY.md b/docs/SAFETY.md index 4cdf0a9..b93ec2c 100644 --- a/docs/SAFETY.md +++ b/docs/SAFETY.md @@ -22,10 +22,16 @@ For each file EC is allowed to convert: 8. Atomically installs the verified temporary output where the platform supports it. 9. Marks the recovery record `Completed` after installation succeeds. -If a required step fails, EC does not install converted output. Because the -backup is created before decoding and encoding, a later conversion failure can -leave a valid `.bak` beside an unchanged source; metadata is not written until -both the output and backup have verified. +If a step before installation (step 8) fails, EC does not install converted +output and the source is unchanged. Because the backup is created before decoding +and encoding, a later conversion failure can leave a valid `.bak` beside an +unchanged source; metadata is not written until both the output and backup have +verified. + +If step 9 fails, installation has already happened: the verified converted output +is in place, EC reports a recovery-record error with the replacement recorded as +committed, and the `Prepared` record keeps the hashes needed to inspect the result. +Do not treat that file as unchanged. ## Source-encoding policy @@ -53,6 +59,9 @@ This is intentionally conservative: most ordinary BOM-less UTF-16 files are expected to be refused. It costs a second full read, which is deliberate because rewriting a file must not rest on a sample-based byte-order guess. +Choose `-From utf-16le` or `-From utf-16be` if you know the source order. That +chooses the source interpretation only; it does not bypass any other safeguard. + ### BOM-less UTF-32 EC never converts it automatically. It reports `Refused` with reason code @@ -67,8 +76,10 @@ pass it through. Separately, genuine UTF-32 can be valid under both orders. The cost is that ordinary BOM-less UTF-32 is refused too. Nothing in the bytes separates it from the UTF-16 file above. Add a BOM, or name the source. -Choose `-From utf-16le` or `-From utf-16be` if you know the source order. That +Choose `-From utf-32le` or `-From utf-32be` if you know the source order. That chooses the source interpretation only; it does not bypass any other safeguard. +Naming a UTF-16 order for a UTF-32 file would read its bytes as UTF-16, so use +only the UTF-32 names. ## Plans, backups, and recovery metadata diff --git a/sources/EncodingChecker/ConversionMetadata.cs b/sources/EncodingChecker/ConversionMetadata.cs index 868d375..c52dcdc 100644 --- a/sources/EncodingChecker/ConversionMetadata.cs +++ b/sources/EncodingChecker/ConversionMetadata.cs @@ -103,13 +103,12 @@ internal sealed record ConversionMetadata public required bool SourceHasBom { get; init; } /// - /// What detection concluded, or when detection did not run. + /// What detection concluded, or when it identified no codec. /// /// - /// This is null only when detection did not run, such as a CLI -From - /// conversion. A GUI user can explicitly choose a source after a scan; in that - /// case the sidecar preserves both the detector's earlier conclusion and the - /// codec the conversion actually used. + /// Detection runs even when the source is chosen explicitly, such as with a CLI + /// -From or a GUI choice after a scan, so the sidecar preserves the detector's + /// conclusion beside the codec the conversion actually used. /// [JsonPropertyOrder(15)] public int? DetectedEncodingId { get; init; } diff --git a/sources/EncodingChecker/ConversionPolicy.cs b/sources/EncodingChecker/ConversionPolicy.cs index 152772b..e688071 100644 --- a/sources/EncodingChecker/ConversionPolicy.cs +++ b/sources/EncodingChecker/ConversionPolicy.cs @@ -60,7 +60,8 @@ internal static PlannedAction Decide( return PlannedAction.Skip; } - // An unchanged file is not read or rewritten, so no source choice is needed. + // An unchanged file is not rewritten, so no source choice is needed. It is still + // read and validated in full after this decision. // // Codec identity is the code page, not the label. "utf-16", "unicode", "ucs-2" // and "utf-16le" all name code page 1200, so comparing the strings reported a