Summary
On current CASS main, cass status --json can report:
{
"healthy": true,
"status": "healthy",
"storage_integrity": {
"storage_state": "ok",
"source_of_truth_risk": "none",
"archive_readability": "readable",
"checks_attempted": [
{
"name": "db_open",
"timed_out": false,
"read_only": true
}
]
}
}
while stock SQLite's PRAGMA quick_check on both the live database and a consistent .backup snapshot reports committed structural corruption:
Error: stepping, database disk image is malformed (11)
*** in database main ***
Page 41: never used
wrong # of entries in index sqlite_autoindex_conversations_1
The immediate bug is not that the lightweight status command omits a multi-gigabyte integrity scan. The bug is that it converts only db_open succeeded into the definitive verdicts storage_state: "ok" and source_of_truth_risk: "none".
For operators and coding agents, ok means a check passed. Here, the relevant check was never attempted.
Environment
CASS commit: 968a5f3c914e975327c998368ab2c5510aa22654
Build: cargo build --release --locked
Platform: Linux x86_64
Database size: approximately 6.2 GiB
Canonical rows: 9,596 conversations / 1,209,091 messages
Storage dependency: fsqlite 0.1.13
All paths and corpus content are intentionally omitted. The database is a large multi-connector agent-session archive.
Reproduction
- Use a CASS database whose canonical table remains readable but whose unique autoindex is malformed. In the observed file:
- a table scan of
conversations succeeds;
- forcing
sqlite_autoindex_conversations_1 returns SQLITE_CORRUPT;
- stock SQLite
quick_check reports one orphan page and a wrong autoindex entry count.
- Run:
cass status --json > status.json
sqlite3 -readonly "$DATA_DIR/agent_search.db" 'PRAGMA quick_check;'
- Compare:
jq '.healthy, .status, .storage_integrity' status.json
Observed CASS result:
{
"storage_state": "ok",
"source_of_truth_risk": "none",
"archive_readability": "readable",
"checks_attempted": [
{
"name": "db_open",
"elapsed_ms": 0,
"timed_out": false,
"read_only": true
}
]
}
Observed stock SQLite result:
database disk image is malformed (11)
Page 41: never used
wrong # of entries in index sqlite_autoindex_conversations_1
The same quick_check result occurs on a snapshot created with stock SQLite .backup, ruling out a transient read of an incompletely copied file. The live table remains scan-readable, which explains why db_open and simple counts can succeed.
Why this matters
This is a truth-surface contract problem:
- an agent sees
healthy: true, storage_state: ok, and source_of_truth_risk: none;
- it reasonably skips recovery and may continue writing to a malformed canonical store;
- the actual evidence only supports "database opens and bounded reads work";
- search can remain complete because the authoritative lexical index was already published, masking canonical storage damage.
A false definitive success is worse than an explicit "unchecked" state.
Expected behavior
When status only performs db_open, report the scope honestly. For example:
{
"storage_integrity": {
"storage_state": "unchecked",
"source_of_truth_risk": "unknown",
"archive_readability": "readable",
"checks_attempted": [
{"name": "db_open", "result": "pass"}
],
"checks_not_attempted": [
{"name": "quick_check", "reason": "outside_status_budget"}
]
}
}
If a recent, fingerprint-matched integrity attestation exists, status could safely project that cached verdict with its age and database fingerprint. It should not synthesize ok from openability alone.
Suggested implementation direction
- Separate these concepts in the storage-integrity model:
openable;
table_readable;
structurally_checked;
structurally_valid.
- Reserve
storage_state: "ok" for a passed structural check or a still-valid cached attestation.
- Use
unchecked / unknown when the only probe was db_open.
- Include:
attestation_source (live, cached, none);
attested_db_fingerprint;
attested_at;
check_depth (open, quick_check, integrity_check).
- Keep
archive_readability: "readable" if bounded reads succeed; that field is useful and is not contradicted by an autoindex-only failure.
- Ensure top-level
healthy cannot be true when structural integrity is known bad. For merely unchecked state, expose a non-alarming but honest qualification.
Regression test / acceptance criteria
Create a fixture where:
- the table b-tree can be scanned;
- a secondary/unique index has a missing entry or wrong entry count;
PRAGMA quick_check fails;
- opening the DB and counting the table still succeed.
Assert:
cass status --json does not report storage_state: "ok" based only on db_open.
source_of_truth_risk is not none when corruption is known.
checks_attempted and checks_not_attempted make probe coverage explicit.
- A cached passed attestation is only reused when its database fingerprint still matches.
- The output remains bounded and machine-readable; this report does not request an unbounded integrity scan on every status call.
- Search readiness and storage integrity remain separate fields, so a usable published lexical index can coexist with a degraded canonical-store verdict.
Related issues
Summary
On current CASS
main,cass status --jsoncan report:{ "healthy": true, "status": "healthy", "storage_integrity": { "storage_state": "ok", "source_of_truth_risk": "none", "archive_readability": "readable", "checks_attempted": [ { "name": "db_open", "timed_out": false, "read_only": true } ] } }while stock SQLite's
PRAGMA quick_checkon both the live database and a consistent.backupsnapshot reports committed structural corruption:The immediate bug is not that the lightweight status command omits a multi-gigabyte integrity scan. The bug is that it converts only
db_opensucceeded into the definitive verdictsstorage_state: "ok"andsource_of_truth_risk: "none".For operators and coding agents,
okmeans a check passed. Here, the relevant check was never attempted.Environment
All paths and corpus content are intentionally omitted. The database is a large multi-connector agent-session archive.
Reproduction
conversationssucceeds;sqlite_autoindex_conversations_1returnsSQLITE_CORRUPT;quick_checkreports one orphan page and a wrong autoindex entry count.jq '.healthy, .status, .storage_integrity' status.jsonObserved CASS result:
{ "storage_state": "ok", "source_of_truth_risk": "none", "archive_readability": "readable", "checks_attempted": [ { "name": "db_open", "elapsed_ms": 0, "timed_out": false, "read_only": true } ] }Observed stock SQLite result:
The same
quick_checkresult occurs on a snapshot created with stock SQLite.backup, ruling out a transient read of an incompletely copied file. The live table remains scan-readable, which explains whydb_openand simple counts can succeed.Why this matters
This is a truth-surface contract problem:
healthy: true,storage_state: ok, andsource_of_truth_risk: none;A false definitive success is worse than an explicit "unchecked" state.
Expected behavior
When status only performs
db_open, report the scope honestly. For example:{ "storage_integrity": { "storage_state": "unchecked", "source_of_truth_risk": "unknown", "archive_readability": "readable", "checks_attempted": [ {"name": "db_open", "result": "pass"} ], "checks_not_attempted": [ {"name": "quick_check", "reason": "outside_status_budget"} ] } }If a recent, fingerprint-matched integrity attestation exists,
statuscould safely project that cached verdict with its age and database fingerprint. It should not synthesizeokfrom openability alone.Suggested implementation direction
openable;table_readable;structurally_checked;structurally_valid.storage_state: "ok"for a passed structural check or a still-valid cached attestation.unchecked/unknownwhen the only probe wasdb_open.attestation_source(live,cached,none);attested_db_fingerprint;attested_at;check_depth(open,quick_check,integrity_check).archive_readability: "readable"if bounded reads succeed; that field is useful and is not contradicted by an autoindex-only failure.healthycannot be true when structural integrity is known bad. For merely unchecked state, expose a non-alarming but honest qualification.Regression test / acceptance criteria
Create a fixture where:
PRAGMA quick_checkfails;Assert:
cass status --jsondoes not reportstorage_state: "ok"based only ondb_open.source_of_truth_riskis notnonewhen corruption is known.checks_attemptedandchecks_not_attemptedmake probe coverage explicit.Related issues
cass status --jsoncould still report healthy/readable after a stranded WAL. That issue fixed the checkpoint/finalize cause, but the status truth-model gap remains.