Repository navigation
Description
Problem
id world doctor's journal check (validate_journal_file, pkgs/id/src/world_doctor.rs:361-395) disagrees with the code that actually opens a journal in three ways, so doctor both clears journals the world refuses to open and condemns journals the world opens fine:
- Version 0 passes. The check ensures only
version <= MAX_JOURNAL_VERSION(world_doctor.rs:382-385). The real header check inWorldCore::restorerequiresJOURNAL_VERSION..=MAX_JOURNAL_VERSION(1..=2) (pkgs/id/src/world/core.rs:152). A journal headed{"entry":"created","world_id":"w","version":0}is reported by doctor as1 entries, format version 0/ Ok, but restore refuses it:unsupported world journal version 0. - A leading blank line makes a valid journal fail. Doctor matches on the raw split-line
index(world_doctor.rs:368,377-381), but skips empty lines withcontinuewithout adjusting that index, so a journal beginning with one blank line reportsentry 2 is Created, but it is not the first entry. The real reader (read_journal_entries,pkgs/id/src/world_store.rs:452-465) skips empty lines before parsing, and restore seesCreatedas the first entry and opens it. - The same blank line makes a headerless journal pass. With a leading blank line, a first real entry that is not
Createdis atindex == 1, so the_ if index == 0bail (world_doctor.rs:387-389) never fires,versionstaysNone, and the function returnsOk((1, JOURNAL_VERSION))via theunwrap_orat:394. Restore refuses the same bytes:world journal does not start with a header.
Evidence (verified this run)
Probe crate on the laptop (~/git/fleet/probe-2026-10-28-laneB-doctor there; world_doctor.rs sha256 72559955a81526838c8266a65fbdea1c6b6fcc39d1d1e11625ebfc748aa61848 identical on the laptop clone and the sandbox clone; probe copies the validate_journal_file logic verbatim against a minimal JournalEntry shim and the restore header checks verbatim from world/core.rs + world_store.rs):
CTRL v1: doctor=Ok((1, 1)) restore=Ok(())
V0 version0: doctor=Ok((1, 0)) restore=Err("unsupported world journal version 0")
V3 future: doctor=Err("journal format version 3 is newer than this binary supports (2)") restore=Err("unsupported world journal version 3")
BLANK+Created v1: doctor=Err("entry 2 is `Created`, but it is not the first entry") restore=Ok(())
BLANK+headerless: doctor=Ok((1, 1)) restore=Err("world journal does not start with a header")
CTRL headerless no blank: doctor=Err("the first entry is not `Created`") restore=Err(...)
Controls behave: a normal v1 journal passes both, and a v3 (future) journal is refused by both — the validator is alive; its first-entry test uses the wrong counter and its version range is missing the lower bound.
Why it matters
Doctor is the tool a user is told to run when a world will not open ("restore the journal from a backup, or recreate the world" is its own fix text). A check that says Ok for a journal restore will refuse — and Fail for one restore accepts — sends that user to recreate or restore over a working world, or to trust a broken one. Doctor's whole contract is that its verdict matches the opener's.
Acceptance criteria
validate_journal_filerefuses aCreatedheader with version 0 (lower boundJOURNAL_VERSION), matchingWorldCore::restore's1..=MAX_JOURNAL_VERSIONrange; versions 1 and 2 still pass, 3 still fails.- First-entry checks are made against the first parsed entry, not the raw line index: a journal with leading/interior blank lines and a
Createdfirst entry validates; a journal whose first parsed entry is notCreatedis refused regardless of blank lines. - Malformed-entry error messages may keep the raw line number (that is the useful diagnostic there).
- New unit tests in
world_doctor.rspin all three cases (version 0, blank-line + Created, blank-line + headerless) alongside the existing journal test; existing doctor tests still pass.
Activity
developing-today commentedon Oct 28, 2026
CODE-625
dezren39 commentedon Oct 28, 2026
🤖 Agent note · picked up
Merge pull request #1600 from developing-today/creator-b/1598-doctor-…
dezren39 commentedon Oct 28, 2026
🤖 Agent note · done
cargo test --lib world_doctoron the laptop: 12/12 passed including the newa_journal_version_zero_and_blank_lines_match_restore; rustfmt clean. PR CI was still QUEUED (runner backlog) at merge; merged under the standing directive on local verification.