Skip to content

perf(converter): read each session once for the converter and the audit - #9

Merged
laithalsaadoon merged 1 commit into
mainfrom
lever/convert-parse-once
Sep 13, 2026
Merged

laithalsaadoon merged 1 commit into
mainfrom
lever/convert-parse-once

Conversation

@laithalsaadoon

Copy link
Copy Markdown
Owner

Convert reads each transcript once

Climb run 2, attempt 1 (objective 1.1 against main 31b61d5). Every transcript file was opened 5 times, parsed twice and hashed 3 times across the snapshot, the converter, the audit census and two mutation re-checks. Now one pass reads, hashes (sha256 through a digesting reader under the same UTF-8 text layer) and parses each file, the converter and the audit share the resulting LoadedSession, and one mutation re-check runs after conversion. Codex gets the same treatment.

measurement (idle host) main this PR
convert of the largest session (76 MB), median of 5 2.78 s / 797 MB 2.07 s / 736 MB
materialize --force of the 300-session snapshot, 8 workers 13.74 s (convert_seconds 49.7) 11.57 s (convert_seconds 34.8)

Byte identity: live parity oracle over both frozen corpora, 0 divergences; direct compare against main's binary for all 378 sessions, 0 differing trajectory.json, edges.jsonl, stdout summaries or exit codes; the materialized snapshot's 600 artifacts identical.

Kept: the post-conversion re-check still hashes, because the pinned same-size-rewrite-within-one-mtime-tick test requires it (0.10 s of the 1.0 s in-process total). New TestSinglePass tests pin opens, parses and digests per file and fail on main's code.

mise run check green (1403 passed, 1 skipped); mise run docs:gate green.

convert_and_audit and convert_codex_and_audit read every transcript file
once. raw_records.load_session stats a file, then streams its bytes through
a sha256 digest into the JSON parser, so the fingerprint is the fingerprint
of the bytes that were parsed. The converter, the census, the edges emitter
and the enrichment pass consume that one list of records, and the
fingerprints are re-checked (stat and digest) once the artifacts are built.

Before: each file was opened five times (snapshot hash, converter read,
re-check hash, audit parse, re-check hash), parsed twice and hashed three
times with blake2b. After: two opens, one parse, two sha256 passes, which run
at 1.6 GB/s on this host's SHA extensions against blake2b's 0.9 GB/s.

Measured on the 76 MB benchmark session (59 MB of side files): the use case
went from 1.55 s to 1.01 s in-process; `atif-sql convert` from 2.78 s / 797 MB
to 2.07 s / 736 MB (median of 5); a materialize of the 300-session Claude
snapshot from 13.7 s to 11.6 s wall with 49.7 s to 34.8 s of summed worker
convert time. Byte identity: 378 sessions across both frozen corpora, 0
differing trajectory.json, edges.jsonl, stdout summaries or exit codes; the
live parity oracle passes for both agents at ATIF_PARITY_LIMIT=0.

The same-size-rewrite-inside-one-mtime-tick guard is kept: the post
conversion re-check still hashes, so a rewrite the stat pair cannot see still
refuses the session. TestSinglePass pins the open, parse and hash counts for
both agents and fails on the previous flow.
@laithalsaadoon
laithalsaadoon merged commit 2d22e32 into main Sep 13, 2026
17 checks passed
@laithalsaadoon
laithalsaadoon deleted the lever/convert-parse-once branch September 13, 2026 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant