QUAYZ
telling a crash loop from an OOMKill, and naming the failure that no single field finds.
A crash loop and a container the kernel killed for memory are the same thing in `kubectl get pods`, and the remedy for one is not the remedy for the other. Five failures are produced against a cluster the test run creates and destroys, each read with six instruments, and the resulting matrix is what the taxonomy is checked against: three of its entries were wrong until they were joined to it, every one in the direction that flattered the repository.
- Tests
- 135
- Python
- 3.11 to 3.13
- Release
- v0.1.0
- Licence
- MIT
The demo, as it really ran
$ uv run python examples/tell_them_apart.py
Six instruments, five states, one cluster. Measured, not asserted.
phase restarts waiting terminated exit ready
------------------------------------------------------------------------------------
healthy Running no none none none 2
image cannot be pulled Pending no ImagePullBackOff none none 0
crash loop Running yes CrashLoopBackOff Error 1 0
killed for memory Running yes CrashLoopBackOff OOMKilled 137 0
alive but never ready Running no none none none 0
A crash loop and an OOMKill agree on 4 of these 6 columns (phase, restarts, waiting, ready).
They differ on 2: terminated, exit.
crash loop Error with exit 1
killed for memory OOMKilled with exit 137
And they present identically: 'killed for memory' shares its symptom.
What each instrument can do with that:
restart count separates nothing
container logs separates crash loop
pod phase separates image cannot be pulled
lastState.terminated.reason with exitCode separates crash loop, killed for memory
state.waiting.reason separates image cannot be pulled
EndpointSlice readiness separates nothing
every instrument at once, read together separates image cannot be pulled, crash loop, killed for memory, alive but never ready
terraform plan over a helm_release separates nothing
the declared objects against the live ones separates changed by hand afterwards
The pod that is alive and never ready differs from a HEALTHY pod in 1 column (ready),
and that column reads the same for every failure above. No single field finds it.
Output captured on 2026-08-28. It is committed to the repository and a test fails when it stops matching a live run, so this page cannot quietly drift from the code it describes.
Read it
- Source on GitHub the README carries the argument in full
- Release v0.1.0 changelog and tag
The rest of the toolset
- QUACKZ deflating a backtest that only looks good because it was picked out of two hundred
- QUOTEZ market data an agent can read and cannot act on
- QUELLZ measuring what prompt-injection containment costs in utility as well as in attack rate
- QUIDZ refusing the outbound payment that would have gone out twice
- QUESTZ stopping a scraper before it writes a CSV from a page that changed shape
- QUIZZ answering what a statistic said at the time, and refusing when it cannot
- QUARANTINEZ treating an outcome the venue never confirmed as terminal rather than as a retry
- QUENCHZ deciding in the open what a tool server gets free while it is still somebody's subprocess
- QUILTZ proving infrastructure code wrong without a cloud account, and saying what that cannot show
- QUARRYZ keeping every version a statistical office published, and failing the build when it quietly issues another
- QUASHZ refusing a row whose outcome had not been decided yet when the decision would have been made
- QUALMZ a fixed number of looks at the holdout, where re-running the same configuration does not buy another
- QUEUEZ ordering a feed by its sequence, because on a real recorded session the clock goes backwards
- QUANDARYZ counting the distinct screens a component can settle into when its responses arrive out of order