Guide
Routing disposition vs acceptance state: two questions hiding inside "what was the outcome?"
Your workflow asks "which path next?" The economic question is "which units counted, and what was earned?" Spoolis records only the second, per unit, signed. Your dispositions stay yours, your orchestrator stays the judge, and one result can serve systems with different policies.
Here's a design conversation I keep having. A team runs agent workflows, and after a work step their orchestrator decides where the run goes next: continue, retry, escalate to a human, mark the case ineligible. Then they look at Spoolis and ask where eligible or needs review fits in our result schema. The answer is: it doesn't, on purpose, and the reason is worth spelling out because it decides who stays in charge of your workflow. You do.
Two different questions
"What was the outcome?" hides two questions that deserve different owners:
- The acceptance question. Against the agreement that was declared before the work: which units counted, which didn't, which couldn't be resolved, and what was earned. The answer is per unit: accepted, rejected, or uncertain, plus an earned amount. It's a fact about the work against the agreement, and it's the same fact for every reader.
- The routing question. Given that result, which named path should this run in this system take next: proceed, retry, escalate, mark ineligible, hold for review. That answer is policy. It depends on your risk tolerance, your SLAs, your review capacity, and it can legitimately differ between two systems reading the same result.
An acceptance state is universal; a routing disposition is one consumer's decision. When a schema mixes them, whoever runs the verification quietly becomes the owner of everyone's routing policy. That's the thing we refuse to be.
Why doesn't Spoolis record "needs review"?
Because "needs review" isn't a fact about the delivery. It's a decision about what your organization does when a fact is unwelcome or unresolved. Two teams can read the same result, 91 accepted, 4 rejected, 5 uncertain, and route differently: one pays for 91 and retries 9, one holds the whole batch for a human because 4 rejections in this account is a red flag. Both are reasonable. Neither belongs inside the signed record, because baking either one in would make the record wrong for the other team.
So the Outcome Receipt records the acceptance state and stops. Uncertain stays uncertain: the record preserves that the question couldn't be resolved under the declared agreement, rather than rounding it to pass or fail. What to do about uncertainty is, again, routing, and it's yours. When Spoolis decides and when you decide draws this boundary across the whole product.
Your orchestrator stays the judge
If you run an orchestration framework, the framework is already good at routing. Conditional edges in LangGraph, retry policies in Temporal, steps in Cloudflare Workflows. Nothing about verification should take that from it. The shape that works:
- Declare the agreement before the work. What counts, per unit, in checkable terms. The agreement can also name your own judge for the parts only you can decide.
- Verify the delivery against it. Out comes the per-unit acceptance state and a signed receipt.
- Apply your policy in your orchestrator. Map accepted/rejected/uncertain onto your own dispositions: eligible, ineligible, needs review, retry, escalate. Continue with the accepted work, retry the rest. The mapping is yours, versioned with your workflow, changeable without touching the record.
The orchestrator keeps every judgment call it wants to keep. What it gains is a decision input it didn't have to compute, and a record it can hand to systems that weren't in the room, who can verify it themselves.
Why keeping them apart pays off
- One result, several consumers. Your workflow routes on it, billing pays on it, an audit reads it later. Each applies its own policy to the same signed fact. Fold routing into the record and it serves exactly one consumer. Who decides what counted is the long version.
- Policy can change without rewriting history. Tighten your review threshold next quarter and old receipts stay true; only the mapping changed. A record that says "needs review" is stale the day your review policy moves.
- Disagreement becomes legible. When two systems route the same result differently, that's visible policy divergence, not a data conflict. A consumption event can record which policy a consumer applied to the result it read.
- The economic fact stays clean. Earned amounts computed from acceptance states survive every reorganization of your workflow's named paths.
What this doesn't mean
- It doesn't mean routing is trivial. Your dispositions encode real operational judgment; that's exactly why they belong in your system, versioned by you.
- It doesn't mean Spoolis never says no. The acceptance state itself is strict: a unit that fails a declared check is rejected whatever any consumer would prefer.
- It doesn't mean every workflow needs this separation on day one. A single consumer with a hardcoded mapping is fine. The separation starts paying when a second system reads the same result, and it costs nothing to have from the start.
Notes
The acceptance vocabulary here (accepted, rejected, uncertain, earned amount) is specified in the Outcome Receipt specification. The orchestrator framing extends the "Routing disposition vs acceptance state" section of the Bring your own judge guide.