success starts arriving as succeeded. The changelog is silent, or nobody read it.
Detecting the change is the easy part. The rest is being able to reproduce it, fix it, and keep it fixed. pikopod is one cycle, and each stage feeds the next.
The stages
Stage 5 is the one nothing else does. You cannot ask a provider’s sandbox to return that exact 503, with that body, at that point in your state machine. pikopod can, because the same tool recorded it and owns the sandbox. Mocking tools have a sandbox and no observer; monitoring tools have an observer and no sandbox.
You do not have to adopt all of it. Stage 0 is the usual on-ramp: one line in CI, nothing installed in your request path. Import and the sandbox need no proxy at all.
Three tenses of one question
Everything pikopod does answers “what is this API about to do to me?”, asked about three different times. Each part covers what the others structurally cannot.
The sandbox is where you rehearse. The agent is the smoke detector. Replay is the evidence.
How the parts fit
One config file, onedata_dir, one command. pikopod up starts two listeners in one process: the sandbox on :4600 and the agent on :4700. They share the data directory and fail independently. If the sandbox listener dies, the message is loud and the agent keeps serving. Your production traffic does not depend on the sandbox being up.
up always starts both listeners. The spec watcher is also part of up, not a separate command, and arms per upstream whenever spec_source is set. Recordings made by the agent feed the sandbox’s replay tier only when you ask for it with --recordings-fallback on import, never silently.
It also crosses the two sides
A spec-diff tool reads what the provider published. Monitoring sees your traffic but throws response bodies away. pikopod holds both, so it can say things neither can:The spec removed this endpoint, and you’re still sending it 120 requests a day.Traffic evidence raises the severity of a declared change. A declared change downgrades an observed one to “documented, not silent”. Holding both sides is why a reproduction is possible at all.
What pikopod refuses to do
The refusals are the design, not gaps in it.- It never alerts on latency. Latency is noisy, environment-dependent, and rarely provable from the bytes. A request that failed is an incident; a request that was merely slow is nothing. pikopod sets no upstream timeout of its own, so an incident fires when your caller gives up, not when a stopwatch says so.
- It never enforces a guess. Model-extracted fields are simulated but marked DRAFT, capped in severity, never unlock redaction, and cannot bind an archetype without an explicit
--bind. - It never advances your pin on its own. A provider publishing a new spec generates findings; accepting them is an explicit
import --update. - It never lets internal failure touch your traffic. Observation is bounded and panic-isolated, and the proxy does not retry.
- It never reports clean when it cannot tell.
UNVERIFIABLEis a real outcome, distinct from a pass. See Exit codes.