What an inbox file has: its version number, tables, columns and indexes. Made by tests/test_file_shape.py.

init creates a new inbox with every part, and no command adds a part or takes one away. A file that an older
release left is short of some. The first command that opens it gives it those: the file then has the shape of
a new inbox, and every row that it had.

A table is written in the words of the statements that the file itself keeps: its columns, then what holds
for the whole table, then its indexes. Under an older file, a line with + is a part or a row that the first
command gives it.

== new inbox
version 2
table adapter_state
    source TEXT PRIMARY KEY
    adapter TEXT NOT NULL
    revision INTEGER NOT NULL
    state TEXT NOT NULL
    backlog_pending INTEGER NOT NULL DEFAULT 0
table messages
    arrival_seq INTEGER PRIMARY KEY AUTOINCREMENT
    source TEXT NOT NULL
    id TEXT NOT NULL
    thread_id TEXT NOT NULL
    parent_id TEXT
    provider_seq INTEGER
    kind TEXT NOT NULL
    author TEXT
    title TEXT NOT NULL
    body TEXT NOT NULL
    url TEXT NOT NULL
    created_at INTEGER NOT NULL
    arrived_at INTEGER NOT NULL
    read_at INTEGER
    needs_reply INTEGER NOT NULL DEFAULT 0
    replied_at INTEGER
    reply_ref TEXT
    discovery TEXT
    addressing TEXT
    UNIQUE(source, id)
    CREATE INDEX messages_reply_ref ON messages (source,reply_ref)
table originals
    source TEXT NOT NULL
    id TEXT NOT NULL
    value TEXT NOT NULL
    fetched_at INTEGER NOT NULL
    PRIMARY KEY (source,id)
table reader_settings
    key TEXT PRIMARY KEY
    value TEXT NOT NULL
table reply_attempts
    source TEXT NOT NULL
    message_id TEXT NOT NULL
    idempotency_key TEXT NOT NULL UNIQUE
    body TEXT NOT NULL
    body_sha256 TEXT NOT NULL
    state TEXT NOT NULL CHECK (state IN ('prepared','unknown','confirmed'))
    prepared_at INTEGER NOT NULL
    attempted_at INTEGER
    confirmed_at INTEGER
    reply_ref TEXT
    readback_sha256 TEXT
    PRIMARY KEY (source,message_id)
table reply_candidate_checks
    source TEXT NOT NULL
    message_id TEXT NOT NULL
    idempotency_key TEXT NOT NULL
    reply_ref TEXT NOT NULL
    checked_at INTEGER NOT NULL
    reason TEXT NOT NULL
    PRIMARY KEY (source,message_id,reply_ref)
table reply_candidates
    source TEXT NOT NULL
    message_id TEXT NOT NULL
    idempotency_key TEXT NOT NULL
    reply_ref TEXT NOT NULL
    adapter TEXT NOT NULL
    account_id TEXT NOT NULL
    recorded_at INTEGER NOT NULL
    PRIMARY KEY (source,message_id,reply_ref)
table reply_verifications
    source TEXT NOT NULL
    message_id TEXT NOT NULL
    evidence TEXT NOT NULL
    PRIMARY KEY (source,message_id)
table sources
    source TEXT PRIMARY KEY
    account_id TEXT NOT NULL
    status TEXT NOT NULL DEFAULT 'unknown'
    last_checked INTEGER
    last_ok INTEGER
    error TEXT
    unavailable INTEGER NOT NULL DEFAULT 0
    paused INTEGER NOT NULL DEFAULT 0
table subscriptions
    source TEXT NOT NULL
    thread_id TEXT NOT NULL
    subscribed_at INTEGER NOT NULL
    PRIMARY KEY (source,thread_id)
table thread_tags
    tag TEXT NOT NULL
    source TEXT NOT NULL
    thread_id TEXT NOT NULL
    tagged_at INTEGER NOT NULL
    PRIMARY KEY (tag,source,thread_id)
    CREATE INDEX thread_tags_membership ON thread_tags(source,thread_id,tag)

== version 1
tests/fixtures/v1.sql
version 1 -> 2
+ table adapter_state
+ messages: discovery TEXT
+ messages: addressing TEXT
+ messages: CREATE INDEX messages_reply_ref ON messages (source,reply_ref)
+ table originals
+ table reader_settings
+ table reply_attempts
+ table reply_candidate_checks
+ table reply_candidates
+ table reply_verifications
+ sources: paused INTEGER NOT NULL DEFAULT 0
+ table subscriptions
+ table thread_tags
+ row of adapter_state: moltbook, moltbook, 0, {}, 0

== version 1, written by 0.15.1
tests/fixtures/v1-written-0.15.1.sql
version 1 -> 2
+ messages: discovery TEXT
+ messages: addressing TEXT
+ messages: CREATE INDEX messages_reply_ref ON messages (source,reply_ref)
+ table originals
+ table reply_candidate_checks
+ table reply_candidates
+ table reply_verifications
+ row of adapter_state: moltbook, moltbook, 0, {}, 0

== version 1, collected by 0.15.1
tests/fixtures/v1-collected-0.15.1.sql
version 2
+ table reader_settings
+ table reply_attempts
+ table reply_candidate_checks
+ table reply_candidates
+ table reply_verifications
+ sources: paused INTEGER NOT NULL DEFAULT 0
+ table thread_tags

== created by 0.15.1
tests/fixtures/created-0.15.1.sql
version 2
+ table reader_settings
+ table reply_attempts
+ table reply_candidate_checks
+ table reply_candidates
+ table reply_verifications
+ table thread_tags
