3.3 KiB
3.3 KiB
T1.6 — Prompt and output blob capture
| Field | Value |
|---|---|
| Phase | P1 — Walking skeleton |
| Size | S — under 1 day |
| Status | Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
Goal
Write the prompt to the blob store when it is built, and the output when the
model responds. Record both as BlobRef on the attempt.
Facts (inlined — no spec read needed)
- Two capture points:
prompt-builtand model response. The prior implementation had neither — every downstream consumer worked from identifiers alone and could not answer "what did the agent actually see". - Prompts and outputs are large, so they go by reference; context partitions are identifiers and go inline (T1.5). That split is what makes lazy blob access (T4.3) possible.
- Blobs are content-addressed within a tenant, never across (T0.7).
- A
BlobRefwhose body later returnsNoneis normal after reduction (T8.4) — the log carries aReduced { original, summary }event saying what replaced it.
Steps
- At prompt assembly, serialize the final prompt,
BlobStore::put, keep the returnedBlobRef. - On model response,
putthe raw output, keep itsBlobRef. - Attach both refs to the attempt record; commit them in the same
EventLog::commitas the attempt transition, so a crash cannot leave a dangling ref in state with no log record. - Surface as
AttemptView.prompt: Option<BlobRef>andAttemptView.output: Option<BlobRef>. - Test across a process restart: complete a run, drop the process, reopen the store, fetch the prompt by ref, assert the text.
Acceptance
- Prompt text retrievable from the blob store by ref after a process restart.
Verify
Harness: embedded store on a temp path that survives process exit; the test runs the agent in a child process, then reopens the store in the parent.
Integration test — tests/it_blob_capture_restart.rs:
- Child process: run one model step to completion, print the store path, exit.
- Parent: reopen the store, read the attempt, take
promptandoutputrefs. BlobStore::getboth; assert the prompt bytes equal the assembled prompt (with template variables substituted), not the template.- Re-hash both bodies; assert each matches its ref.
- Crash case: arm a fault hook between the blob
putand the commit; assert on reopen there is no attempt record pointing at a body-less ref, and no orphan body that no record points at.
Command: cargo test -p executor blob_capture -- --test-threads=1
False pass:
- Reading the blob back in the same process from a warm cache. The restart is the point — an in-memory blob map passes everything else.
- Asserting the prompt is non-empty rather than comparing to the expected assembled text. Capturing the template instead of the rendered prompt passes a non-empty check.
Traps
- Putting the blob outside the commit transaction and recording the ref inside it, or the reverse. Either way a crash leaves a ref with no body or a body no record points at.
- Capturing the prompt template instead of the assembled prompt. The template is in the workflow definition; what the model saw is not.
Background (not required to do this task): rust-agentic-sys.md §8.6, §10.1 · rust-agentic-task.md