3.3 KiB
3.3 KiB
T4.3 — Lazy blob access
| Field | Value |
|---|---|
| Phase | P4 — Verification |
| Size | S — under 1 day |
| Status | Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
Goal
A verifier that needs no text performs no blob reads.
Facts (inlined — no spec read needed)
- Context partitions hold identifiers — packed, available-but-not-packed, dropped — and are small enough to inline. Prompts and outputs are large and go by reference.
- Laziness matters concretely: a verifier that shells out and checks an exit code needs none of this. Making every verifier carry prompt text penalizes the common case and blows broker payload limits.
VerifierCtx.blobs: Arc<dyn BlobStore>is the mechanism — the verifier callsgetif and only if it wants a body.getmay returnNoneafter reduction (T8.4); that is a normal answer, and a verifier must not treat it as an error.
Steps
- Confirm
EpisodeViewcarriesBlobRefonly. Noprompt_textfield, no eagerly-resolved cache. - Pass the store handle through
VerifierCtx.blobs. - Instrument the store with a call counter behind a test-only wrapper — counting is what turns this from an intention into an assertion.
- Write the exit-code verifier used as the acceptance case: it reads the attempt state and nothing else.
- Write a second, text-reading verifier and assert its call count is exactly the number of refs it asked for — no over-fetch, no prefetch-all.
Acceptance
- An exit-code verifier records zero
BlobStore::getcalls.
Verify
Harness: a counting BlobStore decorator wrapping the real store, injected
through VerifierCtx.blobs.
Integration test — tests/it_lazy_blobs.rs:
- Run a real run with an exit-code verifier that reads only attempt state.
- Assert the counter is exactly 0.
- Run a text-reading verifier that resolves 2 refs. Assert the counter is exactly 2 — not more (no prefetch) and not fewer (no silent cache hit masking a missing read).
- Assert
EpisodeViewhas no field holding blob bytes — a compile-level check if the type is closed, otherwise a serialization size assertion on a run with a 1 MB prompt: the view must stay small. - Reduction interaction: delete a blob body, then run the text verifier; assert
getreturnsOk(None)and the verifier handles it without erroring. - Assert the counter is per-run, not global, so parallel tests do not mask each other.
Command: cargo test -p verify lazy_blobs
False pass:
- Counting at the store level while a caching layer sits above it. The count then measures cache misses, not verifier behaviour. Wrap the handle the verifier actually receives.
- Step 4 omitted: a
prompt_textconvenience field makes every verifier pay, and steps 1–3 still pass if the resolution happens at view-build time rather than throughcx.blobs. The size assertion catches that.
Traps
- A "convenience"
EpisodeView::prompt_text()that resolves on access. Every verifier then pays, invisibly. - Prefetching all refs when the view is built, which is the same regression one layer earlier.
Background (not required to do this task): rust-agentic-sys.md §10.1 · rust-agentic-task.md