(tasks) add tasks for harness
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# T2.4 — Schema evolution end-to-end
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Phase | P2 — Durability hard parts |
|
||||
| Size | M — 1 to 3 days |
|
||||
| Status | Not started |
|
||||
| Flags | — |
|
||||
| Spec | inlined below |
|
||||
| Blocks | — |
|
||||
|
||||
## Goal
|
||||
|
||||
Change the event enum for real and prove a log recorded in P1 still folds. This
|
||||
is T0.4's framework exercised against actual history rather than a synthetic
|
||||
fixture.
|
||||
|
||||
## Facts (inlined — no spec read needed)
|
||||
|
||||
- Depends on T0.4 (upcaster registry) and T0.3 (`SchemaVersion` on every record).
|
||||
- The rules being tested: variants are **never removed or repurposed**;
|
||||
deprecated variants stay decodable forever; migrations are upcasters applied on
|
||||
read, never a rewrite of stored records.
|
||||
- The failure this prevents: two years of records, one `WorkEvent` variant
|
||||
renamed, and the drop-and-re-fold property is silently gone. Nothing fails at
|
||||
the time of the rename — it fails at the first cold rebuild.
|
||||
- The v1 fixture must be a **real P1 log**, not a hand-written one. A synthetic
|
||||
fixture only tests the variants whoever wrote it remembered.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Capture a full P1 run's log as a committed fixture, at v1, with its blobs.
|
||||
Store the expected folded state alongside it.
|
||||
2. Make a genuine v2 change: add a field to an existing variant, or split one
|
||||
variant into two. Do not rename or delete anything.
|
||||
3. Bump `CURRENT_SCHEMA` to v2 and register the v1→v2 upcaster.
|
||||
4. Run the fold over the v1 fixture under the v2 binary; assert the folded state
|
||||
equals the recorded expectation.
|
||||
5. Record a fresh v2 fixture from the same workflow and assert the two folded
|
||||
states agree — an upcast v1 log and a native v2 log must be
|
||||
indistinguishable downstream.
|
||||
6. Extend T0.3's directory-walk fixture test so both version folders are covered
|
||||
permanently, not just in this task's test.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- A v1 log fixture recorded in P1 still folds correctly after the event enum
|
||||
changes.
|
||||
|
||||
## Verify
|
||||
|
||||
**Harness:** a **real P1 run's** log committed as a fixture, with its expected
|
||||
folded state committed beside it. Not hand-written.
|
||||
|
||||
**Integration test** — `tests/it_schema_evolution.rs`:
|
||||
1. Under the v2 binary, fold the committed v1 fixture → `state_a`.
|
||||
2. Assert `state_a` equals the committed expected state, byte for byte.
|
||||
3. Record a fresh v2 run of the same workflow → fold → `state_b`.
|
||||
4. Assert `state_a` and `state_b` are equivalent under the fields that should not
|
||||
have changed. An upcast v1 log and a native v2 log must be indistinguishable
|
||||
downstream.
|
||||
5. Assert the v1 fixture file's bytes are unchanged by the test run — the fixture
|
||||
is read-only history.
|
||||
6. Variant-removal guard: a test that enumerates v1's variant set and asserts
|
||||
every one is still decodable under v2.
|
||||
|
||||
**Command:** `cargo test -p log schema_evolution`
|
||||
|
||||
**False pass:**
|
||||
- Regenerating the fixture when the test goes red. That is the one move that
|
||||
destroys the guarantee — the fixture is the historical record, the upcaster is
|
||||
what changes. Make the fixture path read-only in the test and assert on that.
|
||||
- A v2 change that touches no variant present in the P1 fixture, so no upcaster
|
||||
logic runs. Step 6 catches the removal case; choose a v2 change that provably
|
||||
affects a recorded variant.
|
||||
|
||||
## Traps
|
||||
|
||||
- "Fixing" the fixture bytes when the test fails. The fixture is the historical
|
||||
record; the upcaster is what changes.
|
||||
- A v2 change that removes a variant, which passes this test today because
|
||||
nothing in the P1 fixture used it, and breaks the moment an older log does.
|
||||
|
||||
---
|
||||
|
||||
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