DashboardThree-Axis ProbesCrypto Shared Data Poolmanifest.json — schema & usage

finding · findings/evolution/shared_data/manifest.md

manifest.json — the catalogue card for every slice of crypto data

A manifest is just a master list — like the index card catalogue in a library that tells you what books exist, where each one sits on the shelf, and whether it's in good condition. This page documents manifest.json: the master list of every chunk of crypto market data the research used to pull together, what each entry means, and the rules that kept that list trustworthy.

In plain English. Imagine a warehouse full of boxes of market data. The manifest is the clipboard at the door that lists every box: what's inside, where it lives, how big it is, and a tamper-proof seal number so you can prove the box wasn't swapped. Researchers (and their scripts) read the clipboard instead of digging through the warehouse — so they can instantly find exactly the data they need and be confident nothing was quietly changed underneath them.
⚠️ Legacy notice (2026-05-30). This describes a system that was removed. The old approach copied data into files called parquet (a compact spreadsheet-on-disk format) and listed them here. That copy-to-file step and its fetcher (fetch_multi_slice.py) no longer exist — the active probe (orthogonality_probe.py) now reads each data cell live from the database and writes its results elsewhere. The manifest was never actually populated. The schema below is kept for reference and possible future revival. Crypto-only since version 2.

What is this?

Why it matters

Two separate quality checks — one that evaluates measurement metrics, one that evaluates candidate features — both needed to look things up programmatically (i.e., with code, not by hand). Specifically, they needed to discover:

SSoT means single source of truth — one authoritative place everyone trusts instead of scattered, conflicting copies. The manifest was designed to be the SSoT for all of the above.

The shape of the file (top level)

At the very top, the manifest carries a few bookkeeping facts about the whole catalogue, then two big lists: cells (the data chunks) and fetch_runs (a log of each time the catalogue was built or refreshed).

{
  "schema_version": 1,                      // bump when this schema changes
  "pre_spec_version": 1,                    // which pre-spec.md version produced this
  "pre_spec_file": "pre-spec.md",
  "generated_at": "2026-05-23T14:32:00Z",   // ISO timestamp of last fetch
  "host": "bigblack",                       // host that ran the fetcher
  "data_root_on_bigblack": "/home/nasimubd/shared_data/",
  "cells": [ ... ],                          // per-cell records (see below)
  "fetch_runs": [ ... ]                      // per-run log entries (see below)
}

A schema is just the agreed-upon shape/layout of the data — which fields exist and what type each is. schema_version is a number bumped whenever that layout changes, so old readers can tell they're looking at a newer format.

One entry per data chunk (the per-cell record)

Each cell in the cells list looks like this — a complete catalogue card for one slice of data:

{
  "cell_id": "crypto_BTCUSDT_100dbps_slice01",
  "substrate": "crypto",
  "symbol": "BTCUSDT",
  "threshold_dbps": 100,
  "slice_id": "slice01",
  "slice_start_iso": "2026-01-01T00:00:00Z",
  "slice_end_iso": "2026-02-28T23:59:59.999999Z",
  "applicable": true,
  "applicable_reason": "in range; effective_start satisfied",
  "bar_count": 84321,
  "non_null_frac_per_col": {
    "ofi": 1.0,
    "vwap": 1.0,
    "kyle_lambda_proxy": 1.0,
    "lookback_hurst": 0.7234,
    ...
  },
  "fetch_timestamp_ingestion": "2026-05-23T14:32:18Z",
  "parquet_path": "/home/nasimubd/shared_data/crypto/BTCUSDT_100dbps_slice01.parquet",
  "file_size_bytes": 4521734,
  "sha256": "abc123def456..."
}

The schema / fields, explained

