(tasks) add tasks for harness
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# T0.4 — Upcaster framework
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Phase | P0 — Foundations |
|
||||
| Size | M — 1 to 3 days |
|
||||
| Status | Not started |
|
||||
| Flags | — |
|
||||
| Spec | inlined below |
|
||||
| Blocks | T2.4 |
|
||||
|
||||
## Goal
|
||||
|
||||
Read-time migration chain so old log records fold correctly after the event enum
|
||||
changes. Never rewrite stored records.
|
||||
|
||||
## Facts (inlined — no spec read needed)
|
||||
|
||||
- Migrations are **upcasters**: `fn upcast(vN) -> vN+1`, applied on read.
|
||||
- Rewriting an append-only log is a contradiction. History stays as written; the
|
||||
reader adapts.
|
||||
- Registry keyed by version. Reading a v1 record under a v3 binary runs
|
||||
`v1→v2→v3` in sequence.
|
||||
- Deprecated variants stay decodable forever — an upcaster maps them forward, it
|
||||
does not delete them.
|
||||
- The guarantee is the fixture test: a stored fixture of every historical version
|
||||
still folds to the expected state.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Keep the per-version wire types as real types — `WorkEventV1`, `WorkEventV2`,
|
||||
… — with the current one aliased to `WorkEvent`.
|
||||
2. Define the upcaster shape: `fn(vN) -> vN+1`, either as function pointers or a
|
||||
`trait Upcast { type From; type To; fn upcast(from: Self::From) -> Self::To; }`.
|
||||
3. Build the registry keyed by `SchemaVersion`. Registration is explicit; a
|
||||
missing link is an error at registry construction, not at read time.
|
||||
4. `read_record(bytes)`: decode `schema`, decode the matching `vN` body, then
|
||||
apply each upcaster in order up to `CURRENT_SCHEMA`.
|
||||
5. Return typed errors — `UnknownSchemaVersion`, `MissingUpcaster { from, to }`.
|
||||
A corrupt or future-version record must not panic the fold.
|
||||
6. Build the synthetic v1→v2 migration as the test vehicle: add a field or split
|
||||
a variant in `WorkEventV2`, write the upcaster, commit fixtures for both.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Synthetic v1 → v2 migration with a fixture per version.
|
||||
- Folding a v1 log through the upcaster yields the **same state** as a
|
||||
natively-v2 log. Assert on the folded state, not on intermediate events.
|
||||
|
||||
## Verify
|
||||
|
||||
**Harness:** committed v1 and v2 fixtures, plus T0.8's fold.
|
||||
|
||||
**Integration test** — `tests/it_upcast_equivalence.rs`:
|
||||
1. Fold the committed **v1** log through the upcaster chain → `state_a`.
|
||||
2. Fold the committed **native v2** log directly → `state_b`.
|
||||
3. Assert `serialize(state_a) == serialize(state_b)` byte for byte.
|
||||
4. Instrument the registry with a counter; assert **at least one** upcaster
|
||||
actually ran on the v1 path.
|
||||
5. Feed a record stamped with an unknown future version; assert
|
||||
`UnknownSchemaVersion` is returned and **no panic** escapes.
|
||||
|
||||
**Command:** `cargo test -p log upcast`
|
||||
|
||||
**False pass:**
|
||||
- `CURRENT_SCHEMA` still equal to v1, so the chain is empty and both folds
|
||||
trivially agree. Step 4 is the guard.
|
||||
- Comparing folded states with a derived `PartialEq` over `HashMap`, which
|
||||
ignores ordering. Compare serialized bytes.
|
||||
- The v2 change being cosmetic (a renamed local, an added comment) so no upcaster
|
||||
logic is exercised. The v2 fixture must contain a record whose shape actually
|
||||
differs.
|
||||
|
||||
## Traps
|
||||
|
||||
- Lossy upcasters that default a new field to a value the fold treats as
|
||||
meaningful. If v1 cannot supply the field, the fold handles `Option` — it does
|
||||
not receive a fabricated value.
|
||||
- A registry populated by iteration order rather than an explicit chain. The gap
|
||||
only shows at v3.
|
||||
|
||||
---
|
||||
|
||||
Background (not required to do this task):
|
||||
[rust-agentic-sys.md](../../../rust-agentic-sys.md) §8.7 ·
|
||||
[rust-agentic-task.md](../../../rust-agentic-task.md)
|
||||
Reference in New Issue
Block a user