This runbook documents the operator workflow for cass doctor after the
archive-first doctor v2 work. The core rule is preservation before repair:
cass treats the SQLite archive, raw mirror metadata, raw mirror blobs, backup
bundles, source ledgers, receipts, failure contexts, and support-bundle manifests
as evidence. Derived lexical, semantic, and report assets may be rebuilt through
fingerprinted plans, but recovery must not discard the only remaining copy of a
coding-agent session.
Use robot-safe commands for automation. Never run bare cass from an agent or
script because it launches the interactive TUI.
- SQLite is the archive of record once a conversation is indexed.
- Provider session logs under harness-owned locations such as
~/.codex,~/.claude, Cursor, Gemini, OpenCode, and remote sources are upstream inputs, not guaranteed long-term backups. Those harnesses may prune old session logs. - The raw-session mirror is cass-owned evidence captured before parsing. It is content-addressed, path-safe, privacy-aware, and verified by hashes.
- Lexical and semantic indexes are derived assets. Rebuild them when the doctor plan says so; do not treat an index rebuild as proof that archived sessions are recoverable from upstream logs.
- Repairs build candidates first, compare coverage, verify integrity, and only promote a candidate when the approved plan proves equal-or-better archive coverage.
Doctor workflows must preserve:
- canonical archive databases such as
agent_search.dband required sidecars - raw mirror blobs, manifests, provenance ledgers, and source coverage ledgers
- backup bundles, restore rehearsal receipts, promotion receipts, and rollback references
- bookmarks, TUI state, source configuration, remote mirror metadata, and user configs
- provider source logs and private raw sessions unless an operator explicitly opts into a sensitive support artifact
Do not hand-remove cass data directories, index directories, raw mirrors, backup bundles, WAL/SHM sidecars, or provider session trees as a repair step. If disk pressure is the problem, run the storage-pressure and archive export flows below and inspect their fingerprints before any mutation.
-
Capture the read-only truth surface:
cass doctor check --json
-
Branch on JSON fields, not prose:
statusrisk_levelrecommended_actionoperation_outcome.kindoperation_outcome.exit_code_kindcoverage_risk.statussource_authority.authority_levelraw_mirror.statusremote_source_sync.statusstorage_pressure.statusrepair_failure_marker.status
-
If the command reports active locks, wait or retry later. Do not remove lock files by hand.
-
If the command reports sole-copy or source-pruned risk, preserve the cass archive first. Do not run source-only rebuild recipes.
-
If support is needed, collect the support handoff bundle near the end of this runbook.
Run the archive scan when the question is "does cass still have enough evidence if upstream logs disappeared?":
cass doctor archive-scan --jsonImportant fields:
source_inventoryinventories current provider paths and FAD-backed sources.coverage_summarycompares archived rows, current sources, raw mirror links, and legacy DB-only rows.sole_copy_warningsidentifies conversations where cass may be the only remaining archival copy.source_authorityexplains whether the live source, raw mirror, verified backup, or current DB is the authority for a repair.remote_source_syncclassifies remote gaps such as unavailable hosts, pruned upstream paths, local archive ahead of remote, and verified remote copies.
Treat missing upstream files as a preservation warning, not proof that the cass
archive is bad. If sole_copy_warnings is non-empty, take an archive export or
backup verification path before any repair that could replace canonical state.
The legacy command remains available for low-risk derived repairs:
cass doctor --fix --jsonFor a derived refresh request:
cass doctor --fix --force-rebuild --jsonSafe auto-run is intentionally narrow. It can apply only predeclared safe actions and must emit receipts for every mutation. It must fail closed when archive coverage, source authority, prior repair failure markers, or storage-pressure evidence make the action unsafe.
Use explicit repair for candidate-based archive work.
-
Generate a read-only plan:
cass doctor repair --dry-run --json
-
Inspect:
repair_plan.plan_fingerprintrepair_plan.apply_commandcandidate_stagingcoverage_summarysource_authoritysafety_gatesforensic_bundle.artifact_manifest_path
-
Apply only the exact inspected fingerprint:
cass doctor repair --yes --plan-fingerprint <plan_fingerprint> --json
-
Confirm:
operation_outcome.kindis an applied or no-op outcome, not blockedpost_repair_probesshow successful read/write verificationreceipt.pathorreceipts[]existscoverage_summarydid not shrink- rollback or restore guidance is present if promotion failed
If repair_failure_marker.status shows a previous failed repair, do not loop
blindly. Re-run the dry-run and use --allow-repeated-repair only when the
reported failure marker is part of the plan you inspected.
Reconstruction builds an isolated candidate from verified authority, such as the raw mirror or a verified backup. It must not mutate the live archive while the candidate is being built.
Current operator entry point:
cass doctor repair --dry-run --jsonInspect candidate_staging and source_authority. When a completed candidate is
eligible for promotion, the repair dry-run emits the fingerprinted apply command.
Promotion must still pass non-decreasing coverage, integrity checks, and
post-repair probes.
The doctor-reconstruct-dry-run schema in cass introspect --json documents the
candidate contract for automation. Treat any example path in documentation as
illustrative unless it comes from an actual scripts/e2e/doctor_v2.sh run
artifact.
List backups before trusting a restore target:
cass doctor backups list --jsonVerify a specific backup:
cass doctor backups verify <backup_id> --jsonRun the restore rehearsal first. This is the default no-mutation restore mode:
cass doctor backups restore <backup_id> --jsonInspect restore_plan.plan_fingerprint, restore_rehearsal.status, manifest
hashes, sidecar completeness, and the rehearsal receipt. Apply only the matching
fingerprint:
cass doctor backups restore <backup_id> --yes --plan-fingerprint <plan_fingerprint> --jsonRestore apply must capture a pre-restore backup, build a candidate, verify the candidate, promote atomically, and emit a restore receipt. If any verification fails, stop and keep all artifacts for inspection.
Cleanup is for derived or explicitly reclaimable assets, not archive evidence.
cass doctor cleanup --json
cass doctor cleanup --yes --plan-fingerprint <plan_fingerprint> --jsonArchive normalize may add metadata annotations for hygiene findings. It must not rewrite raw session blobs or canonical archive rows.
cass doctor archive-normalize --dry-run --json
cass doctor archive-normalize --yes --plan-fingerprint <plan_fingerprint> --jsonIf either command routes a finding to repair, reconstruct, or restore, leave it out of cleanup and follow the higher-authority workflow.
Use archive export or relocation planning when the archive is precious and the current filesystem is under pressure.
Plan export:
cass doctor archive export /absolute/target/cass-archive-export --jsonApply export:
cass doctor archive export /absolute/target/cass-archive-export --yes --plan-fingerprint <plan_fingerprint> --jsonVerify a copied bundle:
cass doctor archive export verify /absolute/target/cass-archive-export --jsonFor relocation planning, use:
cass doctor archive relocate /absolute/target/cass-archive --jsonImportant fields:
archive_export_plan.plan_fingerprintrequired_bytescopied_bytesverified_asset_classesskipped_asset_classesprivacy_modecompressionencryptionconfig_update_statusold_archive_retainedwill_delete_old_archivereceiptsevent_log_pathverify_status
The old archive is retained. If will_delete_old_archive is ever true, stop and
audit the implementation before proceeding.
Save a baseline before risky investigation or after a known-good state:
cass doctor baseline save --jsonDiff a later state against it:
cass doctor baseline diff <baseline_id> --jsonUpdate a baseline only when the new state is intentionally the new known-good reference:
cass doctor baseline update <baseline_id> --jsonBaseline outputs are diagnostic-only. They should include artifact manifests and redacted paths; they should not mutate archive evidence.
Create a scrubbed support bundle:
cass doctor support-bundle --jsonVerify the manifest before sending or attaching it:
cass doctor support-bundle verify <bundle_or_manifest_path> --jsonDefault bundles are redacted diagnostic handoffs, not backups. They exclude raw session content, raw mirror blobs, the full SQLite archive, encrypted payloads, environment secrets, private source snippets, and full home-directory paths.
Support checklist:
cass doctor check --jsonoutput- latest
failure_context.json, if present - support bundle
manifest.json artifact_manifest_pathvalues referenced by doctor outputsevent_log_pathvalues referenced by doctor outputs- baseline diff JSON, if a baseline exists
- backup verification JSON, if restore is being discussed
- exact command line and exit code for the failing command
- no raw session logs, no full SQLite archive copy, and no private source files unless the user explicitly opts into sensitive evidence attachment
Symptom: err.kind is lock-busy, or operation_state reports an active
doctor, index, or watch owner.
Action: wait for the owner, retry cass doctor check --json, and attach lock
diagnostics if it stays busy. Do not remove lock files by hand.
Symptom: storage_pressure.status is degraded or
recommended_action mentions archive export, relocation, or cleanup.
Action: run archive export planning first, verify the target has enough space, then run cleanup only for derived/reclaimable assets with a matching fingerprint.
Symptom: fallback_mode is lexical, semantic model fields report absent
models, or search remains lexical-only.
Action: this is usually not an archive repair issue. Run:
cass models status --jsonInstall models only when the operator consents:
cass models install --jsonSymptom: remote_source_sync.status or source_inventory reports unavailable
hosts, pruned paths, or local archive ahead of remote.
Action: preserve local cass evidence, then run:
cass sources sync --all --jsonIf the remote harness pruned logs, do not assume a local archive row is invalid.
Use source_authority and coverage_summary.
Symptom: repair apply wrote a receipt but post_repair_probes reports failed
read/write checks.
Action: stop. Collect the receipt, failure context, candidate manifest, pre-mutation backup manifest, and event log. Use backup verify/restore rehearsal before any further apply.
Symptom: repair_failure_marker.status reports a previous failed repair.
Action: do not re-run apply with the old fingerprint. Re-run the dry-run, inspect
the marker, and use --allow-repeated-repair only when the new plan explicitly
accounts for the marker.
Symptom: support bundle verify reports missing_artifact,
checksum_mismatch, extra_file, or unsafe_path.
Action: regenerate the bundle from the same cass data directory and verify the new manifest. Do not edit manifests by hand.
The doctor v2 scripted runner is the source for reproducible journey artifacts:
scripts/e2e/doctor_v2.sh list --json
scripts/e2e/doctor_v2.sh describe <scenario_id> --json
scripts/e2e/doctor_v2.sh run <scenario_id> --json --artifact-dir /tmp/cass-doctor-e2eEach run writes an artifact directory with run-summary.json, command stdout and
stderr, JSON snapshots, file-tree diffs, checksums, receipts, failure contexts,
and rerun commands. Any artifact path shown in docs should either come from one
of those fixture runs or be clearly marked illustrative.
Stop and inspect manually when:
- a plan would reduce coverage
source_authorityis ambiguous- sole-copy warnings are present and no verified export or backup exists
- a target path is inside a source path, symlinked unexpectedly, or not absolute
- a plan fingerprint does not match the inspected dry-run
- restore rehearsal fails
- post-repair probes fail
- support-bundle verification fails
- a command suggests deleting, hand-removing, or overwriting archive evidence
The safe default is to keep every artifact and gather a support bundle.