Changes to SPEC.md’s locked decisions and fills for gaps in it. SPEC §0 holds D1–D6. Each entry gives the date, the decision, the reason and the SPEC sections it touches. Newest last.
Format:
## Dn · Short title
Date · SPEC §x · Lanes affected
Decision. Reason.
agg_week_cbd carries the source-file month23 Oct 2026 · SPEC §5 · L01, L07, L10
The grain of agg_week_cbd becomes month × iso_year × iso_week × mode × cbd_group (plus zone_list, see D9). month is the first day of the source file’s month. Metrics sum over month to get whole weeks.
Reason: ISO weeks straddle month boundaries, so aggregate.py MONTH= can’t delete and rewrite “that month’s rows” in a table keyed only by week.
23 Oct 2026 · SPEC §5, §7.2, §8 · L01, L07, L08
Add to SPEC §5:
| Table | Grain | Columns |
|---|---|---|
agg_cbd_pairs |
month × mode × pu_zone × do_zone (months from 2025-01) | trips_all, trips_cbd_fee (cbd_fee > 0) |
agg_fee_values |
month × mode × cbd_fee | trips |
The CBD-list check (SPEC §7.2) and the fee check (SPEC §8) read these tables.
Reason: both checks need trip-level detail, but the refresh job restores only aggregates and raw and clean files for past months are gone.
23 Oct 2026 · SPEC §4.1, §5, §7 · L04, L06, L07, L10
config/cbd_zones.csv has columns LocationID, zone, borderline, note. The core list excludes borderline zones; the wide list includes them. agg_week_cbd gains zone_list ∈ {core, wide}, with cbd_group computed under each list. Clean computes the CBD flags for both lists. Other uses of cbd_touch use core unless stated.
Reason: SPEC §7.3 asks for results with and without borderline zones, and cbd_group is fixed when the aggregate is built.
23 Oct 2026 · SPEC §5, §9.3 · L01, L07, L09, L16
agg_zone_month_dist gains one row per month × mode with pu_zone = 0, holding city-wide percentiles over all valid trips (same n ≥ 100 rule). Company and prices tiles read “median fare per mile” from it. The airport “fare to Manhattan” tile shows the mean fare per trip (ratio of sums from agg_airport / agg_od_month) and is labelled as a mean.
Reason: percentiles can’t be combined across zones, and agg_airport stores sums only.
23 Oct 2026 · SPEC §2, §4 · L03
discover.py may load DuckDB httpfs and read only each remote file’s Parquet footer (DESCRIBE / parquet_schema) instead of downloading files. Every other step still works on downloaded files.
Reason: discovery covers 96 files (about 17 GB) in Phase 1, before the pipeline exists; downloading them all would repeat the back-fill. Replaces SPEC §2’s “httpfs not needed” for this one script.
23 Oct 2026 · SPEC §6 · L10
The year-over-year difference-in-differences uses ISO weeks 2025-W02 onward. In the pay-rise event study, 2025-W31 (28 Jul – 3 Aug) is drawn but marked as a transition week and left out of before/after summaries.
Reason: 2025-W01 (30 Dec – 5 Jan) has only one day of pricing, and W31 straddles the 1 Aug 2025 pay rise, so both mix pre and post days.
/zones index route23 Oct 2026 · SPEC §9.1 · L01, L05, L14
New route /zones from site/src/zones/index.md: the zone level and change maps (Q1, Q10) and a searchable table linking to each zone page. It reads zones/index.json and taxi_zones.geojson.
Reason: zones/index.json had no page in SPEC §9.1, and the city-wide zone maps need one.
23 Oct 2026 · SPEC §1, §10 · L00, L17
Git repo initialised in the existing project folder. Because the folder name contains spaces, the Makefile and scripts use relative paths only. The user creates the GitHub repo and enables GitHub Pages; L17 needs both.
Reason: worktree-based lanes need git; Pages needs a GitHub repo; Make doesn’t handle paths with spaces.
Update 23 Oct 2026: the repo was created at the user’s request as https://github.com/aagamshah15/nyc-ride-market, first private, then made public by the user the same day. GitHub Pages (source: GitHub Actions) is not enabled yet; L17 needs it.