Files
Dicklesworthstone 4f023d4e4e feat(doctor): land world-class doctor surface (chokepoint, runs, undo, robot-docs, ergonomics)
Implements the world-class-doctor pattern (24-axiom kernel) for cass: the
doctor subcommand becomes the single agent-ergonomic entrypoint for
self-diagnosis, repair, undo, audit, and capability reflection — all
routed through one mutate() chokepoint with capabilities reflection and
per-run artifact substrate.

New modules in src/:
- doctor_chokepoint.rs   — single mutate() callsite with the 8-step contract
                           (capability check → backup → mutate → verify → log).
- doctor_runs.rs         — per-run artifact substrate at <data_dir>/doctor/runs/<run-id>/
                           with manifest, actions.jsonl, and byte-identical backups.
- doctor_undo.rs         — reverse-walk actions.jsonl with hash verification and
                           byte-identical restore from per-run backups; refuses on
                           any post-mutation tampering.
- doctor_robot_docs.rs   — emits the doctor's capability surface (detectors,
                           fixers, exit codes, data paths, env vars) in one envelope.

CLI flags exposed on doctor (all hidden until stabilized):
- --ls                     list per-run dirs (newest-first JSON when --robot)
- --undo <run-id|latest>   undo by id with hash verification
- --robot-triage           one-shot mega-command: summary + findings +
                           actions_planned + recommended_command + capabilities_url
- --diff [<ref>]           show what --fix would change (read-only)
- --gc-before <ISO8601>    quarantine runs older than DATE (requires --yes)
- --watch / --watch-interval-ms / --watch-iterations
                           long-running monitor that emits JSONL events on run dir
                           changes; bounded poll interval [500, 60000] ms
- --explain <run-id|latest> emit run manifest + actions + flat band timeline
- --emit-capabilities      extended capability surface (detectors[], fixers[],
                           exit_codes[], data_paths[], env_vars[])
- --allow-repeated-repair  permit mutating repair when a prior failure marker exists

Tests:
- tests/cli_robot.rs            new robot envelope assertions for the new flags
- tests/doctor_fixtures/        fixture inputs for each detector/fixer pairing
- tests/doctor_fixtures_round_trip.rs   round-trip every fixture: detect → fix → undo
- tests/doctor_mutate_auditor.rs        rejects any mutation that bypasses mutate()
- tests/doctor_pass1_runs_integration.rs persists run-id, manifest, actions.jsonl

Golden updates:
- robot/capabilities.json.golden, doctor.json.golden, doctor_shape.json.golden,
  doctor_quarantine.json.golden, introspect.json.golden  — reflect the new
  doctor surface and capability schema.

Companion docs in README.md describe the recommended agent flow:
robot-triage → fix → ls → undo if needed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-10 07:10:35 -04:00
..

cass doctor fixture suite — pass-1

Phase 9 deliverable. One fixture per representative failure mode plus the round-trip regression test asserting corrupt → doctor --fix → undo → byte-identical.

Pass-1 ships a representative slice of fixtures (5 of the 136 catalogued FMs). Each fixture is self-contained and can be invoked from tests/doctor_fixtures_round_trip.rs (added in this pass).

Pass-2 extends to all P0/P1 FMs (~30 fixtures); pass-3 covers P2/P3.

Layout

tests/doctor_fixtures/
├── README.md                                    (this file)
├── fm-pass1-foundation/
│   ├── corrupt.rs                              corruption helper (writes a known-bad state)
│   └── expected_after_fix.txt                  text describing the post-fix state
├── fm-storage-stale-wal-shm/
│   ├── corrupt.rs
│   └── expected_after_fix.txt
├── fm-tui-state-json-corrupt/
│   ├── corrupt.rs
│   └── expected_after_fix.txt
├── fm-cli_robot-schema-version-missing/
│   └── README.md                               (regression spec; no on-disk fixture needed)
└── fm-update_check-clock-rollback/
    ├── corrupt.rs
    └── expected_after_fix.txt

Round-trip contract

Every fixture must satisfy this round-trip in the regression test:

1. corrupt(data_dir)                        → on-disk state matches expected corruption
2. cass doctor                              → finding emitted with the FM's stable id
3. cass doctor --fix                        → mutation applied; report.json::operation_outcome.kind == "fixed"
4. cass doctor                              → exit 0, no findings
5. cass doctor undo <run-id>                → byte-identical to step 1's corrupted state

Step 5 is the strongest invariant: undo must be a true inverse, not a "best-effort restore."

Pass-1 scope

In pass-1 the round-trip is exercised against the new pass-1 modules (doctor_runs, doctor_chokepoint, doctor_undo, doctor_robot_docs) directly because the dispatch wiring into run_doctor_impl() is deferred to pass-2. The fixture infrastructure is in place; pass-2 adds cass doctor invocation in steps 2-5.

For pass-1, the fixtures mainly serve to:

  1. Document what "corruption" looks like for each FM (so the chokepoint integration knows what state to repair from).
  2. Provide a smoke target for cargo test --test doctor_fixtures_round_trip.
  3. Pin the fixture layout for future passes.