# Money2046 — Agent & LLM Contract

Money2046 publishes **advertised vs settled** for machine payments: which wallets
can pay, where x402 services are listed, and what a payment actually cost —
fee, time, fail — with dispositions, evidence IDs, and replayable discovery
quotes. Card spend and remittance corridors are secondary subgraphs. Read this
file before consuming the feeds.

## Non-negotiables

1. **Never invent rates, fees, speeds, or availability.** Fail-closed:
   nothing renders as fact without verified, consent-gated evidence.
2. **Dispositions are the only truth.** Every wallet, facilitator, card, route,
   quote, and observation carries one. See the enum below.
3. **Never rank on SCHEMA_ONLY.** Ranking is only meaningful over VERIFIED_FRESH rows at the same accepted task amount.
4. **Pending evidence is invisible in public feeds** — except as a count in `meta`.
5. **INSUFFICIENT_EVIDENCE is a correct answer.** Prefer it over a plausible guess.
6. **Discovery quotes are not settlements.** A QUOTE row with `method: X402` may be
   `VERIFIED_FRESH` (the poll is real and fresh). That is not index-grade.
   Agent index = x402 SETTLEMENT outcomes. Read `observationKind` and `method`.
7. **Never rank on volume or user counts.** Volume boards are out of scope.
   No aggregate payment count renders anywhere unless it passes
   `docs/chain-addendum.md` (what may rank, which provenance enters, what
   still never does). Discovery `payTo` is a join key, not a census.
   The CHAIN surface is allowlisted (`disposition`, `reasons`,
   `attributionPrecision`, `epochIds`, `joinRule`, `asOf`, `epoch`) —
   `assertChainFlowPayload` fails the build on any other key, including
   `payToCount`, and on values outside the §4 enums (`attributionPrecision`
   ∈ four labels, `joinRule` === `epoch_overlap`, `disposition` ∈
   DISPOSITIONS, `epoch` required, `epoch.status` ∈ `none_ingested`
   \| `refused`). `UNJOINABLE` / `none_ingested` require empty
   `epochIds`; `VERIFIED_FRESH` requires non-empty `epochIds`. Other
   feeds apply a name-shaped tripwire (case-insensitive substring on keys
   such as volume, txns, paymentCount). That is a tripwire, not a
   semantic guarantee — abbreviations (`vol_usd`) and invented names
   (`nPayments`) escape.

## Evidence permalinks

Every published number is self-carrying. Verified observations have a
stable page at `/evidence/{id}/` — the human rendering of the matching
row in `/data/v1/observations.json` (lookup by `id`). Same object: same
disposition, provenance, observation kind, payload hash, and replay.
There is no second evidence endpoint. Route quotes keep `/receipts/{id}/`. Human pages mark
measurements with `data-evidence-id` on a resolvable `<a>`. An unlinked
number fails the build (`EVIDENCE LINK FAILED`). Zero marks also fail —
deleting the attribute cannot satisfy the gate. Each publishing surface
declares `data-evidence-surface`: `measurements` requires ≥1 mark on
that page; `hole-only` requires zero measured cells. Committed list:
`src/data/evidence-surfaces.json`. Evidence-page self-links cannot
satisfy `/observatory`. The gate prints marks checked across pages.
Listing-shape epoch counts cite `/epochs/#{epoch_id}` (named exemption:
not an observation or payment count; never activity/usage/adoption).
SCHEMA_ONLY estimates and HOLE cells must not carry the attribute.
On-chain readings are a different object. `/data/v1/onchain/<slug>.json`
cites `method_url` (`/onchain/<slug>/#method`) and `sources`. `status: OK`
is a reading with method, as-of, confidence, and limitations. It is not
`VERIFIED_FRESH`. Those pages are hole-only: no `data-evidence-id`. They
do not create a second evidence endpoint.
Disposition anchors: `/methodology/#dispositions`.

## Dispositions

Stable anchors (same ids as `/methodology/#dispositions`):
<a id="dispositions"></a>
<a id="disposition-schema-only"></a>
<a id="disposition-verified-fresh"></a>
<a id="disposition-stale-reverify"></a>
<a id="disposition-unavailable"></a>
<a id="disposition-insufficient-evidence"></a>

