Metadata-Version: 2.4
Name: quant-swarm
Version: 0.4.0
Summary: MCP servers extracted from the trading swarm: point-in-time data, pre-trade invariant + leakage audits, regime-fragility probes, and the Shadow Tournament bridge that scores your genome against the swarm's live champion.
Author: The 1.21 Initiative
License: MIT
Project-URL: Homepage, https://github.com/blink1217/trading-swarm-mcp
Keywords: mcp,trading,backtest-audit,point-in-time,regimes,tournament,evolution
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp>=2.0
Requires-Dist: httpx>=0.27
Requires-Dist: numpy>=1.26
Requires-Dist: pandas>=2.0
Requires-Dist: scipy>=1.11
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Provides-Extra: remote
Requires-Dist: uvicorn>=0.30; extra == "remote"
Requires-Dist: starlette>=0.37; extra == "remote"
Dynamic: license-file

# quant-swarm

Risk-first pre-trade checks that gate live capital — point-in-time data, invariant and leakage audits, regime probes — plus the **Shadow Tournament**: score your strategy genome against a live, self-evolving trading swarm's champion on identical market paths.

<!-- mcp-name: io.github.blink1217/quant-swarm -->

## Built by a Principal Quantitative Technologist

Authored by the Principal Quantitative Technologist at [The 1.21 Initiative](https://1.21initiative.com) — the same code path that gates live promotion and execution decisions in the trading swarm. Every tool exists because production trading systems fail in two repeatable ways: **lookahead leakage in research** and **an oversized position in production**. `quant-swarm` ships the checkers that prevent both, so you can audit your own work with the exact logic that guards deployed capital.

## Your backtest is static. The swarm is not.

Behind this package is a swarm that does not hand-tune strategies. A **champion** genome runs live; every cycle the swarm breeds **challengers** (tier-capped mutations), replays champion and challenger on the *identical* episode-seed matrix across five labelled market regimes (high-vol, drawdown, chop, melt-up, gap-heavy), and records the paired outcome in an **ELO ledger**. A surrogate prior pre-scores candidates so expensive replays are spent where they matter. Nothing is promoted on a single good backtest: promotion requires `MIN_EPISODES=20` paired episodes, a Wilcoxon-significant delta, a positive **worst-regime** margin (maximin, not mean), a **deflated-Sharpe** margin against the monotonic count of every trial ever attempted, and a **PBO** cap. This is the champion/challenger, self-play-style loop popularised by AlphaZero-style systems, applied honestly to markets — with the two things that do *not* transfer stated plainly: the market does not react to us, so there is no true self-play, and there is no learned dynamics model or tree search; selection is done by paired replay, ELO and statistical gates.

What that means for you: a local backtest tells you how a strategy did on one path. The Shadow Tournament tells you whether it beats an *evolving* champion on the same paths, in the regime that hurts it most, at a sample size that can actually have an opinion — and your result enters the swarm's ELO ledger. Opt in as a **contributor** and your genome becomes an external challenger in the swarm's next breeding cycle (at half price). That is the flywheel: every honest submission makes the champion harder to beat, and every user gets a harder benchmark.

## Why risk-first

Risk gates are not post-hoc reports — they are the pre-condition for every action. The package is organized around that constraint:

- **Fail-closed by default.** Unknown features map to tier C, missing provenance returns `UNSCORABLE` (never neutral-filled), and unverifiable tokens are refused on the hosted path. See `warden.audit_features` and `features.build` provenance guards.
- **Pinned, non-drifting invariants.** Order sizing floors (per-name 25%, gross 60%), fill model (spread + slippage + adverse selection, both legs, always against you), and hard-constraint checks are vendored at pinned commit SHAs (`.github/pins.json`, verified byte-for-byte by CI). A parity test pins the three copies of the floors (Python/MCP, C# live engine, Terraform) so they cannot drift.
- **Point-in-time provenance.** SQLite WAL cache at `%LOCALAPPDATA%\1.21-initiative\swarm-mcp\cache.db` (`$XDG_CACHE_HOME/1.21-initiative/swarm-mcp` on POSIX): finalized sessions are never re-fetched, in-progress sessions refresh at most every 60 s, earnings/news are append-only on `fetched_at`, and `features.build` runs the no-lookahead guard on every row (each feature must equal a fresh causal recomputation at `as_of`).
- **Pessimistic execution.** `warden.cost_check` and the simulator model the fill that hurts you; there is no optimistic fill path to inflate backtests.
- **No order-placement code path.** No tool can place, cancel, or route an order — this repository cannot trade, only refuse unsafe trades.
- **Statistically honest refusals.** Promotion verdicts are **never** issued locally. Statistically undecidable outputs return `INDETERMINATE_LOCAL`/`UNDERPOWERED`/`UNSCORABLE`, name the exact missing inputs (`MIN_EPISODES=20`, PBO, DSR, worst-regime margins), and hand off to the hosted Shadow Tournament (`tournament.submit`).

- Local-first, BYO-key: your Alpaca/Finnhub keys are read from env only when operating in BYOK mode; otherwise data flows through the hosted relay.
- Your symbols, bars, features and orders never leave your machine. The **only** thing that ever leaves is the genome parameter vector you explicitly pass to `tournament.submit` (public schema fields — no code, no symbols), and by default even that is deleted from the hosted side once scored.

**One-click install on [Smithery](https://smithery.ai/servers/blink-kt/quant-swarm):**
the listing is [`blink-kt/quant-swarm`](https://smithery.ai/servers/blink-kt/quant-swarm) (package and Smithery slug are both `quant-swarm`); the Smithery stdio launcher starts `swarm-data-mcp`, and the hosted streamable-HTTP endpoints below serve all three servers. Configuration is optional — without a token the servers still start and list every tool; the first call points you at the free signup. Add a token any time to unlock the relay-backed and hosted tools.

---

## The servers

| Server | Hook | Tools |
| --- | --- | --- |
| `swarm-data-mcp` | Derived-only market signals plus point-in-time feature building | `market.pulse`, `market.sentiment`, `market.regime`, `market.microstructure`, `volume.forecast`, `market.screen`, `market.rank`, `features.build`, `cache.warm`, `cache.stats`, `cache.offline` |
| `swarm-warden-mcp` | Pre-trade invariant + leakage gate — the live-capital floors and the point-in-time guards | `warden.validate_order`, `warden.audit_features`, `warden.cost_check`, `warden.validate_genome`, `warden.explain_sizing`, `warden.promotion_verdict` |
| `swarm-gym-mcp` | Regime fragility locally, then the **Shadow Tournament** against the swarm's live champion | `gym.label_regimes`, `gym.probe_fragility`, `gym.paired_preview`, `gym.estimate_cloud_run`, `tournament.submit`, `tournament.verdict`, `tournament.leaderboard` |

Raw bar/enrichment access (`get_bars` / `enrich_symbol`) is internal only and no longer
registered as tools — those paths echo raw provider values, and the data policy is
derived-only: ratios, percentile ranks, labels, buckets and counts. `market.pulse` and
`market.sentiment` are the general-purpose replacements; both accept an optional `bars`
argument so you can supply your own OHLCV rows for symbols we don'"'"'t carry.

### The Shadow Tournament

`gym.paired_preview` is honest about being underpowered: at most 8 seeds × 2 per regime on
your cached window, every statistic labelled `UNDERPOWERED`, never a verdict. `tournament.submit`
is how a genome leaves that ceiling:

1. **Validate locally** — `warden.validate_genome` returns the `genome_hash`; nothing is sent.
2. **Submit** — `tournament.submit(genome, contribute=false|true)`. The site charges credits
   (200, or 100 with `contribute=true`) and dispatches the job to the hosted runner.
3. **Hosted replay on identical paths** — the runner replays *your genome and the swarm's
   current champion* over the same 5 regimes × 4 per regime × 5 seeds = **100 paired episodes**
   on the hosted `bars_1day` panel (above `MIN_EPISODES=20`), computes the Wilcoxon paired
   p-value, bootstrap CI, per-regime deltas and the **worst-regime margin**, counts hard-constraint
   and lookahead violations, and classifies the outcome: `CHALLENGER_BEATS_CHAMPION`,
   `CHALLENGER_LOSES`, or `INCONCLUSIVE`.
4. **ELO** — the outcome updates your genome's rating against the champion (K=16, start 1500) and
   the champion's rating against the field. `tournament.leaderboard` (free) shows the anonymised
   board: 12-char hash prefixes only.
5. **Poll** — `tournament.verdict(job_id)`; no charge to poll. Runs take about two minutes.

The outcome is a *tournament result*, not a promotion. The promotion gate — deflated-Sharpe
margin, PBO cap, the monotonic trials ledger — runs inside the swarm's private registry on
genomes that qualify. That boundary is deliberate (see **The IP boundary** below).

**What is sent:** the genome parameter vector, its hash, and the `contribute` flag. Never symbols,
bars, features, orders, or code. **Retention:** with `contribute=false` the vector is deleted from
the job record once scored — hash and outcome remain. With `contribute=true` you license the vector
and outcome to the swarm's evolution loop, where it is registered as an external challenger
(`origin=external_contribution`) and put through the same tier-capped tournament and promotion gates
as the swarm's own mutants. That is why contributors pay half: your genome is the swarm's proposer
diversity, and every accepted contribution makes the next champion harder to beat — for everyone.

## Plans and the credit rate card

Access is tokened through [https://1.21initiative.com/mcp/](https://1.21initiative.com/mcp/).
**One credit is the unit for everything that costs us money** — a relay data call, one simulated
episode of hosted compute, or a tournament run — so a pack buys a bounded amount of *all* of it and
we never run hosted compute at a loss.

| What | Credits | Notes |
| --- | --- | --- |
| Relay data call (`/data/bars`, `/data/enrich`) | 1 | any symbol count within your plan cap counts as one call |
| Hosted single-shot Pro tool (`features.build`, `warden.promotion_verdict`, `gym.label_regimes`, `gym.estimate_cloud_run`) | 1 | charged only on the hosted endpoint |
| Hosted gym episode (`gym.probe_fragility`, `gym.paired_preview`) | 1 per episode | 5 regimes × per_regime × seeds (× 2 genomes for the paired preview); `gym.estimate_cloud_run` prices any geometry before you run it |
| Shadow Tournament (`tournament.submit`) | **200** — **100** with `contribute=true` | fixed price for the full 100-paired-episode geometry vs the champion |
| `tournament.verdict`, `tournament.leaderboard`, all warden checkers, `cache.*`, local stdio runs of any tool | 0 | local execution is never metered — your CPU, your electricity |

- **Free** (instant token at signup): all warden checkers, the derived snapshots
  `market.pulse` / `market.sentiment` / `market.regime` (10 symbols/call, 250 relay calls/month,
  365-day backfill), `cache.stats`, `cache.offline`, and `tournament.leaderboard`. No hosted compute,
  no GCP spend on your behalf beyond the relay allowance.
- **Pro** — one-time credit packs, self-serve: **10,000 credits for £19** or **100,000 for £149**,
  valid 90 days, no subscription, no unlimited plan. Unlocks `features.build`, `cache.warm`, the Pro
  derived tools (`market.microstructure`, `volume.forecast`, `market.screen`, `market.rank`; 50
  symbols/call, full backfill), all gym tools, `warden.promotion_verdict`, and `tournament.submit` /
  `tournament.verdict`. A Starter pack is 50 tournaments — 100 as a contributor.
- **Institutional** (custom-quoted): Strategy Validation Audit engagements, custom universes,
  hosted league runs, SLA.

A Pro token whose pool is empty or past its 90-day window verifies with `status: exhausted` /
`expired` and the **free** feature set — Pro tools refuse until you buy again. Plan limits are
enforced server-side (the relay, `/api/mcp/meter`, `/api/mcp/verify`, and the hosted
streamable-HTTP endpoint return structured `402` refusals with an `upgrade_url`). This open-source
client'"'"'s plan check is **advisory**: a free token calling a Pro tool gets an `UPGRADE_REQUIRED`
envelope — the tool still lists, and the attempt points at the upgrade page. No DRM; the free plan
is deliberately the zero-cost surface.

### Point-in-time data, for real

LLM-driven research re-runs cells constantly; each re-run burns Finnhub (60 req/min) and
Alpaca (200 req/min) budgets re-pulling identical history — and then silently builds
features from data that did not exist at decision time. `swarm-data-mcp` fixes both:

- SQLite (WAL) cache at `%LOCALAPPDATA%\1.21-initiative\swarm-mcp\cache.db`
  (`$XDG_CACHE_HOME/1.21-initiative/swarm-mcp` on POSIX).
- **Finalized sessions are never re-fetched** — zero-cost replays forever. The
  in-progress session refreshes at most every 60 s; enrichment every 300 s.
- Earnings/news are append-only on `fetched_at`: a later fetch can never rewrite an
  earlier `as_of`.
- Per-provider token buckets + `429` exponential backoff (`1s\u00b72\u207f`).
- `features.build` runs the no-lookahead guard on every row (each feature must equal a
  fresh causal recomputation at `as_of`) and the provenance guards on every field.
  Tier-B/C fields without recorded point-in-time evidence come back `UNSCORABLE` —
  never neutral-filled with `0.0`.

Every response carries `coverage` (cache vs API, oldest/newest session per symbol) and
`limits` (your local depth in weeks vs the tape-depth gates: 8 weeks for the tier-A
fast path, 26 weeks for tape eligibility). Below the gates you get an `escalation`
block naming the hosted `bars_1day` panel that satisfies them. Tape-tier replay is
**roadmap, not available** — we will not imply otherwise.

### The warden

`warden.validate_order` is the same function that rejects live orders: per-name 25% of equity,
gross cap 60%. Per-fund overrides are allowed, but the response always reports your
deviation from the house floors. `warden.audit_features` flags banned actuals sources
(`open-meteo.archive` and friends return *actuals*, not what the forecast said on a past
Friday), features predating tape start, and unknown features fail closed to tier C.
`warden.cost_check` converts a claimed gross edge into net-of-cost reality under the pessimistic
fill model (spread + slippage + adverse selection, both legs, always against you).
`warden.explain_sizing` is a step-by-step mirror of the C# live risk engine, and a parity test
pins the floors against terraform and guardrails so the three copies cannot drift.

### The gym

`gym.probe_fragility` replays your genome over the deterministic tier-A simulator and reports
per-regime net bps, the worst regime, turnover, and hard-constraint violations — never a
promotion. Seeds are capped at 8 and `per_regime` at 2: **statistical honesty, not
artificial scarcity**. Tier-B/C mutations against a champion raise the gym'"'"'s
`TierScoringRefusal` (UNSCORABLE) instead of silently neutral-filling features the price
panel cannot provide. `gym.paired_preview` compares champion vs challenger on identical
market paths with the promotion gate bypassed and every statistic labelled
**UNDERPOWERED**, naming the exact seed count needed to clear `MIN_EPISODES=20` — and every
undecidable result ends with a `cloud_job` block that is literally the `tournament.submit` call
that resolves it.

---

## Install

Requires Python \u2265 3.11. One kind of credential:

- **Access token (all three servers, required).** Every tool call is gated on a token
  issued by [https://1.21initiative.com/](https://1.21initiative.com/) — request access
  there (that'"'"'s also the Strategy Validation Audit booking flow), then set
  `SWARM_MCP_ACCESS_TOKEN` in the server'"'"'s `env`. Clients still list the tools without a
  token; every call returns an `ACCESS_REQUIRED` envelope pointing back to the site.
  The token is verified against the site, and that verification is the usage meter —
  only the token itself is ever sent, never symbols, genomes, prices, or provider keys.

The same token also feeds the **hosted data relay**: `swarm-data-mcp` serves bars and
enrichment through `https://1.21initiative.com/api/mcp/...`, so **no Alpaca or Finnhub
credentials are required** — the site holds the provider keys behind the relay and caches
historical bars in GCS. The relay is fail-closed: a rejected or unverifiable token means a
refused data fetch, never partial rows. The point-in-time cache semantics on the client
side are unchanged — finalized sessions are immutable in local SQLite regardless of which
data path filled them.

### Smithery

Install [`blink-kt/quant-swarm`](https://smithery.ai/servers/blink-kt/quant-swarm) from
Smithery — one listing, one token, all three servers. Smithery forwards `apiToken` as the
`SWARM_MCP_ACCESS_TOKEN` env var (stdio) or as `?apiToken=` on the hosted endpoints; the
token is optional at connect time.

### Cursor

`Settings \u2192 MCP \u2192 Add server` (or `.cursor/mcp.json` — a checked-in example lives at
[.cursor/mcp.json](.cursor/mcp.json)):

```json
{
  "mcpServers": {
    "swarm-data": {
      "command": "uvx",
      "args": ["--from", "quant-swarm", "swarm-data-mcp"],
      "env": {
        "SWARM_MCP_ACCESS_TOKEN": "<token from https://1.21initiative.com/>"
      }
    },
    "swarm-warden": {
      "command": "uvx",
      "args": ["--from", "quant-swarm", "swarm-warden-mcp"],
      "env": { "SWARM_MCP_ACCESS_TOKEN": "<token from https://1.21initiative.com/>" }
    },
    "swarm-gym": {
      "command": "uvx",
      "args": ["--from", "quant-swarm", "swarm-gym-mcp"],
      "env": { "SWARM_MCP_ACCESS_TOKEN": "<token from https://1.21initiative.com/>" }
    }
  }
}
```

Prefer a deeplink? `scripts/make_deeplinks.py` prints `cursor://\u2026/mcp/install` links for
all three servers (base64 of the stdio config, so they cannot drift from the JSON above);
the generated list is checked in at [.cursor/DEEPLINKS.md](.cursor/DEEPLINKS.md).

### Claude Desktop

`claude_desktop_config.json` \u2014 identical `mcpServers` block as above.

### Claude Code

```bash
claude mcp add swarm-data   --env SWARM_MCP_ACCESS_TOKEN=<token> -- uvx --from quant-swarm swarm-data-mcp
claude mcp add swarm-warden --env SWARM_MCP_ACCESS_TOKEN=<token> -- uvx --from quant-swarm swarm-warden-mcp
claude mcp add swarm-gym    --env SWARM_MCP_ACCESS_TOKEN=<token> -- uvx --from quant-swarm swarm-gym-mcp
```

### Windsurf

`~/.codeium/windsurf/mcp_config.json` \u2014 the same stdio JSON shape as the Cursor block
above. For the hosted endpoints use the `serverUrl` form instead:

```json
{
  "mcpServers": {
    "swarm-data-remote": {
      "serverUrl": "https://swarm-mcp-503318750546.europe-west1.run.app/mcp/data"
    }
  }
}
```

(The hosted endpoints accept the token as `Authorization: Bearer <token>` or as
`?apiToken=<token>`.)

The warden and gym are pure checkers and the data server fetches through the hosted
relay, so **no server needs provider keys** \u2014 only the access token.

**Local development:** operators of this repo can bootstrap offline by setting
`SWARM_MCP_LOCAL_TOKEN` to the same value as `SWARM_MCP_ACCESS_TOKEN` (documented
bypass; token verification against the site is skipped and the token gets the full
Pro entitlement \u2014 it is a local override on your own machine).

**Swarm operators (internal):** to fetch directly from the providers instead of the
relay, set `SWARM_MCP_BYOK=1` plus `ALPACA_API_KEY`/`ALPACA_SECRET`/`FINNHUB_API_KEY`
on `swarm-data-mcp`. Public users should leave `SWARM_MCP_BYOK` unset.

**Hosting the remote endpoint yourself:** `swarm-mcp-http` validates the `Host` header
(DNS-rebinding protection). The defaults allow `1.21initiative.com`, the project'"'"'s Cloud
Run hostname, the Smithery gateway, and localhost; `SWARM_MCP_ALLOWED_HOSTS`
(comma-separated) **extends** the defaults — it never replaces them, so a custom domain
cannot accidentally lock out the Cloud Run URL. `SWARM_MCP_REMOTE_URL` overrides the
advertised endpoint base, and `SWARM_MCP_TOKEN_VERIFY_URL` overrides the verify endpoint.
See the Dockerfile for the container form.

The hosted endpoint meters compute (`swarm_mcp/metering.py`): before a Pro compute tool runs it
charges `POST {SWARM_MCP_RELAY_URL}/meter` with the caller'"'"'s token, and refuses (JSON-RPC `-32003`,
HTTP 402/429/503) when the meter refuses or is unreachable — hosted compute is never served
unmetered. The Shadow Tournament runner lives in the same service: the site dispatches jobs to
`POST /internal/tournament/run` guarded by the shared secret `SWARM_MCP_INTERNAL_KEY`, the runner
fills its panel through the relay with `SWARM_MCP_SERVICE_TOKEN` (an institutional token, so
users are never billed for the runner'"'"'s own data), scores against `SWARM_MCP_CHAMPION_GENOME`
(path to the registry'"'"'s current champion; the packaged `swarm_mcp/data/champion_genome.json` is the
fallback), and calls back `POST {relay}/tournament/complete`. `SWARM_MCP_TOURNAMENT_UNIVERSE` and
`SWARM_MCP_TOURNAMENT_LOOKBACK_DAYS` shape the hosted panel. The runner scores in a background task
after answering `202`, so the Cloud Run service must run with **CPU always allocated**
(`--no-cpu-throttling`) and a request timeout of at least 300 s; with request-based CPU the task
starves after the response and the job is refunded as failed.

---

## The IP boundary (what ships, what doesn'"'"'t)

This repository ships **checkers only**: order checks, provenance guards, the
pessimistic fill model, the genome schema, provenance tiers, hard-constraint checking,
gate thresholds, the tier-A gym simulator, and the regime labeller \u2014 vendored at pinned
commit SHAs (`.github/pins.json`, verified by CI).

The **selection machinery stays server-side** and is not in this repo: objective scoring,
deflated-Sharpe estimation, and the promotion-gate decision. Any request for a promotion
verdict returns `INDETERMINATE_LOCAL` with the exact missing statistical inputs
(`MIN_EPISODES=20`, PBO ≤ 0.30 via combinatorially-symmetric splits, DSR margin with the
monotonic trials ledger, worst-regime margin across all 5 regimes × seeds), plus:

- an `audit_request` block — genome hash + violation summary, **no proprietary payload**;
- a `cloud_job` spec that is the `tournament.submit` call which resolves it.

The Shadow Tournament runner in this repo computes **paired statistics and an outcome** on
identical paths; it does not contain, and a CI test (`tests/test_ip_boundary.py`) forbids, the
objective, the DSR estimator, or the promotion decision. Contributed genomes that beat the
champion are handed to the swarm'"'"'s private registry, where those gates run. The **Strategy
Validation Audit** at [https://1.21initiative.com/](https://1.21initiative.com/) remains the
route for multi-genome league runs, custom universes, and NDA'"'"'d live metrics.

## Telemetry

Off by default, opt-in only (`SWARM_MCP_TELEMETRY_OPT_IN=opt-in`), counters only
(tool name, success flag, coarse duration). Never symbols, genomes, prices, or
credentials. Institutional buyers read the source; silent phone-home destroys the wedge.

The exceptions are by contract and explicit:

- **Access-token verification.** When a token is set and no local bootstrap token matches,
  the token is POSTed to the verify endpoint (default `https://1.21initiative.com/api/mcp/verify`,
  override `SWARM_MCP_TOKEN_VERIFY_URL`), at most once per 5 minutes per process. Only the token
  is sent; the gate fails closed if the endpoint is unreachable or rejects the token.
- **Relay data calls** carry the token plus the symbols/days you asked for (that is the request).
  Relay calls are metered server-side per call.
- **`tournament.submit`** sends the genome vector, its hash and the `contribute` flag — the one
  tool that ships a strategy artefact, and it says so in its output every time.

## Development

```powershell
pip install -e ".[test]"
py -3.11 -m pytest                          # 160 tests
scripts\vendor.ps1                          # re-vendor the pinned checker subset
py -3.11 scripts\check_pin.py               # vendored tree == pins.json
```

Vendoring uses the sibling checkouts of the private repos at the pinned SHAs
(`-FromWorktree` bootstraps before the pin commit exists). CI mirrors the swarm'"'"'s own
`guardrails-invariants` gate: it checks out the pinned SHAs and verifies the committed
vendored tree byte-for-byte (and the stripped subsets transform-for-transform), then runs
the guardrails'"'"' own invariant suite at the pinned SHA.

## License

Wrapper code: MIT (see `LICENSE`). The vendored guardrails checker subset under
`swarm_mcp/vendored/guardrails/` is distributed under the source-available terms in
`swarm_mcp/vendored/guardrails/LICENSE.md`. The excluded selection machinery is not
licensed.

---

*The gym is the tier-A price subset. The tape_replay service does not exist publicly.
Tier-B/C scoring is hosted-only. The Shadow Tournament returns paired outcomes, never
promotions. Anything else would be fabricated evidence — and this repo refuses to fabricate.*
