Bronze Age Near East. Generated from ROADMAP.md and data/.
Era rail preview. Segment width is railWeight, derived from
actual band membership in places.geojson — not hand-authored (invariant 10).
Numbers are places attested in each band.
tell repo, push index.html + src/main.jsdocs/DECISIONS.md D1mapView.js: init map centered on Mesopotamia, flat projectionmanifest.json + sw.js with CACHE_VERSIONdocs/DECISIONS.md D5Gate production URL loads a blank basemap in both projections, zero console errors.
Status deployed and passing locally. Verified in headless Chromium against the pinned MapLibre build: map loads, flat ⇄ globe ⇄ flat all correct, service worker registers, place markers render in both projections, and zero console errors, page errors or failed requests. The graticule is rectilinear in flat and visibly curved in globe, confirming the toggle does real work rather than reporting that it did. Still owed by a human: the same pass on the production URL in Safari — the build sandbox has no Safari and cannot reach the deployed site.
docs/CHRONOLOGY.md — middle chronology chosen and documented (resolves SPEC Q2)package.json boundary — "type": "module", zero deps, one gate command (docs/DECISIONS.md D6)docs/LICENSES.md — audited per-source register (47-agent verification). SPEC's table was wrong in 6 rows. Q1 answered: historical-basemaps is GPL-3.0, not CC-BY-SAsrc/graph/schema.js — typedefs + runtime validator, shared by app and ETLetl/fetch-pleiades.js — pull, filter to bbox, cache per-place JSONetl/normalize.js — emit places.geojson; derive railWeight (invariant 10)etl/fetch-periodo.js — periodisation authority, joined to Pleiades via sameAs (falls back to the stale GitHub archive; data.perio.do unreachable from the sandbox)etl/validate.js — schema check, non-empty sources check, exit codes, no --forcedata/places.geojson (target ≥150 records) — 62 committed, target not metGate node etl/validate.js passes clean. Zero records with empty sources[]. Spot-check five records against Pleiades by hand.
Status validator passes clean on 62 records, all sourced — the ≥150 target is not met, so the gate is not passed, but the blocking cause is resolved. Periodisation now comes from Pleiades' attested periods resolved through PeriodO, not from its sparse Barrington-derived date ranges: 23 → 62 places, and Babylon, Kish and Isin are recovered. Remaining shortfall and the supplements that would close it: docs/DATA-COVERAGE.md §7.
time/bands.js — 7 Bronze Age bands, widths by record densitytime/timeIndex.js — query(year), setBand(), onChange subscriptiontime/eraRail.js — segmented buttons, density-proportional widthstime/detailTrack.js — in-band scrubbing, snapping to attested eventsplaceGraph to subscribe to timeIndexGate clicking a band visibly changes map contents in <200ms. Grep the codebase: no year arithmetic outside src/time/.
ui/layerPanel.js — 8 togglesgraph/placeGraph.js — filter by layer tagui/detailPanel.js — type-dispatched rendering (Place / Edge / Text / Artifact)ui/emptyState.js — honest sparse-band messageGate all 8 toggles filter without map re-init. Select a deliberately sparse band and confirm the empty state, not a blank canvas.
Watercourse typedef + validator rules in src/graph/schema.js (fifth record type; amends SPEC §4.1)data/hydrology.geojson — 8–15 hand-curated features: Euphrates 2–3 states, Tigris 1–2, Gulf shoreline 2, marsh 1–2, named Ur III canalsmap/hydrology.js — line + polygon rendering, certainty tier styling (solid / dashed / faint)placeGraph — not a parallel subscriber to timeIndex (invariant 1)Gate stepping Ur III → Kassite visibly moves the water, and a reconstructed channel is distinguishable from a surveyed one without clicking. Spot-check every feature's sources.
data/edges.json — hand-curated from Ur III and Old Assyrian attestations, ~20–40 edges to startmap/edges.js — animated flow lines when economy layer is onattestation tier visible in the UI (textual vs archaeological vs inferred)Gate economy layer on → the trade system reads visually. Show it to someone with no background; if they don't grasp "these places were connected," redesign before moving on.
_redirects for SPA routingcloudflare-deploy checklistdocs/VERIFICATION.md §7