```json
["SCHEMA_ONLY","VERIFIED_FRESH","STALE_REVERIFY","UNAVAILABLE","INSUFFICIENT_EVIDENCE"]
```

| Enum | Meaning | Use |
|---|---|---|
| `SCHEMA_ONLY` | Schema/estimate values only, zero verified evidence | Label as estimate. Do not rank. |
| `VERIFIED_FRESH` | Verified within 30 days | Fact. Safe to rank and quote. |
| `STALE_REVERIFY` | Was verified, older than 30 days | Re-verify before reliance. |
| `UNAVAILABLE` | Not available / eligible in the stated `jurisdiction` | Refuse with reason + jurisdiction. |
| `INSUFFICIENT_EVIDENCE` | Cannot score — required fields or evidence missing | Return clean refusal. |

## Public delay

The free site and `/data/v1/agent-index.json` withhold SETTLEMENT values captured in the last 7 days. A withheld row is not a fee you can cite. QUOTE rows stay labeled QUOTE and do not enter the agent index. The paid evidence API is a separate surface. It stays locked until payment state is `paid`.

## Machine feeds (static, versioned, generated at build time)

| Feed | Contents |
|---|---|
| `/data/v1/catalog.json` | Cards, routes, providers, wallets/facilitator counts + dispositions |
| `/data/v1/wallets.json` | **Agent wallet catalog** — SCHEMA_ONLY capabilities |
| `/data/v1/agent-index.json` | **Agent payment outcomes** — x402 SETTLEMENT only, fail-closed. Public file withholds values captured in the last 7 days. |
| `/data/v1/chain-flow.json` | **CHAIN flow hole** — allowlisted keys only; no counts |
| `/data/v1/onchain/index.json` | **On-chain readings** — one ratio, risk, quality, or calendar per slug; no size board |
| `/data/v1/registry-epochs.json` | **Bazaar listing shape over time** — addresses/listings, not payments |
| `/data/v1/quotes.json` | **Verified** route quotes only + pending count |
| `/data/v1/card-evidence.json` | **Verified** card evidence only (legacy projection) |
| `/data/v1/watch.json` | **Approved** watch ledger only |
| `/data/v1/observations.json` | **Verified** observations only + `replay` on certified QUOTE rows |
| `/data/v1/card-index.json` | **Landed Card Spend Index** — measured FX only (secondary) |
| `/data/v1/index.json` | **Landed Cost Index (corridors)** — MYR subgraph, fail-closed |
| `/data/v1/score-examples.json` | Scoring examples + `score_agent_refusal` + illustrative shape |
| `/data/v1/openapi.json` | OpenAPI 3.1 description of feeds + disposition enum |

Base URL: `https://money2046.com` (staging: `PUBLIC_NOINDEX=1` — same paths, noindex).

## CHAIN addendum

On-chain joins to bazaar `payTo` are a different object from probe
settlements. Policy: `docs/chain-addendum.md`. Until eligible CHAIN rows
exist, the public answer is `INSUFFICIENT_EVIDENCE` on
`/data/v1/chain-flow.json` (allowlisted keys only). Local collector
output is not a census. Registry polls are versioned epochs; retired
addresses stay attributable. A listing-shape projection may ship
(`/data/v1/registry-epochs.json`, `/epochs/`) — address and listing
counts only. That does not publish a payment count. Batched settlement
(Circle Gateway / Nanopayments) is excluded from call-level counts.

## On-chain conditions

`/onchain/` and `/data/v1/onchain/index.json` (`money2046.onchain-index.v1`).
Each slug file is `money2046.onchain.v1`. An agent about to move money or
take a position reads one analysis. Publication order is not a size order.

| Slug | Why an agent reads it |
|---|---|
| `bsc-dex-volume-realism` | Is this venue's liquidity real enough to route through? |
| `aave-liquidation-cascades` | What a cascade does to a position and to the ability to execute. |
| `aerodrome-incentive-efficiency` | Is the depth real or rented? |
| `aerodrome-emission-mix` | Whether emissions rent the liquidity an agent would route through. |
| `arb-unlock-risk` | Dilution risk to its book. |
| `near-bridge-flow-composition` | How money moves between chains for settlement. |
| `near-stable-flow` | Whether a stable settlement and a volatile settlement are on the same side of the rail. |
| `zcash-shielded-adoption` | Counterparty and settlement privacy. |
| `zcash-shield-direction` | Whether privacy demand is shielding new value or spending it back out. |

