diff --git a/.gitignore b/.gitignore index 37bee45..e97f437 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,16 @@ -#foo +# OS cruft +.DS_Store +Thumbs.db + +# Editor/tooling +.vscode/ +.idea/ + +# Python (build-time tooling only, never shipped) +__pycache__/ +*.pyc +.venv/ +venv/ + +# Serena MCP tool metadata (local dev-tool state, not project content) +.serena/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..695592f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,232 @@ +# Agent Instructions + +This repository is being developed interactively using Codex and Claude Code. + +## Repository structure + +This repo serves `erikson1970.github.io` as a whole: + +- `/` (root `index.html`, root `css/`) is a modest personal landing page — + not a project in its own right. Keep it simple and static. +- `projects//` holds each individual project as a self-contained + static site (its own `index.html`, `css/`, `js/`, `data/`, etc.), reachable + at `erikson1970.github.io/projects//`. The first and (for now) + primary project is `projects/world-history/`, the world-history explorer + described throughout the rest of this file. +- `ISSUES.md` and `TRACEABILITY.md` at the root are shared across the whole + repo (one continuous history, not split per project) — see "Issue and + requirement tracking" below. +- `AGENTS.md` and `README.md` stay at the root as the overall primer; a + project may have its own `docs/` for project-specific detail (e.g. + `projects/world-history/docs/`). + +When adding a new project, give it its own `projects//` directory and +link it from the root landing page; don't scatter its files into the shared +root directories. + +## Project intent (`projects/world-history/`) + +Build a fully static, graphically rich, interactive world-history explorer for GitHub Pages. + +Do not introduce: + +- a production backend; +- authentication; +- a database server; +- API keys; +- runtime Python dependencies. + +Python is acceptable for build-time preprocessing. + +The same static-only, no-backend constraints apply to the root landing page +and to any future project added under `projects/`. + +## Source of truth + +Excel files in `projects/world-history/source/` are the human-editable source data. + +Generated JSON in `projects/world-history/data/` should be reproducible from those files. + +Do not silently modify generated JSON in a way that cannot be recreated from the source workbook or build script. + +## Read first + +Before substantial work, read: + +- `README.md` +- `projects/world-history/docs/STATUS.md` +- `projects/world-history/docs/DATA_MODEL.md` +- `projects/world-history/docs/VISUALIZATION.md` +- `projects/world-history/docs/IMPLEMENTATION_PLAN.md` + +## Historical-data discipline + +Do not silently “correct” source-poster data using general knowledge. + +Distinguish among: + +1. data transcribed from the ChartOrigin poster; +2. externally researched additions; +3. implementation assumptions. + +When adding researched data, preserve source URL, notes, confidence, and uncertainty where appropriate. + +## IDs + +Stable IDs are important. + +Before renaming `box_id`, `seai_id`, `link_id`, or `segment_id`, search all dependent tables and generated files. + +Prefer migrations over casual renaming. + +## Wikipedia TODO URL + +This URL is an intentional placeholder: + +```text +https://en.wikipedia.org/wiki/Time_management#Implementation_of_goals +``` + +Treat it as `TODO`, not as actual metadata. + +## Initial stack preference + +Preferred progression: + +1. Plotly for rapid Sankey prototype; +2. D3 if custom timeline/alluvial geometry is needed; +3. ECharts is acceptable if it materially simplifies interaction. + +Do not prematurely rewrite a working prototype merely to change libraries. + +## Browser architecture + +Prefer plain HTML, CSS, modular JavaScript, and static JSON. + +Avoid framework introduction unless there is a demonstrated need. + +## Data build + +Implement validation as early as practical. + +The build should detect: + +- duplicate IDs; +- broken foreign keys; +- malformed years; +- invalid population ranges; +- unknown relation types. + +Warnings should include: + +- TODO URLs; +- missing population; +- low-confidence records. + +## Visualization semantics + +A Sankey/alluvial link does **not** mean literal conservation of people. + +Ribbon width means estimated historical scale unless a particular view explicitly defines another metric. + +Chronology must remain semantically correct. + +Do not allow an auto-layout to reorder nodes in a historically misleading way. + +## Accessibility + +Interactive marks should not require hover. + +Where practical: + +- click/tap selects; +- keyboard access is available; +- inspector mirrors tooltip information; +- color is not the sole encoding. + +## Scope control + +Prefer small vertical slices: + +1. load data; +2. validate; +3. render a small subset; +4. synchronize selection; +5. add filtering; +6. expand data coverage. + +Do not attempt to perfect every historical region before producing a working visualization. + +## Source control workflow + +`main` is treated as sacred, even though it is not branch-protected on GitHub. + +- Do work on `feature/` or `fix/` branches, never directly on `main`. +- Merge to `main` only after a milestone's goal is verified closed (see + "Milestone review process" below). +- Commit frequently on the working branch — small, real commits, not one + giant squash at the end. + +## Issue and requirement tracking + +- `ISSUES.md` tracks open defects/deferred work, each tagged **Gatekeeper** + (blocks the current milestone) or **Minor** (tabled — tracked, not + blocking). +- `TRACEABILITY.md` tracks closure of stated requirements/goals (from this + file, `README.md`, and each project's own docs, e.g. + `projects/world-history/docs/DATA_MODEL.md` and + `projects/world-history/docs/IMPLEMENTATION_PLAN.md`) against verification + evidence. +- Gatekeeper issues must be resolved (or explicitly reclassified as minor, + with reasoning) before a milestone branch merges to `main`. Minor issues + are fine to table indefinitely. + +## Milestone review process + +A **milestone branch** is one that closes out a numbered phase/milestone from +a project's `docs/IMPLEMENTATION_PLAN.md` (e.g. +`projects/world-history/docs/IMPLEMENTATION_PLAN.md`), a site-level change +(e.g. the Milestone 3 root/`projects/` restructure), or `TRACEABILITY.md` +generally (e.g. `feature/repo-reset` for Milestone 0). Small `fix/` +branches for sub-tasks within a milestone don't need their own council; only +the milestone-closing merge to `main` does. + +Before that merge, close out the milestone by instantiating a small **council +of experts**: independent reviewers (each a subagent with a distinct lens) +who check the milestone's stated goal against the actual repo state — not a +summary of it — and report findings. At minimum, run: + +1. a **data/content integrity** lens (whatever the milestone touched: + workbook, generated JSON, etc.); +2. an **architecture/static-site constraints** lens (this file's Project + intent constraints, recommended structure, no leftover disposable + content); +3. a **process & documentation consistency** lens (do `ISSUES.md` and + `TRACEABILITY.md` cross-reference each other correctly, do stated file + paths actually resolve, is anything stale) — do not skip this one; it has + caught real issues that the other two lenses miss. + +Whoever drives the merge (the session/agent orchestrating the milestone) +reconciles the council's findings into `ISSUES.md` (new issues, filed at the +correct severity) and `TRACEABILITY.md` (status updates), and fixes cheap +wording/process nits inline rather than filing them. Each reviewer should +report a `VERDICT: PASS | PASS_WITH_MINOR_ISSUES | FAIL` plus a `FINDINGS` +list tagged `[gatekeeper]` or `[minor]`, citing concrete evidence (file +paths, counts, quoted lines) rather than impressions. + +A milestone can close with tabled minor issues; it should not close with +open gatekeeper issues, and a `FAIL` verdict from any reviewer blocks the +merge until resolved or the finding is reclassified with stated reasoning. + +## Definition of done for v0.1 (`projects/world-history/`) + +A successful v0.1 of the world-history explorer: + +- runs as a static site; +- loads generated JSON; +- shows an interactive chronological Sankey/alluvial subset; +- shows a simple timeline; +- supports selecting a historical box; +- updates an inspector; +- supports at least one region filter; +- is deployable directly to GitHub Pages. diff --git a/HotelList.txt b/HotelList.txt deleted file mode 100644 index 16d8cf7..0000000 --- a/HotelList.txt +++ /dev/null @@ -1,20 +0,0 @@ -Near Natick Mall -https://www.google.com/maps/place/Magnuson+Hotel+Framingham/@42.375724,-71.3588041,11.94z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e388899793653d:0x311c731fa3c55bd2 -https://www.google.com/maps/place/Crowne+Plaza+Boston-Natick/@42.375724,-71.3588041,11.94z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e38886b31319e7:0xce21e72878a39355 -https://www.google.com/maps/place/Boston%2FNatick+Travelodge/@42.297921,-71.5519922,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e38883dd75517d:0x34d43e2dd8208bba -https://www.google.com/maps/place/Courtyard+Boston+Natick/@42.297921,-71.5519922,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e3889d9832d973:0x51b30ad7146c6cf1 -https://www.google.com/maps/place/Hampton+Inn+Boston%2FNatick/@42.2845889,-71.4135279,13z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x0000000000000000:0x90ce182cc66f4946 -https://www.google.com/maps/place/Red+Roof+Inn+Boston+-+Framingham/@42.2845889,-71.4135279,13z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x0000000000000000:0x20ff70aff91febc5 - - -On RT-9 in Framingham -https://www.google.com/maps/place/Sheraton+Framingham+Hotel+%26+Conference+Center/@42.297921,-71.5519922,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e38a27a40998f7:0xc901f7bfb3e62eaa -https://www.google.com/maps/place/Motel+6+Bstn-Frmgham/@42.297921,-71.5519922,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e38a26c0032c15:0x75e183388d06656 - - -On Rt-128 -https://www.google.com/maps/place/Hotel+Indigo+Boston+-+Newton+Riverside/@42.3339714,-71.3944735,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x89e383ba69fea8f3:0xd340c878a4e20c8a -https://www.google.com/maps/place/Boston+Marriott+Newton/@42.3339714,-71.3944735,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x0000000000000000:0xe9780f9eba24e960 - -On Rt-128 in Waltham -https://www.google.com/maps/place/Embassy+Suites+by+Hilton+Boston%2FWaltham/@42.3339714,-71.3944735,11z/data=!4m5!1m2!2m1!1shotels+near+home!3m1!1s0x0000000000000000:0xcd882ff41d9ace68 diff --git a/ISSUES.md b/ISSUES.md new file mode 100644 index 0000000..b157449 --- /dev/null +++ b/ISSUES.md @@ -0,0 +1,309 @@ +# Issues + +Open-issue tracker for `erikson1970.github.io` as a whole (the root landing +page, `projects/world-history/`, and any future project) — one shared, +continuous history, not split per project. + +Severity: + +- **Gatekeeper** — blocks closing the current milestone. Must be fixed or explicitly downgraded before merging the milestone branch to `main`. +- **Minor** — tabled. Tracked but does not block milestone closure. + +Status: `Open`, `Tabled`, `Resolved`. + +An issue closed by a milestone council review notes which review closed it. + +**Path note:** issues filed before Milestone 3 refer to paths at the +repository root (`docs/`, `source/`, `tools/`, `css/`, `js/`, `data/`) — +accurate at the time. As of Milestone 3 those paths live under +`projects/world-history/`. Historical entries are left as originally +recorded rather than rewritten. + +--- + +## Open + +_(none yet — see Tabled below)_ + +## Tabled (minor, deferred) + +### ISSUE-001 — `Regions` rows lack a unique per-row identifier +- **Severity:** Minor +- **Status:** Tabled +- **Source:** `docs/DATA_MODEL.md`, workbook `Regions` sheet +- **Description:** `region_id` is a grouping key shared by every country row in a region (e.g. `NE_SCAND` repeats once per country), not a unique row key. Fine for filtering today; will need a real per-row key (or a composite `region_id`+`country`) if `Regions` grows into real historical timelines per Phase 8. +- **Deferred until:** Phase 8 (region expansion) or whenever a `Regions`-keyed foreign key is needed. + +### ISSUE-002 — All `Boxes`/`SEAIs` URLs are still the TODO placeholder +- **Severity:** Minor +- **Status:** Tabled +- **Source:** `docs/STATUS.md` +- **Description:** Confirmed by validation: 198/198 `Boxes` rows and 83/83 `SEAIs` rows currently hold `https://en.wikipedia.org/wiki/Time_management#Implementation_of_goals`. Expected at this stage; tracked here so it isn't mistaken for a data bug later. +- **Deferred until:** "Add real Wikipedia URLs gradually" (STATUS.md recommended next work, priority 4). + +### ISSUE-003 — `Population` table has zero filled estimates +- **Severity:** Minor +- **Status:** Tabled +- **Source:** `docs/STATUS.md` +- **Description:** All 390 seeded knot-point rows have no `population` value yet, by design (values intentionally not invented). No width-by-population rendering is possible until a representative subset is filled. +- **Deferred until:** Phase 6 (population experiment); STATUS.md's recommended first-subset list (Roman, Byzantine, Persian, Ottoman, major Chinese dynasties, etc.). +- **Note (Milestone 5):** This is why the Phase 4 timeline (`js/timeline.js`) has no population-based width mode: `js/state.js`'s `widthMode` field exists but has no UI control yet, deferred until this table has real values to render. + +### ISSUE-004 — `Links` and `BoxSegments` tables do not exist yet +- **Severity:** Minor +- **Status:** Tabled +- **Source:** `docs/DATA_MODEL.md`, `docs/STATUS.md` +- **Description:** No succession/relationship data and no per-country-lane segmentation exist yet. Alluvial/Sankey view and accurate multi-country boxes (Rome, Ottomans, etc.) are blocked on these. +- **Deferred until:** Phase 3 (`Links`, minimal subset) and Phase 7 (`BoxSegments`). +- **Note (Milestone 4):** The `Links` half is now partially resolved — a 7-row hand-authored subset covering the Mediterranean/Europe cluster (`docs/IMPLEMENTATION_PLAN.md` Phase 3) exists and drives a working Sankey/alluvial prototype (see `TRACEABILITY.md` § Milestone 4). The China cluster and the rest of the dataset remain unlinked, and `BoxSegments` remains fully open (still deferred to Phase 7). Left open rather than closed since the title's `Links` scope is only partially covered. + +### ISSUE-006 — No automated test suite for `tools/wh_data.py` +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 1 implementation +- **Description:** `build_data.py`/`validate_data.py` were exercised manually against the real workbook and against a deliberately corrupted copy (duplicate `box_id`, invalid `color_hex`, cascading FK break) to confirm the ERROR path genuinely blocks output. There's no repeatable test file for this yet. +- **Deferred until:** whenever the validation logic grows complex enough that manual spot-checks stop being sufficient, or before a CI step is added. + +### ISSUE-005 — Six `Boxes` rows have no `start_year` +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Data-integrity council review of `source/world_history_chart_dataset_v2.xlsx` +- **Description:** A handful of "Indigenous Era" boxes (e.g. `US_INDIG`, `CA_INDIG`, `AR_INDIG`, `AU_INDIG`) have a null `start_year` because the poster prints an illegible "c. [BCE]" with no parseable number there. `end_year` is always present, and `DATA_MODEL.md`'s rule only requires `start_year <= end_year` "when both exist," so this is not a validation-rule violation — just an open transcription gap, consistent with STATUS.md limitation #2. +- **Resolution:** None yet. Left for whoever transcribes those boxes' start dates, or for the build script to render them with an explicit "unknown start" treatment. +- **Note:** This entry was misfiled under `## Resolved` from Milestone 0 through Milestone 1 despite its own `Status:` field always saying `Tabled` — caught and moved here by the Milestone 1 process/docs council review. +- **Note (Milestone 5):** `js/timeline.js`'s `buildTimelineLayout()` gives these six boxes exactly the "explicit unknown start treatment" this issue's resolution note anticipated — `approxStart: true`, with the bar's rendered start pinned to the current view's left edge rather than a fabricated year. Still not resolved (no real `start_year` has been transcribed), just no longer un-rendered. + +### ISSUE-007 — `wh_data.py` vocabulary-check loop has dead code for `estimate_method` +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 1 data-integrity council review +- **Description:** The loop in `validate_population` iterates `for field_name in ("population_basis", "estimate_method")`, but the guard condition only fires for `field_name == "population_basis"`, so the `estimate_method` branch can never execute. Harmless today because `DATA_MODEL.md` §3 defines no recommended vocabulary for `estimate_method` (nothing is actually missed), but the code reads as if both fields are checked. +- **Deferred until:** whenever `estimate_method` gets a real controlled vocabulary, or general pipeline cleanup. + +### ISSUE-008 — Malformed/corrupt source workbook produces a raw Python traceback, not a clean CLI error +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 1 data-integrity council review +- **Description:** A truncated/non-zip `.xlsx` raises an uncaught `zipfile.BadZipFile` from inside `openpyxl.load_workbook`, and a workbook missing an expected sheet raises an uncaught `ValueError` from `wh_data.load_workbook`; neither is wrapped in a try/except in `build_data.py`/`validate_data.py`. Confirmed safe in both cases (exit code 1, no output written) — just not a clean `error:`-prefixed message like the already-handled missing-`--source`-file case. +- **Deferred until:** whenever the CLI's error UX is revisited, or before non-maintainers start editing the workbook directly. + +### ISSUE-009 — No automated test suite for `js/app.js`/`js/data.js`/`js/state.js` +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 2 process/docs council review +- **Description:** Parallel to ISSUE-006 but for the frontend: the Milestone 2 commit message documents real Node-based runtime verification (against a live local server and a minimal DOM stub), but none of it is a committed, repeatable test file — only prose in the commit message. ISSUE-006's title/scope is explicitly the Python pipeline (`tools/wh_data.py`) and does not cover this. The same gap recurred in Milestone 3: a Node `loadAllData()` run verified the moved `data/*.json` still loads correctly post-move, again only as prose (see `TRACEABILITY.md` M3-4, downgraded to Partial for this reason). Recurred a third time in Milestone 4: a Node fake-DOM harness verified the Sankey/Links integration (data load, box-list render, region-filter narrowing, box- and link-click-to-inspector, the accessible fallback list, and the Plotly-unavailable degradation path), but again only as commit-message/`TRACEABILITY.md` prose, not a committed test file (see `TRACEABILITY.md` M4-6/M4-8). +- **Deferred until:** whenever `js/` grows complex enough that manual/ad-hoc verification stops being sufficient, or alongside ISSUE-006 if/when a test runner is introduced for either side. +- **Note (Milestone 5):** Partially resolved rather than recurring a 4th time — `js/timeline.test.mjs` is a committed, repeatable test for `buildTimelineLayout()` (run with `node js/timeline.test.mjs`; a new root `package.json` with `"type": "module"` lets Node load it and `./timeline.js` directly, no scratch-copy workaround needed). `renderTimeline()`'s actual D3/DOM rendering and click-firing are still unverified (no real browser in this environment), and `sankey.js`/`app.js`/`data.js`/`state.js` remain entirely uncovered, so this issue stays open and Tabled rather than moving to Resolved. +- **Note (Milestone 6):** A second module now has committed coverage — `js/sankey.test.mjs` (run with `node js/sankey.test.mjs`), covering `buildSankeyFigure()` (previously untested, Phase 3) and the new `computeSankeyHighlight()` (Phase 5). `applySankeySelection()`'s actual `Plotly.restyle` call, and `app.js`/`data.js`/`state.js` in full, remain uncovered — still Tabled, not Resolved. + +### ISSUE-010 — Milestone commits land as one (or two) large commits, not the "commit frequently" granularity AGENTS.md describes +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 2 process/docs council review +- **Description:** AGENTS.md § Source control workflow says "commit frequently on working branch — small, real commits, not one giant squash at the end." All three milestones so far (0, 1, 2) each landed as one primary commit (plus, for 1 and 2, one small follow-up docs commit) rather than incremental commits during the work. Not flagged by either of the first two council reviews; caught on the third pass. No functional impact — each commit message is detailed and the work was verified as a unit before committing — but it's a real gap between written process and actual practice. +- **Deferred until:** a decision on whether to tighten actual practice (commit more granularly mid-milestone going forward) or relax AGENTS.md's wording to match reality; not worth rewriting history on already-merged milestones. +- **Note (Milestone 4):** Improved, not resolved — Milestone 4 split cleanly into three commits (data pipeline, UI, docs/traceability) instead of one or two, closer to but still short of the "small, real commits" ideal. Left open since Milestones 0–3 are unaffected and the practice isn't yet consistent enough to call this closed. +- **Note (Milestone 5):** Regressed back to two commits (code, then docs/traceability) — not egregious (still a clean split, not a single squash), but not the three-commit improvement Milestone 4 made either. Practice still inconsistent; left open. +- **Note (Milestone 7):** Regressed further — landed as a single commit bundling the new `js/timescale.js` module, the `js/timeline.js`/`js/sankey.js`/`js/app.js`/`index.html` integration, all three test files, and all docs/traceability updates together (flagged by that milestone's own architecture council review). Practice remains inconsistent milestone to milestone; left open. + +### ISSUE-011 — `Links` "transition year sensible" check is a loose union-envelope heuristic, not a real sensibility check +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 4 data-integrity council review +- **Description:** `docs/DATA_MODEL.md` §8 lists "transition year sensible" as a `Links` validation rule. The actual implementation (`tools/wh_data.py` `validate_links`) checks only that the link's `year` falls within `[min(source.start_year, target.start_year), max(source.end_year, target.end_year)]` — the *union* of both boxes' lifespans, not their overlap or adjacency. A link between two boxes centuries apart could still pass this check if the chosen year happened to land inside the wider combined span. Not triggered by any of the current 7 rows (all pass cleanly and are historically accurate), and it's correctly scoped as a WARNING rather than a build-blocking ERROR, but the word "sensible" oversells what's actually verified. +- **Deferred until:** whenever a real subset gets large/varied enough that this heuristic would plausibly miss a genuinely bad link, or general validation-logic cleanup. + +### ISSUE-012 — Timeline SVG doesn't re-render on window resize; a few prehistoric-landmark SEAIs can visually detach from their row if the year range is widened enough +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 5 architecture/accessibility council review +- **Description:** Two independent minor gaps in `js/timeline.js`: (1) `renderTimeline()` computes SVG width once per render from `container.clientWidth`; unlike the Sankey/Plotly diagram (`responsive: true`), it only picks up a new width on the next state change, not on a bare window resize. (2) A few `seais.json` rows (e.g. `L15`/`PT_TRIBES` at year -3500, `L18`/`ES_IBERIAN` at -14500, `L21`/`FR_GAUL` at -17000) have a real numeric year that predates their parent box's own `start_year` by thousands of years — a pre-existing quirk in the data, not something `timeline.js` introduced. At the default `-3000..2026` view these are correctly excluded by the ordinary year-range filter, but if a user widens "From year" enough to bring one into view, its diamond marker clamps to the plot's left edge while its parent box's bar sits far to the right, which could read as misattributed. +- **Deferred until:** (1) whenever the timeline gets enough real usage to justify a resize listener; (2) whenever those specific `seais.json` rows are reviewed for whether their year, their parent `box_id`, or both need correcting — likely alongside whatever eventually addresses ISSUE-005's prehistoric-era boxes generally. + +### ISSUE-013 — Semantic-zoom time scale changes snap instantly, not smoothly animated +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 7 (Phase 5.5) implementation, `docs/timescaleRequirement.md` § Zoom Interaction +- **Description:** That doc explicitly frames smooth animation while zooming/dragging the time-compression slider or year-range inputs as optional ("if technically practical, animate the layout smoothly"). The current implementation (`js/timeline.js`'s full SVG redraw per state change, `js/sankey.js`'s `applySankeyTimeScale()` via `Plotly.restyle`) recomputes and redraws positions immediately on every `input` event with no transition/tween, so bars, markers, ticks, and Sankey nodes jump to their new position each frame rather than easing. +- **Deferred until:** real usage suggests the instant-snap behavior is actually distracting/hard to track at the current ~198-box, small-Links-subset scale; would likely mean D3 `.transition()` calls in `renderTimeline()` and a Plotly `layout.transition`/animated `restyle` for the Sankey side. + +### ISSUE-014 — Time-scale slider's continuous `input` updates re-render every panel, not just the ones that depend on it +- **Severity:** Minor +- **Status:** Tabled +- **Source:** Milestone 7 (Phase 5.5) council review (accessibility/UX lens) +- **Description:** `js/app.js`'s single `store.subscribe` callback re-runs `renderList` (rebuilds the ~198-item box list), `renderInspector`, `renderTimelineView`, `renderAlluvialListSelection`, `renderSankeySelection`, and `renderSankeyTimeScale` on every state change, including the new `#time-scale` slider's `input` event — which can fire many times per second during a drag or a held arrow key. Only `renderTimelineView` and `renderSankeyTimeScale` actually depend on `timeScale`; the rest do redundant work each tick. `docs/timescaleRequirement.md`'s own Performance section recommends updating only x-related geometry where possible. Unlikely to be noticeably slow at the current ~198-box/7-link scale (the pre-existing region/year filters already do a full box-list rebuild on `change`, just far less frequently), but this is the first control wired to a high-frequency event, and the gap is real and unaddressed. +- **Deferred until:** real usage shows jank during a slider drag, or the dataset grows enough (more boxes, a larger `Links` subset) to make the redundant work costly — likely fix is either narrowing what `store.subscribe` re-renders per patch (e.g. a per-field subscription) or `requestAnimationFrame`-throttling the slider's `store.set` calls. + +## Resolved + +### ISSUE-000 — Repo contained an unrelated portfolio template and stray files +- **Severity:** Gatekeeper +- **Status:** Resolved +- **Description:** `index.html` and `static/` held a generic "Portfolio template" theme (Lorem Ipsum, fake bios) unrelated to this project; `HotelList.txt` (personal hotel-search links) and `chat_log.md` (dead sandbox links from doc handoff) were also present. +- **Resolution:** Removed `static/`, `HotelList.txt`, `chat_log.md`; replaced `index.html` with a minimal placeholder. Closed by Milestone 0 council review. + +## Milestone council reviews + +### Milestone 0 — Repository reset & data intake +Reviewed 2026-09-06 against commit `3f84688` (branch `feature/repo-reset`), three lenses: + +| Reviewer | Verdict | +|---|---| +| Data integrity | PASS | +| Static-site architecture / constraints | PASS | +| Process & documentation consistency | PASS_WITH_MINOR_ISSUES | + +No gatekeeper findings. The process/docs reviewer's minor findings (severity-field enum drift on a resolved issue, no per-entry `Status:` field, ambiguity in `AGENTS.md`'s milestone-review process) were fixed inline in this document and in `AGENTS.md` rather than filed as separate issues. Milestone approved to merge to `main`. + +### Milestone 1 — Data build pipeline +Reviewed 2026-09-06 against commit `74459d7` (branch `feature/build-data-pipeline`), three lenses: + +| Reviewer | Verdict | +|---|---| +| Data integrity | PASS | +| Static-site architecture / constraints | PASS | +| Process & documentation consistency | PASS_WITH_MINOR_ISSUES | + +No gatekeeper findings. New minor issues filed: ISSUE-007 (dead code in a vocabulary-check loop), ISSUE-008 (raw traceback on a malformed/corrupt workbook instead of a clean CLI error). The process reviewer's misfiled-`ISSUE-005` finding was fixed inline (moved from `## Resolved` to `## Tabled`, matching its own `Status:` field). Also fixed inline: `tools/README.md` now points at `tools/requirements.txt`, and `docs/STATUS.md` was refreshed to mention the build/validation pipeline. Milestone approved to merge to `main`. + +### Milestone 2 — Minimal static application +Reviewed 2026-09-06 against commits `7511bee`/`3881455` (branch `feature/minimal-app`), three lenses: + +| Reviewer | Verdict | +|---|---| +| Data integrity | PASS_WITH_MINOR_ISSUES | +| Static-site architecture / constraints & accessibility | PASS | +| Process & documentation consistency | PASS_WITH_MINOR_ISSUES | + +No gatekeeper findings. Fixed inline (real code/docs changes, not just tabled): +- **Sort-order bug** (data-integrity finding): `filteredBoxes` in `js/app.js` sorted the 6 null-`start_year` boxes from ISSUE-005 by their *end* year, misplacing e.g. `US_INDIG` (prehistory–1607) next to 16th–century boxes instead of near other prehistoric-start entities. Changed the fallback from `?? end_year ?? 0` to `?? Number.NEGATIVE_INFINITY` so these boxes sort to the front, consistent with them representing the earliest, least-precisely-dated era for their region. +- **Unhandled rejection** (architecture finding): `main()`'s call site had no `.catch()`, so a rendering-time error (as opposed to a fetch failure, already handled) would only produce a silent console warning. Added `main().catch(...)` routing to the same `setStatus(..., true)` error display. +- **Stale `js/README.md`** (process finding): rewritten to describe the actual `data.js`/`state.js`/`app.js` split instead of a since-superseded planned module list. +- **Stale `docs/STATUS.md`** (process finding): refreshed to mention the Phase 2 prototype and mark "Build first interactive prototype" done. + +New minor issues filed (tabled, not gatekeepers): ISSUE-009 (no automated test suite for the new `js/` modules, parallel to ISSUE-006), ISSUE-010 (milestones have landed as one or two large commits rather than the frequent-small-commits granularity AGENTS.md describes — a process/practice gap, not unique to this milestone). Milestone approved to merge to `main`. + +### Milestone 3 — Site restructure +Reviewed 2026-09-06 against commit `ce8b234` (branch `feature/site-restructure`), three lenses: + +| Reviewer | Verdict | +|---|---| +| Path & link integrity | PASS | +| Static-site architecture / constraints & accessibility | PASS_WITH_MINOR_ISSUES | +| Process & documentation consistency | PASS_WITH_MINOR_ISSUES | + +No gatekeeper findings. Fixed inline (real code/docs changes, not just tabled): +- **Missing heading on project cards** (architecture/accessibility finding): `.project-card` links weren't wrapped in a heading, so screen-reader users navigating by heading list would miss per-project headings once more cards are added. Wrapped the link in an `

` in `index.html` and updated `css/site.css` selectors accordingly. +- **Missing `fonts.googleapis.com` preconnect** (architecture finding, trivial performance nit): added the second `` alongside the existing `fonts.gstatic.com` one. +- **Stale `README.md` section citations in `TRACEABILITY.md`** (process finding): Milestones 0–2's requirement rows cite "README.md § ..." headings that moved wholesale to `projects/world-history/README.md` in Milestone 3; the existing "Path note" only covered directory paths, not this. Extended the note to explain the README content relocation too. +- **M3-4 evidence overstated** (process finding): the requirement's "Met" status rested partly on a Node `loadAllData()` run that, like Milestone 2's equivalent checks (ISSUE-009), was never captured as a committed, repeatable test — only asserted in prose. Downgraded M3-4 to Partial in `TRACEABILITY.md` and extended ISSUE-009's description to note the recurrence. + +Noted, not newly filed: Milestone 3 again landed as two large commits (`121b4ff`, `ce8b234`), consistent with the already-tabled ISSUE-010 rather than a new or worsened gap. Milestone approved to merge to `main`. + +### Milestone 4 — Plotly alluvial prototype (Phase 3) +Reviewed against commits `e363906`/`be635c9`/`65f38ab` (branch +`feature/alluvial-prototype`), three lenses: + +| Reviewer | Verdict | +|---|---| +| Data / content integrity | PASS_WITH_MINOR_ISSUES | +| Architecture / static-site constraints & accessibility | PASS_WITH_MINOR_ISSUES | +| Process & documentation consistency | PASS_WITH_MINOR_ISSUES | + +No gatekeeper findings. Fixed inline (real code/docs changes, not just tabled): +- **No keyboard/AT access to Sankey links** (architecture/accessibility finding): Plotly's SVG hit-targets are mouse-only with no tabindex, and unlike box selection (already a real `