Both are zero-domain in the sense the spec meant: they import only `vue` and read rows through accessors. Bodies are what research-dashboard shipped apart from the two parameters the spec named and one policy object, and the old paths re-export for one cycle. ★ THE FIRST STEP FOUND TWO GATES THAT READ THESE FILES BY PATH, which is why it is now the first step. Landing 1 nearly disarmed check-facet-cascade the same way. internal/check-csv-export-shape.mjs does not import useCsvExport; it READS the source and extracts esc() out of it. Left at the plugin path it would have read the one-line shim, found no esc(), and failed with "could not extract esc()" — a gate accusing a working exporter because its subject moved. check-filter-multivalue.mjs — MINE — lists the same file in its PANELS array. Left at the plugin path it would have read the shim, found no predicate to object to, and PASSED VACUOUSLY. That is worse: a gate going quiet about the thing it guards. Both move in this commit. THE COORDINATE IS A PARAMETER; WHAT MAKES A COORDINATE VALID IS NOT. `coords` replaces only the READ of row.longitude / row.latitude, which is pray-tools' spelling and not a universal one. Every guard stays shared: Number() on API strings, 0 accepted per axis, the exact 0,0 null-island sentinel rejected, the out-of-range check. A kit that let each caller re-implement that validation would hand the next dashboard the same four bugs to rediscover. ★ AND THE OPTION WAS DEAD WHEN I FIRST WROTE IT. `coords` was accepted in the signature and never passed to selectionBounds, so a caller could set it, type-check clean, build clean, and watch it do nothing. This tree has paid for that shape before — a defineProps on a component the custom element never binds — and it is worse than a missing feature because it READS as supported. Nobody files a bug against a knob they assume they misused. check:kit-options-reachable now asserts, across all four shared composables, that every option accepted is used. THE CAMERA'S EIGHT CONSTANTS ARE ONE DECISION, so CAMERA_POLICY exports them together. The failure that prevents is a second dashboard re-picking them one at a time and arriving at a camera that feels different from Big Picture's for no reason anybody wrote down. It is read-only and deliberately not yet overridable: making each a per-caller option means threading eight of them through every use, and no consumer has asked for a different camera. Exporting the decision so it can be cited is the half with a use today; saying so is better than shipping eight options nobody passes. THE EXPORTER GAINS exportLabel and sources. "Research Dashboard" was this dashboard's name, and the provenance line said nothing about where the data came from — which is what a provenance line is for. Both default to today's output, to the byte. ★ AND THE NEW GATE HAD THE COMMENT HOLE TWICE IN ONE SITTING. First it searched the raw body, and the comment beside the fixed call site says "`coords` IS PASSED HERE" — so the mutant that removed the argument left it green. Then, stripping comments only per-part, it split the signature's comment PROSE on commas and reported that useCsvExport accepts `and`. Comments are text; every text search has to say so, in both directions. That is the fourth variant of one mistake this week, and all four were caught by running the mutant rather than by reading. Library index regenerated in the same commit, 103 items. Source only. STUDIO: needs a rebuild of research-dashboard and dashboard-plus-grid. The internal/ hunk is one line in check-csv-export-shape.mjs. |
||
|---|---|---|
| .. | ||
| api | ||
| colors | ||
| components | ||
| composables | ||
| constants | ||
| data | ||
| i18n | ||
| layouts | ||
| lists | ||
| maps | ||
| packet | ||
| scripts | ||
| stores | ||
| styles | ||
| utils | ||
| index.js | ||
| ProfileLoader.vue | ||
| README.md | ||
library/ (@map) — the shared map template
The other half of the architecture (see ../plugin-designs/README.md):
every map in plugin-designs/<your-map>/ composes the reusable, parameterized pieces that live here.
Fix something here and every map benefits on the next build; break something here and every map
breaks — read components/WARNING.md before touching shared pieces.
| Folder | What lives there |
|---|---|
ProfileLoader.vue |
The root of every bundle: parses profile-config, loads the profile, provides the stores + config |
components/ |
Shared UI — map, legends, controls, popup (PeopleGroupDetail), tables, charts, hints (README) |
composables/ |
Shared logic — map engine (useMapInstance), provider switch, shadow-DOM styles, theming |
stores/ |
Per-instance Pinia stores (ui / map / data) — provided by ProfileLoader, injected by children |
api/ |
Data-source registry (sources.json) + fetch layer — the JAMstack runtime wiring |
colors/ |
Color sets maps opt into via profile-config.colorSet |
i18n/ |
The shared string catalogs (all maps speak the same languages) |
data/ |
Small shared datasets baked at build time (big served data lives in ../data/) |
constants/ |
Shared constants |
scripts/ |
Maintainer pipelines (posters, research) — not part of any bundle |
The rule of thumb (same as WARNING.md): custom code in your app-profile, reusable code here — and things only move from the first to the second once they've earned it.