docs(plans): implementation plan — wave-based decomposition; wave 1 decomposed into tasks/

- docs/plans/implementation.md: the meta plan (alkstore pattern) — nine
  waves, dependency logic, decided points, review gates. Scope authority:
  v0.1.0 ships the full surface (all five engines, fleet GC, ops).
- Wave 1 decomposed: scaffold-crate-features, core-error-model,
  core-hashing-keys, core-trait-and-types, suite-scaffold,
  review-wave-1 (the one-way-door gate).
- Waves 2-9 shaped in the plan; each decomposes after the prior wave's
  review gate.

Verification: cargo test / clippy -D warnings / fmt --check green
(docs-only change).
This commit is contained in:
glm-5.3-flash committed 2026-10-11 17:43:02 +00:00
1 parent 6f6ab19b8e
commit 8a2df4fa57
7 files changed
+829

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
---
id: core-error-model
name: Error model — the one-enum family with altitude discipline
status: pending
depends_on: [scaffold-crate-features]
scope: single
risk: low
impact: component
level: implementation
tags: [wave-1, errors]
---
## Description
Implement the crate's error family (`src/error.rs`, re-exported from
`lib.rs`) per store-api.md's error model and ADR-012 §6.5:
- One `Error` enum (thiserror) with exactly the five distinguished
variants: `Missing`, `Verification`, `Io(String)`, `GcRefuse`,
`KeyInvalid`.
- **The altitude discipline in doc comments** (store-api.md's "one
enum, both altitudes"): the `Backend` trait's methods return this
family but its *effective* members are
`Missing`/`Verification`/`Io`/`KeyInvalid` — `KeyInvalid` never
fires at the trait boundary (keys arrive opaque there) and
`GcRefuse` never fires below the facade (arbitration answers flow up
as data; the facade decides and owns the refusal). The facade's
public surface re-exposes the family with `GcRefuse` added.
- Semantics per variant: `Missing` — key absent on ops that signal
absence via `Err` (`read_range`, `delete`); `get`/`stat` signal
absence with `None` and never carry `Missing`. `Verification` —
put/get hash-check failure (content ≠ key). `Io(String)` — backend
media failure, stringly because `std::io::Error` is not stable
across versions. `GcRefuse` — direct delete refused (protected key:
pinned, registered-source-live, or protect-callback-named).
`KeyInvalid` — malformed key bytes at the boundary (truncated,
unknown algorithm — rejects, never guesses).
- **Named design point for the review gate**: store-api.md's wording
("one enum, both altitudes… the trait's effective members… the
facade re-exposes them with `GcRefuse` added") is implemented as a
*single* enum with the altitude discipline carried by doc comments
and construction discipline (not two types). The gate audits this
reading against the spec text; if the gate reads it as requiring two
types, that is a cheap fix now.
No panics; no `unwrap`/`expect` outside tests; `#[non_exhaustive]` is
**not** applied unless the spec requires it (the variant set is
ADR-pinned; new failure families are new ADRs — match the family's
posture on alkstore's error taxonomy).
## Acceptance Criteria
- [ ] `Error` enum with the five variants, thiserror-derived
Display/Error impls
- [ ] Doc comments on the enum and each variant stating the semantics
and the altitude discipline verbatim-traceable to store-api.md
- [ ] Unit tests: each variant constructs; `Missing` documented
get/stat exclusion stated in docs (behavioral enforcement lands
with the facade in wave 2)
- [ ] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
`cargo fmt --check` green
## References
- docs/architecture/store-api.md (§Error model)
- docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §6.5, §1
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion