# Data dictionary — `dataset.csv`

Companion to `dataset.csv`. Every column, its type, its source, and its
null semantics.

## Row identity

One row per `(chain, stage_id)` pair. Rows are ordered: the stages flow
Registered → Delivered after payment, so an agent counted at stage 7 is
also counted at stages 1-6 by construction. Two chains × ten stages = 20
rows.

## Columns

| # | Column | Type | Source | Null semantics |
|---:|---|---|---|---|
| 1 | `as_of_date` | ISO date (YYYY-MM-DD) | snapshot label | Always populated. The UTC date the snapshot was taken. |
| 2 | `chain` | string | assigned | `base` (chain_id 8453) or `ethereum` (chain_id 1). Always populated. |
| 3 | `stage_id` | string | assigned | One of `s1_registered`, `s2_advertises_payment`, `s3_endpoint_answers`, `s4_valid_402_challenge`, `s5_includes_payto`, `s6_parseable_price`, `s7_price_normal_range`, `s8_payable_no_auth`, `s9_settled_onchain`, `s10_delivered`. Always populated. |
| 4 | `stage_label` | string | assigned | Human-readable label for the stage. Always populated. |
| 5 | `agents` | integer | computed | Count of distinct ERC-8004 agents at this stage on this chain. Always populated (may be `0`). |
| 6 | `operators` | integer | computed | Count of distinct `payTo` addresses (lowercased) at this stage. Lower bound on operator count. Always populated. |
| 7 | `observed` | boolean (`True`/`False`) | assigned | `False` for stages 1-7 (deterministic from today's profile store). `True` for stages 8-10 (observed from pilot evidence). |
| 8 | `sample_denominator` | integer or empty | assigned | For observed stages (8-10), the number of distinct agents from today's stage-7 pool that the pilots attempted. Empty for deterministic stages. |
| 9 | `pct_of_registered` | float (0.0-100.0) | computed | `100.0 * agents / stage-1 agents on this chain`, rounded to two decimals. |

## Notes

- The `observed` column is NOT a quality grade. Stages 1-7 are *deterministic* in
  the strict sense that two readers of the same profile-store blob will compute
  the same counts; stages 8-10 are *observed* in the sense that they come from
  running test purchases and watching what happens. The former is cheaper to
  refresh (daily, no cost); the latter costs real USDC each time, so it only
  advances when we run a new pilot. Both are legitimate measurements.
- `operators` can be larger than `agents` only if an agent is observed with
  multiple payTos in the same cluster — this does not happen with our current
  counting rule (one agent → one primary payTo lookup).
- The `snapshot.json` companion carries additional detail (drop-off reason
  histograms, the price distribution, the list of delivered agents with their
  tx hashes). The flat CSV is intentionally the aggregates-only version.
