Deterministic. Versioned.
Replayable.

Every Pegana alert is the output of a pure function over four inputs: the asset's intrinsic value, the executable market quote, threshold configuration from assets.toml, and the EWMA + hysteresis state at the moment of decision. The function lives in the open-source methodology Rust crate, versioned by semver, pinned to a git tag.

spread = 1 − market / intrinsic

Verify any alert.

Install the verifier from releases.pegana.xyz — a self-hosted mirror that ships a SHA-256-pinned binary plus a Sigstore attestation.

verify.shshell
# Install (curl|sh — reads SHA256SUMS, verifies, drops the
# binary in ~/.pegana/bin/, no daemon)
curl --proto '=https' --tlsv1.2 -LsSf \
  https://releases.pegana.xyz/pegana-replay-installer.sh | sh

# Verify a single alert
pegana-replay --alert-id <UUID>

# Verify the on-chain commitment too
pegana-replay --alert-id <UUID> --verify-onchain

Ships a pre-built binary for aarch64-apple-darwin; other platforms fall back to cargo install --git until the GA Sigstore fan-out. Source

A version has three states.

The engine refuses to start on a broken version — past receipts from broken versions stay queryable and replayable, but render a warning.

active

currently emitting receipts

The version the running engine is built against. Receipts produced by this version are trusted.

deprecated

superseded, still valid

A newer version is active. Receipts from this version remain valid and replayable.

broken

bug confirmed, engine refuses to run

A bug was found post-release. The engine refuses to start to prevent bad alerts. Past receipts are preserved with a warning.

The canon, hashed into every receipt.

Every receipt hashes the canonical assets.toml as part of its inputs. Replay still works against historical receipts — each receipt embeds the canonical TOML it was produced under.

21active assets across6classes
LST8Stable · Yield6Stablecoin3Stable · CDP2Stable · DN1Synth · Leverage1
SymbolClassPeg targetVerified
jitoSOLLSTSOLon-chain
mSOLLSTSOLon-chain
bSOLLSTSOLon-chain
INFLSTSOLon-chain
bbSOLLSTSOLon-chain
JupSOLLSTSOLon-chain
USDCStablecoinUSDon-chain
USDTStablecoinUSDon-chain

Plus 7 symbols kept in the canon but currently inactive: BRZ, pbUSDC, JupUSD, JLP, EURC, dzSOL, vSOL.

Methodology changelog.

Rendered at build time from crates/methodology/CHANGELOG.md.

v0.3.02026-06-04

Behavior change (MINOR). Activated immediately under the ADR-0009 critical-bug exception ("wrong alerts firing"): during the calibration window hyUSD flapped PEGGED↔DRIFT ~52× in two days as its collateral ratio oscillated around the 130% drift band (oracle jitter on the SOL-priced reserves clipping the threshold). The CR classification path carried neither the EWMA smoothing nor the magnitude deadband the spread path already had (ADR-0021).

  • CR magnitude hysteresis (Schmitt-trigger deadband) — new classify_cr_with_hysteresis. The CR analog of classify_with_hysteresis with the band inverted (for a collateral ratio, a LOWER value is worse). A worsening CR escalates at the normal threshold; a relaxation toward a looser state only commits once CR rises above threshold × (1 + deadband_pct) (engine default 2%). Why: time-hysteresis (transition.rs confirmup/decaydown) alone could not stop sustained oscillation at the boundary. Measured on the calibration window, the deadband cut hyUSD's transitions ~80% (52 → ~10) while keeping escalation immediate.

Receipt schema: v1 (unchanged). Verdicts change for some valid hyUSD inputs, hence the MINOR bump; replay stays deterministic via the recorded methodology_git_sha. See ADR-0023. v0.2.0 → deprecated (still valid for replay), superseded by 0.3.0.

v0.2.02026-06-01

Behavior change (MINOR). Activated immediately under the ADR-0009 critical-bug exception ("wrong alerts firing"): v0.1.0's symmetric classification was emitting two classes of false alerts during the calibration window — DRIFT↔PEGGED flapping when a smoothed discount sat near a threshold, and a 🚨 DRIFT on a benign LST premium (market above redemption value).

  • Magnitude hysteresis (Schmitt-trigger deadband) — new classify_with_hysteresis. Escalation still uses the normal threshold, but a relaxation toward a looser state only commits once the smoothed discount falls below threshold × (1 − deadband_pct) (engine default 25%). Time-hysteresis (transition.rs confirmup/decaydown) alone could not stop oscillation at the boundary. Why: JupSOL flapped DRIFT↔PEGGED around 60 bps (e.g. 84.7 → 48.8 bps); the deadband (exit 45 bps) holds the state through the dead zone.
  • LST premium carve-outis_direction_sensitive now includes AssetClass::Lst. A premium (market > intrinsic) normalizes to PEGGED, same as yield-bearing stables. Why: for an LST the risk signal is the discount (redemption stress, cf. stETH −7% in 2022, ezETH depeg); a premium is demand pressure, not stress. Discount-side classification is unchanged.

Receipt schema: v1 (unchanged). Verdicts change for some valid inputs, hence the MINOR bump; replay stays deterministic via the recorded methodology_git_sha. See ADR-0021. v0.1.0 → deprecated (still valid for replay), superseded by 0.2.0.

v0.1.02026-05-29
  • Initial public release.
  • Extracted pure functions from pegana-engine v0.1.0; no behavior change.
  • Provides: computediscount, applyewmapure, transitiondecide, stateforbps_discount*, stateforcr, isplausiblediscountsample, canonicalassetshash, canonicalreceipthash, methodologyversion, methodologygitsha.
  • Receipt schema: v1.

What this is not.

Not SOC 2 complianceNot a regulatory auditNot financial advice

Pegana's audit log is a verifiable computation log: anyone can prove which methodology produced which alert, given which inputs. Use it to verify our claims; don't substitute it for your own judgment.