`metric_kind` is `ratio`, `risk`, `quality`, or `calendar`. Missing inputs
publish `INSUFFICIENT_EVIDENCE` with a null value. `scripts/assert_onchain.mjs`
refuses banned key stems (volume, tvl, dominance, rank, leaderboard,
market cap, top-N, and the payment-count stems) on every subtree. Design:
`docs/onchain.md`. `stablecoin-carry-peg` is not in this index.

## Scoring contract

### score_wallet

Request: `walletId`.

Response: `disposition` (always `SCHEMA_ONLY` until probed) + `score` with
`x402Client`, `spendLimits`, `sessionCaps`, `networks` from public docs +
top-level `sourceUrl` citation. Never present as measured spend.

### score_agent (index)

Read `agent-index.json` for measured x402 fee / settle time. Every number
you quote carries its `evidenceIds` as
`https://money2046.com/evidence/{id}/`. Do not paraphrase a fee, settle
time, or task amount without that permalink. If the index is not
rankable, return `{ disposition, reasons }` from the feed — do not invent
an order.

Bazaar polls: filter `observations.json` where `method === "X402"` and
`observationKind === "QUOTE"`. Coverage lives on the `discovery` block — never
on `rate` / `fxRateApplied` (those are the $1 USDC task identity).

| Field | Meaning |
|---|---|
| `discovery.resourceCount` | Items on this poll page |
| `discovery.resourceCountCapped` | `true` → page cap (a floor, not a census) |
| `discovery.minFeeUsd` | Advertised min among **parseable** accepts, or `null` |
| `discovery.minFeeParseable` | `false` → do not treat missing min as zero or cheaper |
| `discovery.payTo` | Distinct bazaar pay-to addresses — join keys only |

Never rank facilitators on discovery `minFeeUsd`. Never mix bazaar polls into agent-index.

### score_card / score_route

Unchanged — card research model and corridor quotes. Card index and corridor
index are secondary subgraphs.

### QUOTE replay

Verified `QUOTE` rows from Wise carry a `replay` object with POST body.
Verified x402 discovery rows carry GET `replay` on the discovery URL.
Re-run independently. Quotes are labeled, never mixed into outcome indices.

### x402 facilitator outcomes

Published from verified `SETTLEMENT` rows with `method: X402` — fee, settle
time, failure rate. No volume chart. Not gated on card FX.

## Ingest path (propose evidence — agents cannot self-approve)

**x402 discovery:** `npm run observe:x402` via certified QUOTE adapter.
CI: `.github/workflows/observe-x402.yml`.

**x402 settlement:** `SETTLEMENT` capability on
`x402-settlement-payai` / `x402-settlement-cdp`. Runbook:
`docs/x402-probe.md`. Key path via `MONEY2046_PROBE_KEY_PATH` only.

**CHAIN collector:** `scripts/census/x402_flow.py` — local dataset only.
Does not publish. Gated by `docs/chain-addendum.md`.

**Wise quotes:** `npm run observe:wise` via certified adapter.

**Card spend captures:** `node scripts/card_spend_import.mjs --file <csv>` →
human `--verify <id>`. Protocol: `docs/card-capture-protocol.md`.

## Example answer shape

> "Which facilitator is cheapest for a $1 x402 task on Base?"
>
> → Read `agent-index.json`. If `ranking` is empty: return the index
> `disposition` and `reasons`. Do not rank.
> If a facilitator `value` exists: quote `feeUsd`, `settleTimeSeconds`,
> and `taskAmount`, and cite `https://money2046.com/evidence/{id}/` for
> each `evidenceIds` entry.
>
> Discovery resource counts are in `observations.json` QUOTE rows — cite
> those evidence URLs separately. Never mix them into the index.

## Full API reference

Mirrored on-site: **/agents/api/** — `docs/agent-api.md` and `docs/agent-skill.md` in the repo.
