--- id: SMH-PLAN-CORE0002 type: plan title: "Frame Recovery, Session Identity, and Core Gates" spec: SMH-SPEC-SPEC0001 status: approved depends_on: [SMH-PLAN-CORE0001] --- # Frame Recovery, Session Identity, and Core Gates Remediation plan for the gaps found auditing `SMH-PLAN-CORE0001` against the code. `SMH-PLAN-CORE0001` stays approved and unchanged; this plan carries its unmet work to exit. ## Entry - `smith` and `smith-core` implement types, framing, store, tools, and bash. - The frame-recovery stop condition of `SMH-PLAN-CORE0001` is resolved by the decision below. ## Decisions ### Frame format v2 Wire layout, little endian: ```text [len u32][kind u16][version u16][crc32 u32][CBOR payload] ``` `len` counts every byte after itself, so skip-by-declared-length recovery is unchanged. `kind` discriminates the payload; `SessionHeader` and `Entry` exist now, further kinds are reserved. `crc32` covers kind, version, and payload. Recovery decision table: | crc32 | kind | outcome | | --- | --- | --- | | valid | known | decode; a decode failure is schema damage and is reported | | valid | unknown | future frame, preserved verbatim on round trip | | invalid | any | corruption, reported as damage, skipped by declared length | Damage is reported, not fatal. Loading returns recovered frames plus a recovery report, because complete frames must survive alongside explicit damage reporting. No v1 migration exists because nothing is released; v1 files are rejected by version. ### Error taxonomy One variant per layer, typed per-layer codes, no stringly codes. | layer | carries | | --- | --- | | framing | fault kind and byte offset | | storage | operation and path | | session | branch, entry, and leaf faults | | tools | tool name and `RecordFailed { mutation_applied }` | | config | dotted field path | | control | cancellation as its own variant | `SmithError` stays serializable, so operating-system causes flatten into messages. ### Scope confirmations - Ignore behavior for list, find, and grep belongs to this plan. - Cancellation and timeout plumbing through tool invocation belongs to this plan. ## Order 1. Introduce the layered error taxonomy and frame format v2 with checksum, kind, version, and recovery reports. 2. Add the session header frame so session and branch identity survive reload. 3. Restore branch structure from parent links, add fork, and write real compaction boundary entries. 4. Serialize repair with the writer lock and keep publication atomic for created, forked, and repaired sessions. 5. Fix the tool invocation contract: record call, run effect, record result, and report `RecordFailed` with mutation state. 6. Plumb cancellation and configured timeout into every tool effect and wire the `bash` arm to `bash::execute`. 7. Add edit stale detection, ignore-aware recursive list, find, and grep, and canonical encoding at the entry boundary. 8. Emit tool, result, and compaction trace kinds, and make trace output byte-stable across loads. 9. Restore build gates: remove blanket crate allows and `doc(hidden)`, move `Config` into `smith`, delete duplicated cancellation and dead code. ## Interfaces - `smith::error`: layered faults with codes, offsets, paths, and field paths. - `smith::config`: validated configuration owned by the shared crate. - `smith-core::frame`: v2 layout, checksum verification, and damage classification. - `smith-core::store`: locked append, load with recovery report, fork, and locked repair. - `smith-core::tools`: cancellable, timeout-bounded, durably recorded invocation. ## Verification - Corrupt frames are distinguishable from future frames and reported explicitly. - Future frames still round-trip byte for byte. - Session and branch identity survive reload, so replay output is byte-stable across loads. - Repair cannot lose entries from a live writer. - Fork and restoration preserve IDs, order, leaf, and compaction boundary. - A successful mutation whose recording fails reports `mutation_applied`. - Cancelling or timing out any tool leaves no partial durable claim of success. - Ignore rules change list, find, and grep results deterministically. - `cargo x check` passes with no crate-level lint suppression. ## Exit Provider-free tool activity can be persisted, recovered, and reconstructed deterministically, and the workspace passes its gates without suppression. ## Stop conditions - Checksum coverage cannot separate corruption from schema evolution in practice. - Locked repair cannot stay atomic on a supported platform. - Ignore semantics require configuration that the spec does not define.