Files
apophis-fastify/docs/verify.md
T
John Dvorak dc7a4205ec fix: correct documented vs actual behavior discrepancies from subworker audit
- 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
2026-04-30 11:50:39 -07:00

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

  1. Copy the replay command from failure output
  2. Run it with the recorded route, seed, and artifact data; source or dependency drift can change the outcome
  3. Fix the bug in your handler
  4. 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