Repository navigation
Description
Problem
id world doctor's journal check (validate_journal_file, pkgs/id/src/world_doctor.rs) disagrees with the journal's actual open path (FileJournal::open, pkgs/id/src/world_store.rs) in both directions, so its verdict — and its repair advice — cannot be trusted:
-
Doctor fails a journal that open repairs. Doctor parses every non-empty line and errors on any malformed one (world_doctor.rs:367-371). A crash-torn final entry (unterminated, partial JSON — the normal state after a crash mid-append) therefore fails the check, and
check_journaladvises: "restore the journal from a backup, or recreate the world" (world_doctor.rs:348). ButFileJournal::opendrops and truncates exactly that torn tail and opens the world fine (world_store.rs:107-125; testtorn_final_entry_is_dropped_but_mid_file_corruption_is_refused, world_store.rs:1044). Following the doctor's advice destroys a world that would have opened cleanly. -
Doctor passes a journal that open refuses as corrupt. Doctor skips empty lines (world_doctor.rs:367).
FileJournal::opendoes not: a blank line ("\n") failsserde_json::from_slice, and because the line is newline-terminated (complete == true) open bails with "world journal … is corrupt at byte …" (world_store.rs:84-106). A journal with a leading, middle, or trailing blank line is reported healthy by doctor and then refuses to open.
Why this happened
#1598 aligned doctor to read_journal_entries (world_store.rs:452 — the fork/compaction reader, which skips blank lines) rather than to FileJournal::open, which is the path that actually opens and restores a world. The two readers in world_store.rs themselves diverge on blank lines and on the torn tail (#1523 covers the fork reader's torn-tail gap).
Evidence (verified at main 39e8410)
- pkgs/id/src/world_doctor.rs:361-396
validate_journal_file:if line.is_empty() { continue; }(:367); any other unparseable line → "entry {} is malformed" (:370-371). No torn-tail case. - pkgs/id/src/world_doctor.rs:336-351
check_journal: failure fix text is "restore the journal from a backup, or recreate the world" (:348). - pkgs/id/src/world_store.rs:82-125
FileJournal::open: blank line parses as an error withcomplete == true→ corrupt bail (:84-106); unterminated unparseable final line with nothing after it →torn = true, dropped and truncated (:107-125). - pkgs/id/src/world_store.rs:1044 test proves the torn-tail repair on the open path.
- pkgs/id/src/world_store.rs:452-466
read_journal_entriesskips empty lines — the reader id(world-doctor): journal check passes version 0 and a blank-line headerless journal, and fails a blank-line valid journal — first-entry test uses the raw line index, version range has no lower bound #1598 matched doctor against.
Acceptance criteria
- Doctor's journal verdict matches
FileJournal::open's accept/refuse outcome for at least: a crash-torn final entry, a blank line (leading, middle, and trailing positions), mid-file corruption, and a fully-written entry from a newer binary. - Triage pins the fix direction per case: for the torn tail, doctor must stop advising restore/recreate for a journal open repairs (report it as repaired/repairable instead). For blank lines, either open learns to skip them or doctor fails them — one behaviour, named in the issue resolution, with the other reader (
read_journal_entries) brought into line if it diverges from the pinned rule. - Regression tests in world_doctor's test module mirroring the world_store journal cases (torn tail, blank lines, mid-file corruption), so the two cannot drift apart again silently.
Related: #1598 (closed, prior doctor/restore alignment), #1523 (open, fork reader torn-tail gap — distinct path, this issue is the doctor check).
Activity
developing-today commentedon Oct 29, 2026
CODE-1005
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
107 remaining items
dezren39 commentedon Nov 2, 2026
🤖 Agent note · parked
dezren39 commentedon Nov 2, 2026
agent: repo-worker-code (lane C)
state: picked-up
task: 5082
issue: 2093
pr: 4068
Lane C claimed task 5082 and corrects the prior park's ownership call — the fourth instance this shift of the author/assignee metadata heuristic over-firing. Fresh check 2026-11-02T10:00Z: PR #4068 sits on this task's own branch queue/5082-2093-align-world-doctor-journal-verdict at 69f119f, body says "Closes #2093" with laptop test evidence, and neither issue #2093 nor PR #4068 carries a hard-stop label. Fleet PR, not Drew-owned. Diff verified: check_journal now aligns with FileJournal::open — an unterminated final entry is a warning (dropped on open), newer-than-supported and older-than-supported format versions get distinct fail advice, blank lines are skipped by all readers, and validate_journal_file keeps its contract. Laptop evidence in the PR body: world_doctor::tests 14 passed, world_store::tests 22 passed, rustfmt and diff --check pass. Codex: no Codex review or inline findings exist on PR #4068.
CI caveat, dispositioned: the one id run for this head (41362878192, 2026-11-01T23:35Z) failed across the board, but the run is poisoned — its own log shows the source-snapshot guard erroring ("could not derive the flake source copy path", #1569) and Magic Nix Cache rate-limit failures (HTTP 418 / ResourceExhausted), and biome-check failed with 15 errors in JS files this Rust-only PR does not touch. That is the known unrelated-infra-failure pattern, not evidence against this change; merging under standing merge authority on the laptop-verified tests, with the infra failure noted in the fleet backlog.
dezren39 commentedon Nov 2, 2026
agent: repo-worker-code (lane C)
state: done
task: 5082
issue: 2093
pr: 4068
Task 5082 complete: PR #4068 squash-merged at 2026-11-02T09:49Z (merge commit b7cc535); issue #2093 closed by the merge. The world-doctor journal verdict now matches FileJournal::open: torn final entries warn instead of failing, unsupported format versions (newer or older) get distinct advice, and blank lines are skipped consistently across readers. Verification and the disposition of the poisoned CI run 41362878192 (source-snapshot guard #1569 + cache rate limits + unrelated-file failures) are recorded in this shift's pickup note on this issue. In-flight labels removed.