diff --git a/CLAUDE.md b/CLAUDE.md index 30db039..4761478 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -428,8 +428,43 @@ Theme state lives in `ui/src/theme.jsx` — a React context (`ThemeContext`) wit - **Perspective viewer:** `Forecast.jsx` calls `viewer.setAttribute('theme', dark ? 'Pro Dark' : 'Pro Light')` both on initial load and in a `useEffect([dark, versionId])` so the viewer stays in sync when the toggle fires - **Consuming the theme:** `import useTheme from '../theme.jsx'` then `const { dark, setDark } = useTheme()` +## After a change: restart, and Generate SQL + +Two steps, and which one you need depends on what changed. + +- **Restart the server** for anything in `routes/`, `lib/` or `server.js`. +- **Generate SQL** (Setup, per source) whenever `lib/sql_generator.js` changes. + The templates are *stored* in `pf.sql`, so editing the generator changes + nothing until they are rebuilt — and a template carrying a token the running + code does not substitute fails at the database rather than in JS, which reads + as an unrelated client-side error. + +The order matters: restart first, then Generate SQL, or the old code writes the +templates. + +Schema changes are applied to the live database directly and mirrored into +`setup_sql/` for a fresh install; `01_schema.sql` is idempotent but is not a +migration runner, so running it is not how an existing database gets a new +column. + ## Known issues / active work +- **Zero-row operations report success.** Scale refuses with "Nothing to + scale…" when its slice matches nothing; recode and clone commit an empty log + entry and return `rows_affected: 0`. A recode of a rep whose rows are all + `reference` looked like it worked and did nothing +- **The change log does not show an entry's id**, so there is no way to name + one when asking about it +- **Territory is read onto the session at login**, so granting or changing one + does not reach a signed-in account until it signs in again. Re-reading it per + request in `requireAuth` would also make disabling someone immediate +- **Depth buttons rebuild the view.** A depth lives in `ViewConfig`, so changing + it goes through `restore()` and `Session::update_view_config` tears down and + rebuilds the view — a full traversal — where a manual collapse mutates the + existing one in place. Noticeable on a large grain. The fix is to detect a + depth-only change and call `view.set_depth()` imperatively while still writing + it to the config, at the cost of the two being able to drift + - **Load time is dominated by row count, not payload size.** On `fc_osm_skinny_29` (2.56M raw rows) a 24-column grain still yields 285,685 rows: ~2s to aggregate in pg, but ~15s to serialise those rows out of Postgres and parse them into JS, then