- Fix verify.md --changed exit code (0 → 2) - Add 'deep' as alias for 'thorough' in generation profile resolution - Fix PLUGIN_CONTRACTS_SPEC status: Partially implemented (registry done, runner pending) - Fix OUTBOUND_CONTRACT_MOCKING_SPEC status: Implemented (Phase 1) - Fix cli.md environment matrix to match actual code granularity - Fix chaos.md: document delay handler is currently a no-op - Fix getting-started.md warning: note APOPHIS does not proactively detect nondeterminism - Add variants section to getting-started.md - Build: clean | Tests: 849 pass, 0 fail
4.2 KiB
Verify Mode
Deterministic contract verification for CI and local development.
APOPHIS implements the invariant-driven approach from Invariant-Driven Automated Testing (Malhado Ribeiro, 2021): encode intended behavior as executable formulas, then verify them automatically with property-based generation and deterministic replay.
When to Use It
- Local development: Quick feedback on behavioral changes
- CI pipelines: Catch regressions before merge
- Pre-commit hooks: Fast smoke verification
Profile Examples
Quick (local smoke)
profiles: {
quick: {
name: 'quick',
mode: 'verify',
preset: 'safe-ci',
routes: ['POST /users']
}
}
CI (PR checks)
profiles: {
ci: {
name: 'ci',
mode: 'verify',
preset: 'safe-ci',
routes: []
}
}
Run with: apophis verify --profile ci --changed
Deep (nightly verification)
profiles: {
deep: {
name: 'deep',
mode: 'verify',
preset: 'safe-ci',
routes: []
}
}
Route Filtering
Filter routes with the --routes flag:
# Single route
apophis verify --routes "POST /users"
# Multiple routes (comma-separated)
apophis verify --routes "POST /users,PUT /users/:id"
# Wildcards
apophis verify --routes "POST /users/*"
# All routes (empty or omitted)
apophis verify --profile quick
* and ? wildcards are supported in --routes.
--changed Flag
Run only routes modified in the current git branch:
apophis verify --profile ci --changed
If no routes changed, exits 2 with a message.
Failure Output Format
When a contract fails, APOPHIS prints:
Contract violation
POST /users
Profile: quick
Seed: 42
Expected
response_code(GET /users/{response_body(this).id}) == 200
Observed
GET /users/usr-123 returned 404
Why this matters
The resource created by POST /users is not retrievable.
Replay
apophis replay --artifact reports/apophis/failure-2026-04-28T12-30-22Z.json
Next
Check the create/read consistency for POST /users and GET /users/{id}.
Replay Workflow
- Copy the replay command from failure output
- Run it with the recorded route, seed, and artifact data; source or dependency drift can change the outcome
- Fix the bug in your handler
- Re-run verify to confirm the fix
apophis replay --artifact reports/apophis/failure-2026-04-28T12-30-22Z.json
Nondeterminism warnings appear in output when the same seed produces different results across runs. This indicates stateful behavior in your application that contracts cannot control.
Machine Output for CI
Use concise formats to reduce log volume in large verify runs:
--format json-summary— single JSON with summary, failures, warnings. Omits per-step traces.--format ndjson-summary— three NDJSON lines:run.started,run.summary,run.completed.
Filtering examples
# Extract only failed routes from full ndjson
# Note: route.failed events are only emitted for failures, not passed routes
apophis verify --profile quick --format ndjson | jq 'select(.type == "route.failed")'
# Write artifact to disk and parse the file instead of stdout
apophis verify --profile quick --format json --artifact-dir reports/apophis
Exit Codes
| Code | Meaning |
|---|---|
| 0 | All contracts passed |
| 1 | One or more behavioral contracts failed |
| 2 | Config error, no routes matched, no contracts found, or not a git repo |
| 3 | Internal APOPHIS error |
| 130 | Interrupted (SIGINT) |
Config Example
// apophis.config.js
export default {
profile: 'quick',
profiles: {
quick: {
mode: 'verify',
preset: 'safe-ci',
routes: ['POST /users']
}
},
presets: {
'safe-ci': {
depth: 'quick',
timeout: 5000
}
}
};
For the full config schema, see CLI Reference.
Workspace Support
Run verify across all packages in a monorepo workspace:
apophis verify --workspace --profile quick --format json
Output includes per-package pass/fail summaries. Fails if any package fails.
--generation-profile Flag
Control test data generation depth independently from the verification profile:
apophis verify --profile quick --generation-profile quick