FieldTypeWhat it means (plain words)
cell_idstringThe unique name of this chunk, built by gluing the coordinates together: <substrate>_<symbol>_<threshold>dbps_<slice_id>. A slug like this is a short, machine-friendly label. No two cells share one.
substrate"crypto" or "forex"Which market the data came from — i.e., which database table backed the fetch. (Today it's crypto-only.)
symbolstringThe trading pair, e.g. "BTCUSDT" (Bitcoin vs. a dollar-pegged coin) or "EURUSD" (euro vs. US dollar).
threshold_dbpsintThe sensitivity setting for forming a "bar," e.g. 100. (dbps = decimal basis points; 100 dbps = 0.1%. Smaller = more, finer bars.)
slice_idstringWhich time window, "slice01" through "slice24" — the data is cut into fixed calendar chunks.
slice_start_iso, slice_end_isostring (ISO UTC)The exact start and end of that calendar window, in a standard timestamp format. These mirror the locked plan in pre-spec.md.
applicableboolTrue/false: was data actually fetched for this cell? (False when the slice doesn't make sense for this symbol.)
applicable_reasonstringIf not applicable, the reason — e.g. "symbol effective_start 2023-05-03 > slice_start 2020-04-01" (the coin didn't exist yet in that window).
bar_countint (or null)How many rows of data the chunk holds. null when the cell isn't applicable.
non_null_frac_per_coldictA per-column "how-full-is-it" score: the fraction of rows that actually have a value (1.0 = completely filled, 0.72 = about a quarter missing). A quick data-quality read per column.
fetch_timestamp_ingestionstring (ISO UTC)The moment the fetcher pulled this particular cell.
parquet_pathstringThe full file location on the bigblack server where the data file lives.
file_size_bytesintHow big the file is on disk, in bytes.
sha256string (hex)A SHA-256 fingerprint — a long code computed from the file's exact contents. If even one byte changes, the code changes, so it acts as a tamper-proof seal for reproducibility.

A log of each build run (the per-fetch-run record)

Besides the data chunks, the manifest keeps a diary: one entry every time the fetcher ran, recording how it went.

{
  "run_id": "20260523T143200Z",
  "host": "bigblack",
  "started_at": "2026-05-23T14:32:00Z",
  "completed_at": "2026-05-23T14:50:18Z",
  "pre_spec_version": 1,
  "cells_attempted": 552,
  "cells_fetched": 550,
  "cells_skipped_already_fetched": 0,
  "cells_skipped_not_applicable": 2,
  "cells_failed": 0,
  "cpu_env": {
    "OPENBLAS_NUM_THREADS": "1",
    "OMP_NUM_THREADS": "1",
    "MKL_NUM_THREADS": "1",
    "NUMEXPR_NUM_THREADS": "1"
  },
  "loadavg_at_start": [6.81, 6.90, 7.27],
  "nproc": 32
}
Not-yet-built fields. The fields above are exactly what the old fetcher wrote. Richer ones were considered — duration_sec, pre_spec_hash_sha256, click_house_reads_total_bytes — but were never implemented. They were filed as "CONCEDE-FOLLOW-UP" items from the PR #501 review (i.e., acknowledged gaps to fix later, before any real run).

How it's used

The point of a machine-readable catalogue is that a few lines of code can answer real questions instantly. Examples from the doc:

Python — list every cell for one symbol

import json
from pathlib import Path

manifest = json.loads(Path("findings/evolution/shared_data/manifest.json").read_text())
btc_cells = [c for c in manifest["cells"] if c["symbol"] == "BTCUSDT"]
print(f"BTCUSDT cells: {len(btc_cells)}")

Python — find every applicable cell for one check

btc_100dbps = [c for c in manifest["cells"]
               if c["substrate"] == "crypto"
               and c["symbol"] == "BTCUSDT"
               and c["threshold_dbps"] == 100
               and c["applicable"]]
parquet_paths = [c["parquet_path"] for c in btc_100dbps]
# Audit-side spike reads each path; the 24 slices give it K=24 per-pair values

Bash — quick counts with jq

jq is a small command-line tool for slicing JSON from the terminal.

# Total cells
jq '.cells | length' findings/evolution/shared_data/manifest.json

# By substrate
jq '.cells | group_by(.substrate) | map({substrate: .[0].substrate, count: length})' \
   findings/evolution/shared_data/manifest.json

# List non-applicable cells with reasons
jq '.cells[] | select(.applicable == false) | {cell_id, applicable_reason}' \
   findings/evolution/shared_data/manifest.json

The rules that kept the catalogue trustworthy

The manifest was designed with built-in guarantees — and the doc is honest about exactly how far each one goes:

Property (the promise)How it's enforced — and the caveat
Every cell has a unique address (cell_id)Built deterministically from the coordinates. Caveat: if a duplicate ID is written, the new one silently overwrites the old — there is no collision error yet.
Time windows come from one placeStart/end dates are copied from the fetcher's hard-coded SLICES list. Caveat: there's no automatic check that those match pre-spec.md, so drift between the two wouldn't be caught at write time. (Filed as a follow-up.)
The fingerprint matches the fileThe sha256 is computed and stored at write time, so re-runs can detect a file changed in place. Caveat: it does not guarantee bit-for-bit identity across machines, because the compression can differ across software versions.
Not-applicable cells stay emptyWhen applicable: false, the path and row count are forced to null. No phantom files.
Re-running doesn't create duplicatesWrites are idempotent (safe to repeat) — keyed by cell_id, already-fetched cells with a valid fingerprint are skipped.
These were accurate as of pre-spec v1. Stricter rules — a hard error on duplicate IDs, and a write-time cross-check of timestamps against pre-spec.md — were tracked as follow-up items to add before the first real run.

When the manifest changes

TriggerEffect
Run the fetcher for the first timeEvery applicable cell gets fetched; the list grows to ~552 entries.
Re-run the fetcher laterAlready-fetched cells are skipped; a cell is only refreshed if its file went missing or its fingerprint no longer matches.
Upgrade to pre-spec v2New cells are added; old cells are kept and tagged pre_spec_version: 1, new ones tagged 2.
Someone deletes a data file by handThe next run notices the missing file and re-fetches it.
Hand-editing manifest.jsonDon't. The manifest is fetcher-owned. To change scope, edit pre-spec.md instead.

Where to look next

Bottom line. manifest.json was the trustworthy "table of contents" for the shared crypto data — a unique address, quality score, location, and tamper-proof seal for every slice — but it's now legacy: the project moved to reading data live, so this schema is kept on the shelf for reference, not in active use.