Chapters · Chapter 1

The Phone Book and the Moon

Part I — The Shape of Data · seven builds, seven receipts

The spirit of this chapter's exercises is to plant your own moon and watch the storage layer notice things — every build below produces a receipt that lines up against one I already shipped in this chapter (BLD-DAYONE-16, BLD-CH1-WORKED-KAPPA, BLD-CH1-INTEGRATE-DRIFT, BLD-COST-MEM, BLD-COST-INSERT, BLD-COST-COLD, BLD-TESTS-1373).

Run it live — GQL console

Point at the public read-only instance (no key needed) or your own engine (start it with GIGI_CORS_ORIGIN=* for browser access — dev only).

Try it here first — the curvature odometer

This is E1.1 running in your browser with the engine's exact math: Welford running stats + per-record \(\kappa = |v-\mu|/R\) with declared range \(R\). Plant the plain, drop the spike, watch the odometer notice. Then go reproduce it in Rust for the real receipt.

0
records
mean (Welford)
σ
κ at insert (prior stats)
κ of s151 now
κ of a typical reading (20.3)
0
flagged at 3σ

E1.1Reproduce the s151 receipt

Build

Stand up a stations bundle with one categorical base field and one numeric fiber field, insert 150 readings on the gentle plain \([20.0, 20.6]\), then insert s151 at \(500.0\), exactly as I did.

Receipt

Two harness lines that match BLD-CH1-WORKED-KAPPA within f64 tolerance: pre-spike \(\kappa = 0.000040\) on a typical reading with compute_anomalies(3 sigma) returning zero records, and post-spike \(\kappa = 4.7653\) on s151 with the typical reading's \(\kappa\) rising to \(0.031728\).

Bonus

Walk the sigma threshold from \(1.0\) to \(5.0\) in steps and plot flagged-count vs. threshold — the only knob this detector has, made legible.

E1.2Instrument the Welford six-liner

Build

Add a microbenchmark to tests/welford_correctness.rs (or a sibling file under benches/) that times the FieldStats::update else branch at src/bundle.rs:766--771 over \(10^6\) inserts on a single numeric fiber field.

Receipt

A printed ns/op number and a passing field_stats_welford_matches_offline alongside it — the incremental update still pins to the batch reference under the load you just put on it.

Bonus

Diff against a deliberately-broken naive two-pass mean/variance to confirm the numerical-stability win Welford was chosen for.

E1.3Replay the INTEGRATE drift

Build

Run the two GQL spellings from BLD-CH1-INTEGRATE-DRIFT verbatim against your bundle: first INTEGRATE temp OVER stations COVER ALL; (the README cell), then INTEGRATE stations MEASURE SUM(temp), AVG(temp); (what the parser at src/parser.rs:2047--2099 actually accepts).

Receipt

The first returns execution error: No bundle: temp; the second returns a Rows([...]) whose sum_temp ends in the lower-order f64 bits \(\ldots987\) given \(150\) readings near \(20.3\) plus one \(500.0\).

Bonus

Add a third spelling that supplies both OVER and MEASURE in a single statement; report whether the trailing-token discard Chapter 7 owns swallows your clause silently or errors.

E1.4Benchmark the \(1.5\times\) memory bill

Build

Load the same 150-row stations corpus into your favorite row-store (Postgres works) and into GIGI; measure resident-set size of each after the load settles.

Receipt

A ratio printed against BLD-COST-MEM. If your number lands within \(\pm 20\%\) of \(1.5\times\), you have reproduced the README's premium for keeping the curvature bookkeeping alongside the data (what the paper calls the second fundamental form).

Bonus

Scale to \(10^4\) and \(10^6\) rows and plot the ratio — the metadata is a fixed pile of accumulators per field, so the ratio should drift toward \(1.0\) as the row count dominates.

E1.5Time the cold start

Build

Kill the engine after E1.1's bundle is loaded, then reopen against the mmap snapshot written by src/storage/snapshot.rs. Run compute_anomalies(3 sigma) as the first call after reopen — no warmup, no batch job.

Receipt

Wall-clock from process start to the s151 row appearing in the anomaly list, in seconds, matched against BLD-COST-COLD. The brain endpoints must answer polymorphically against the reloaded bundle on the first request, not the tenth.

Bonus

Confirm by inspection of the snapshot file that the curvature estimator state is on disk — not re-derived from the records at warmup.

E1.6Stress the gauge transformation reading

Build

Extend E1.1's harness with a knob that injects \(k\) wild readings (\(500.0\)) at random base points and records the post-injection \(\kappa\) at one fixed typical record.

Receipt

A printed table of \(k\) vs. that fixed record's \(\kappa\), for \(k \in \{1, 2, 5, 10, 25\}\), demonstrating that \(\kappa\) at a fixed base point is a function of the global \(\mu_K, \sigma_K\) (the section-under-gauge-shift reading from the chapter). The \(k=1\) row should land on \(0.031728\).

Bonus

Plot the typical-record \(\kappa\) alongside the flagged count from compute_anomalies — the moment the wild readings start outvoting the plain, the detector's verdict flips, and the plot shows you where.

E1.7Wire a section verb that returns its own \(\kappa\)

Build

Issue SECTION stations AT station_id='s151'; against the live engine and capture the full response, including the per-result geometric annotation the day-one table promises on row two.

Receipt

A response payload that carries both the fiber values and the per-record \(\kappa\) and confidence — one round trip, no separate aggregation call, no log-scraping. Diff the \(\kappa\) in this response against the \(4.7653\) from E1.1's compute_anomalies output; they should be the same number to f64 precision, because they came from the same compute_record_k at src/bundle.rs:933--967.

Bonus

Issue the same SECTION against a typical station and confirm the \(\kappa\) matches the pre-spike \(0.000040\) — the address didn't grow, and the geometry rode along for free.

← All chaptersChapter 2 exercises →