refactor: comments state current behavior, not project history

Comments across the tree justified the code by pointing at a Rust
implementation that is no longer in the repository, citing files and line
numbers (config.rs:132, schema.rs:26-54, reader.rs:42) that cannot be
opened, plus crates and datasets that are equally gone. A reader could not
check any of it.

Every invariant those comments carried is kept and restated so it stands on
its own: the bytewise sort that decides which row survives a duplicate exam
number, the literal U+0300..U+036F range that must match the site's toAscii,
the trailing space in "SINH ", the BIFF and shared-string corrections, the
VACUUM-after-COMMIT rule, the deploy-from-main guard.

The reader's contract is now anchored to the frozen oracle in
parser/testdata, which still exists and is still checked, rather than to the
tool that originally produced it.

TestDDLMatchesRust becomes TestDDLIsFrozen: it compares against a copy of
the DDL inside the test and never read schema.rs, so both the name and the
failure message were misleading.

ToAscii no longer claims the d-replacement must precede lowercasing. Both
cases map to 'd' and ToLower runs last, so the order has no effect.
This commit is contained in:
tiennm99 committed 2026-08-14 09:40:41 +07:00
1 parent c988bfafcf
commit 933adf70c9
43 files changed
+392 -515

No files matched your search

+11 -11
View File
@@ -1,16 +1,15 @@
// Command dumpcells emits the canonical cell rendering of a spreadsheet.
//
// It exists to diagnose a reader-fidelity failure. That suite compares a
// SHA-256 per input file against a frozen oracle, so a mismatch says which file
// changed but not which cell; this prints the stream the hash is taken over, so
// two runs can be diffed. It was originally written to compare against the
// Rust/calamine ground truth from parser/examples/dump_cells.rs, which was
// removed with the Rust tree — the hashes it produced are what remains.
// It exists to diagnose a TestReaderFidelity failure. That suite compares a
// SHA-256 per input file against the frozen oracle, so a mismatch names the
// file but not the cell; this prints the stream the hash is taken over — plus a
// leading FILE line, which the hash excludes — so a dump from before and after
// a reader change can be diffed line by line.
//
// The canonical stream carries geometry and rendered cell values only. The
// calamine Data variant is deliberately excluded: Data::Empty and
// Data::String("") both render "" and both count as blank everywhere
// downstream, so the distinction cannot affect the database.
// The canonical stream carries geometry and rendered cell values only. Whether
// a cell was absent or an empty string is deliberately excluded: both render ""
// and both count as blank everywhere downstream, so the distinction cannot
// affect the database.
//
// Usage: dumpcells <spreadsheet> [out-file]
package main
@@ -24,7 +23,8 @@ import (
"github.com/tiennm99/thptqg/parser/internal/reader"
)
// escape mirrors the Rust dumper so field separators can never break the format.
// escape hides the field and record separators so a cell value can never break
// the format. Must stay in step with the fidelity test's escaping.
func escape(s string) string {
var b strings.Builder
b.Grow(len(s))
+5 -6
View File
@@ -1,8 +1,7 @@
// Command xlsxread reads .xls/.xlsx files and builds SQLite databases for the
// thptqg datasets.
//
// The CLI contract is fixed by the assembler, which drives this binary, and it
// matched the Rust binary it replaced exactly:
// The CLI contract is fixed by the assembler, which drives this binary:
//
// xlsxread build --schema <config.yml> --input <dir> --output <db>
// xlsxread audit --schema <config.yml> --input <dir> --db <db>
@@ -67,8 +66,8 @@ func runBuild(args []string) {
fatalf("Failed to load config: %v", err)
}
// The 2016 dataset selects its column layout per file at runtime; every other
// dataset uses the fixed columns: mapping (main.rs:63-67).
// The 2016 dataset selects its column layout per sheet at runtime; every
// other dataset uses the fixed columns: mapping from its config.
if cfg.FormatDetection != nil && *cfg.FormatDetection == "thptqg2016" {
if err := ingest.Detect2016(cfg, *inputDir, *outputPath); err != nil {
fatalf("%v", err)
@@ -102,8 +101,8 @@ func runAudit(args []string) {
}
audit.PrintReport(res)
// A mismatch is a non-zero exit even though the audit itself succeeded
// (main.rs:46-48) — CI treats it as a failure signal.
// A mismatch is a non-zero exit even though the audit itself succeeded —
// CI treats it as a failure signal.
if !res.Matched {
os.Exit(1)
}