Wunderspec
Wunderspec is a Python DSL for writing and checking executable specifications.
Distributed systems often fail due to unforeseen issues: message reordering, race condition, stale observations, retry behavior, crashes and restarts, network outages, vibe code. Adding more example tests is often not enough to find these bugs before they make it to production. Specifications written in Wunderspec surface these issues early, so that teams find design flaws before they become production incidents.
This is the open-core distribution.
📋 Wunderspec in 5 minutes: the Wunderspec in Five Minutes gives you a quick overview of the core concepts.
📋 Cheatsheet: the Wunderspec cheatsheet summarizes the DSL and CLI in a few pages — keep it open while you work.
💡 Using Quint? Try this command:
uv tool install wunderspec wunderspec convert --from=spec.qnt --to=spec.py --main=main
1. Wunderspec in Action
Follow Bob in his Wunderspec adventure. There, Bob writes a specification of a write-ahead log, finds a bug, replays the counterexample and fixes the specification.
2. Installation
Using uv:
uv tool install wunderspec
After installation, the CLI is available:
wunderspec --help
If you want to add Wunderspec as a dependency, just type:
uv add wunderspec
uv sync
3. Features
This open-core package includes the features marked ✅ in the Open Core column. Premium-only command names stay visible for discoverability, but those commands are not included in this package.
| Feature | Open Core | Premium |
|---|---|---|
| Symbolic expression evaluator | ✅ | ✅ |
wunderspec lint |
✅ | ✅ |
wunderspec run |
✅ | ✅ |
wunderspec replay |
✅ | ✅ |
wunderspec convert |
✅ | ✅ |
wunderspec check |
✅ | ✅ |
wunderspec with-tlc |
✅ | ✅ |
wunderspec with-apalache |
✅ | ✅ |
wunderspec fuzz |
❌ | ✅ |
wunderspec rust |
✅ | ✅ |
wunderspec lean |
❌ | ✅ |
Rust translation uses the Wunderspec SaaS service and requires a token in every edition. Offline JSON export is available without a token. See the Rust command guide.
4. Release Provenance
- Release tag:
v0.141.1 - Source commit:
6b9cd1dbbaccadc5846db03082e7a9b39868bcfb
See tests/README.md for the development test log captured at release time.
5. Latest Release Notes
Changes since public release v0.137.3.
- Changed (breaking): transfer format 1.1 replaces 1.0. Every instance parameter is
carried as the expression its factory builds (a literal is a
litnode), so instances with set, map, tuple, record, list, or union values (for exampleCORRECT=Set(0, 1, 2)) are no longer skipped, andwunderspec rust run,check, andreplay --instance NAMEwork for them. Format 1.0 is no longer read or written. - Added: when the service accepts another format version,
wunderspec rustexits 69 and names both versions. - Fixed:
wunderspec rust run,check, andreplaywith an--instancethat the export skipped blamed the cached model and suggested--no-cache. They now exit 65 before contacting the service and point to the export warning; so does a specification with parameters whose instances were all skipped. - Changed (breaking):
wunderspec rusthas the commands of the internalwunderspec-rust:compile --from SPEC --to DIR,run SPEC,check SPEC --property P, andreplay SPEC --property P, with the same options and defaults. They translate on the service, build the model locally with Cargo (Rust 1.85 or newer), and run it; verdicts, statuses, and replay commands matchwunderspec-rust. - Added: translations are reused while the transfer document and
--init,--step, and--propertyare unchanged, so other option changes never contact the service. They are kept in a per-user cache (WUNDERSPEC_CACHE_DIR, limited byWUNDERSPEC_CACHE_MAX_SIZE, default 2G) or in--to DIR;--no-cachetranslates again. Interrupted jobs are resumed; concurrent runs submit once. - Changed (breaking): the 0.139 forms are replaced:
SPEC -o DIRbycompile --from SPEC --to DIR --no-build,--exportbyexport SPEC --to FILE,--documentbysubmit FILE --to DIR, and--jobbyjob JOB_ID --to DIR. - Changed (breaking): exit statuses: model outcomes keep 0-3, 101, 124, and 130; usage
errors are 64, evaluation and translation failures 65, service refusals 69, refused
output 73, network errors 74, stopped waiting 75, configuration errors 78, missing
toolchain 79, build failures 80, and options a cached model rejects 81
(
wunderspec rust --help-exit). - Changed: the wait for the service is
--wait-timeoutoncompile,run,check, andreplay(--timeoutthere is the model's time limit, as inwunderspec-rust);submitandjobkeep--timeout. - Added:
wunderspec.rust_cli: the option table and model driver shared withwunderspec-rustand the help of generated models.
[0.139.0] -- unreleased
- Changed (breaking):
wunderspec rustreads the service address, token, and optional extra trust root from a service configuration file:--config FILE, elseWUNDERSPEC_CONFIG, else~/.wunderspec/service.yaml(keysservice,token,ca_file). The file must be owned by the user with mode 600. - Removed:
--service,--token-file,--ca-file,WUNDERSPEC_SERVICE_URL, andWUNDERSPEC_TOKEN. The removed options exit with status 2 and point to--config. Export mode needs no configuration. - Add
wunderspec.transfer: format 1.0 JSON export, strict validation and safe AST import, source locations, and the schema shared with the translation service. - Use AST constructors and their computed sorts for transfer validation; retain scope and document consistency checks without a separate sort-computation table.
- Move the backend-neutral gatherer and JSON encoder from wunderspec-lean
8cc1dcec2f7eb5f86345161a9a9bd677b2d72e66; encoding uses per-export state. - Replace the
wunderspec ruststub with an HTTPS service client in every edition: local export, document submission, job polling/resume, and safe transactional artifact extraction. Translation requires a SaaS token. - Add shared adversarial conformance tests, all-node and sort round trips, example schema checks, and HTTPS/archive security tests.
- Remove
wunderspec.ast.serialization,save_ast, andload_astwithout compatibility wrappers. JSON is the only supported AST transfer format. - Production service URL configuration and publication are separate.
6. License
Wunderspec is distributed under the Functional Source License, Version 1.1, with an Apache 2.0 future license (FSL-1.1-ALv2). See LICENSE.
Metadata
Release files for wunderspec 0.141.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wunderspec-0.141.1.tar.gz | 4.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wunderspec-0.141.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.7 MB
Release files / wunderspec-0.141.1.tar.gz
| Download URL | wunderspec-0.141.1.tar.gz |
|---|---|
| Size | 4.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
70ff5de197617cb237d16197db57634e03790268c0014efaa08a752d9789ab64
|
|
BLAKE2b-256 checksum How to use checksums |
c3d45f36cec70a865a5be2d4fc18062c77ce69876cb1adab40902d4b517226be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / wunderspec-0.141.1-py3-none-any.whl
| Download URL | wunderspec-0.141.1-py3-none-any.whl |
|---|---|
| Size | 340.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
33e8473c4ab852255db6577ab679b0440916700dc15482f3d65e02a3c97aedd3
|
|
BLAKE2b-256 checksum How to use checksums |
7d11a1aee6668a1747ee66cebce3a53e7cbff9a77442ab8b81ac54c07acce421
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log