From 35c68048e80a04ca32c79a1f285a472d69bc4bcb Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Thu, 1 Oct 2026 00:08:29 +0000 Subject: [PATCH 1/4] cities-internet, key-cities: neutral source comments Rewrite code comments to drop quoted directives, person-tied dates, internal process and role names, and QA run references, keeping each technical fact intact. Comments only; behaviour unchanged. --- .../cities-internet/connectivity-map.vue | 22 +++++++++---------- .../cities-internet/data-tables.vue | 17 +++++++------- plugin-designs/key-cities/cities-map.vue | 4 ++-- plugin-designs/key-cities/data-tables.vue | 9 ++++---- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/plugin-designs/cities-internet/connectivity-map.vue b/plugin-designs/cities-internet/connectivity-map.vue index d11333c0b..eaba47ce4 100644 --- a/plugin-designs/cities-internet/connectivity-map.vue +++ b/plugin-designs/cities-internet/connectivity-map.vue @@ -13,7 +13,7 @@ function setGlobal(name, value) { * social platform on tap — the connectivity view of where DX people groups can be reached online. * * Every country shaded by measured internet penetration, with its NAMED carriers - * and dominant social platform on tap. Brief: "all these are missing maps." + * and dominant social platform on tap. One of the data maps this project adds. * * CLONE of gospel-resources/resources-map.vue with the data and bands swapped — * profiles duplicate, the pattern does not get re-derived. Same mobile-first @@ -131,8 +131,8 @@ const rows = ref([]) const selected = ref(null) const aiNoticeOpen = ref(true) // dismissible AI-research disclaimer in the detail sheet const err = ref(null) -// Starts TRUE: the notice must be on screen for the first frame, not switched on after a tick. rega -// measured 7-30s to the first data paint, and for that whole window the map was an empty basemap with +// Starts TRUE: the notice must be on screen for the first frame, not switched on after a tick. +// Measurement showed 7-30s to the first data paint, and for that whole window the map was an empty basemap with // nothing to say it was still working — indistinguishable from a broken embed. const loading = ref(true) @@ -181,7 +181,7 @@ const selectedAdm1 = ref(null) // The DOXA list from pray-tools, the same list Prayer Progress draws. It carries the slug the // detail panel fetches by. The shared pin table (tables/people-group-pins.json) has no slug, // so its dots could not open that panel. -// Dark slate with a white ring (2026-09-28: the red dots looked wrong on the mostly green +// Dark slate with a white ring (red dots looked wrong on the mostly green // map). A neutral dark reads on every fill here, the green/amber/red/grey bands AND India's pale-to-deep // blues, and it carries no "good/bad" meaning the way red does on a map whose red means under 25%. // The white ring keeps it apart from the deepest blue and from the dark basemap. @@ -190,7 +190,7 @@ const uiStore = inject('uiStore', null) const _lang = (() => { const v = inject('lang', null)?.value; return (v && v !== 'en') ? v : null })() // The reader's language for the ENGINE'S OWN labels (the canvas's "Map" name, "Zoom in", attribution…). // This map is built raw, not through useMapInstance, so it must hand the engine that locale itself; -// without it they stayed English under ar on both engines (rega, row 34). Same ladder as +// without it they stayed English under ar on both engines (measured). Same ladder as // useMapInstance's readerLang: ProfileLoader's lang, then profile-config, then ?lang=, then . const readerLang = () => { if (_lang) return _lang @@ -302,8 +302,8 @@ function paintGroups(map) { // installed it, so English from the shipped catalog is the fallback, never a blank or a key. // Carrier and platform names are data and are not translated. // C4 wave 3b: the guard is library/composables/useOptionalT.js now, and the fallback resolves through -// tStatic — the RUNTIME LOCALE first, English as the last resort. exp-shepherd's call as this -// plugin's owner (2026-09-26), on the same reasoning gospel-plugin gave: the bundle already carries +// tStatic — the RUNTIME LOCALE first, English as the last resort. This plugin owns that +// choice, on the same reasoning the other map plugins use: the bundle already carries // all 11 catalogues, so a partner embedding without vue-i18n being served English is a bug, not a // decision. The old enLookup was English-only, which is exactly what that served. // The local fill() is gone with the guard: fillParams applies the same interpolation, except it leaves @@ -565,7 +565,7 @@ onMounted(async () => { paintGroups(map) const geo = await adm1Loaded if (geo && !unmounted) paintAdm1(map, geo) - // ★ CLEARED HERE, NOT ON 'load'. rega measured 7-30s from mount to the first data paint under + // ★ CLEARED HERE, NOT ON 'load'. Measurement showed 7-30s from mount to the first data paint under // SwiftShader: the style fires 'load' early, while the shaded countries, the adm1 provinces and // the 2,105 dots all arrive later. Clearing on 'load' would retire the notice during exactly the // wait it exists to explain, leaving the reader with an empty basemap and no reason for it. @@ -603,7 +603,7 @@ const groupOpen = computed(() => !!uiStore?.selectedPeopleGroup) useShadowStyles( // ⚠ THE MAP MUST FILL ITS HOST, NOT THE VIEWPORT. This element had NO :host rule at all, so a // custom element defaults to display:inline with no height of its own, and .gm's absolute inset:0 - // resolved against whatever ancestor happened to be positioned. rega measured the result in the + // resolved against whatever ancestor happened to be positioned. The result was measured in the // /embed-test re-shoot at 1440: a 1198x900 canvas inside a 1198x560 embed card — ~340px, the // attribution among it, drawn below the card and clipped. Same class as the board's, and the same // fix it already carries: height:100% so a height-bounded slot decides, min-height as a floor so an @@ -612,7 +612,7 @@ useShadowStyles( // .gm below is position:absolute;inset:0, and absolute positioning resolves against the nearest // POSITIONED ancestor — which :host was not. So on a partner page .gm resolved against whatever the // PARTNER happened to have positioned, and the map sized itself to that rather than to this element. - // rega measured it in the hostbox run on ca07fc3c8: the element was CORRECT at 420px in a 420px box, + // It was measured in a host-box run: the element was CORRECT at 420px in a 420px box, // while the canvas inside it stayed 900px and painted the pill and the attribution 478px below the // box (538px in a 360px box), over the partner's own text. Giving the host a HEIGHT without making it // a CONTAINING BLOCK fixes the box and not what is drawn inside it. @@ -635,7 +635,7 @@ useShadowStyles( // control rail by construction: MapToolbar is inset-inline-end:3px with 32px // buttons, so ANY box reaching right:8px intersects it at every viewport. The // rail's z-index:10 beats this z-index:4, so the buttons stayed clickable and - // the defect read as "the legend underlaps the controls" — reported 3x. + // the defect read as "the legend underlaps the controls". // The fix imitates the shared SemanticTreeLegend, which has always done it // correctly: `left:8px; width:var(--map-legend-width,380px)`. Bounded and // left-anchored cannot reach the right rail, so the two can never overlap diff --git a/plugin-designs/cities-internet/data-tables.vue b/plugin-designs/cities-internet/data-tables.vue index bb2606369..ab09c8d5b 100644 --- a/plugin-designs/cities-internet/data-tables.vue +++ b/plugin-designs/cities-internet/data-tables.vue @@ -5,15 +5,14 @@ * @description Four validated research tables, one tab each, with sortable and filterable columns, CSV and JSON * export, and each table's caveats rendered in the UI rather than hidden in a footnote. * - * Four validated Tabulator tables from the flight's research corpora, each with + * Four validated Tabulator tables from the research corpora, each with * sortable/filterable columns, CSV+JSON export, and its caveats rendered IN the UI. * - * > design note 2026-08-01: "all the tabulator data and trees for all the multiple - * > various tabulator tables for all this data all organized in list format with - * > full granularity." + * Design intent: present all the tabulator data and trees for the various tables + * in list format, at full granularity. * * The tables are produced by library/scripts/research/build-tabulator-tables.mjs - * (the M+V of IEMV) — flat scalar rows, one row per fact, validated before write. + * — flat scalar rows, one row per fact, validated before write. * * WHY THE CAVEATS RENDER: a list view strips context. Someone reading * "Internet 12.6%" needs to know it is a NATIONAL figure, and someone reading a @@ -37,14 +36,14 @@ const assetsBase = computed(() => resolveAssetsBase(profileConfig.value)) // i18n is OPTIONAL: useI18n() throws on a host that never installed it, so English from the // shipped catalog is the fallback, never a blank or a key. Region and country names are data. // C4 wave 3b: the guard is library/composables/useOptionalT.js now, and the fallback resolves through -// tStatic — the RUNTIME LOCALE first, English as the last resort. exp-shepherd's call as this -// plugin's owner (2026-09-26), on the same reasoning gospel-plugin gave: the bundle already carries +// tStatic — the RUNTIME LOCALE first, English as the last resort. This plugin owns that +// choice, on the same reasoning the other map plugins use: the bundle already carries // all 11 catalogues, so a partner embedding without vue-i18n being served English is a bug, not a // decision. The old enLookup was English-only, which is exactly what that served. // The local fill() is gone with the guard: fillParams applies the same interpolation, except it leaves // a placeholder for a NULL value where this fill() rendered the string "null". const t = useOptionalT('connectivity') -// NUMERALS ARE HELD fleet-wide (2026-09-26): a locale-following format would switch +// NUMERALS ARE HELD by design: a locale-following format would switch // 'ar' to Arabic-Indic digits. Until that is decided, numbers keep the browser-default format they // had before this pass; only the TEXT is translated. const num = (n) => (Number(n) || 0).toLocaleString() @@ -90,7 +89,7 @@ const table = computed(() => cache.value[current.value?.file] || null) useShadowStyles( // ★ THE TABLE MUST STAY INSIDE ITS HOST BOX — the same defect and the same fix as connectivity-list. // With no :host rule the element is inline with no height, and .ct (position:absolute;inset:0) - // resolved against the partner page's positioned ancestor instead of this element. rega measured + // resolved against the partner page's positioned ancestor instead of this element. Measurement showed // content painting to y=1,698, which is 1,254px BELOW a 420px host box. // .ct already has overflow-y:auto, so containing it is enough to make the table scroll in the box. ':host{display:block;position:relative;width:100%;height:100%;min-height:320px}' + diff --git a/plugin-designs/key-cities/cities-map.vue b/plugin-designs/key-cities/cities-map.vue index d8221d40d..a80a5e34a 100644 --- a/plugin-designs/key-cities/cities-map.vue +++ b/plugin-designs/key-cities/cities-map.vue @@ -3,7 +3,7 @@ * cities-map.vue — THE KEY CITIES GLOBAL MAP. * * Every located population centre as a POINT, sized by how many people groups it - * holds. Brief: "all these are missing maps." + * holds. One of the data maps this project adds. * * POINTS, NOT COUNTRY SHADING — this is the one dataset with real coordinates * (1,646 clusters, 277 of them gazetteer-named), so shading a country would throw @@ -86,7 +86,7 @@ async function load() { const res = await fetch(`${assetsBase.value}/tables/key-cities.json`) if (!res.ok) throw new Error(`key-cities table not found (${res.status})`) rows.value = (await res.json()).rows || [] - // CITY-STAR LAYER (Brief: "better city display"). Fetched SEPARATELY — never a + // CITY-STAR LAYER (a richer city display). Fetched SEPARATELY — never a // static import, which would inline the table into the IIFE bundle (that trap // once took two bundles to 2.0/2.9MB). Failure here must NOT break the base map, // so it is caught: the city layer is an ENHANCEMENT, not a dependency. diff --git a/plugin-designs/key-cities/data-tables.vue b/plugin-designs/key-cities/data-tables.vue index 3e608f6e8..ffaf544e4 100644 --- a/plugin-designs/key-cities/data-tables.vue +++ b/plugin-designs/key-cities/data-tables.vue @@ -2,15 +2,14 @@ /** * data-tables.vue — the CITIES DATA list view: every research table, one tab each. * - * Four validated Tabulator tables from the flight's research corpora, each with + * Four validated Tabulator tables from the research corpora, each with * sortable/filterable columns, CSV+JSON export, and its caveats rendered IN the UI. * - * > design note 2026-08-01: "all the tabulator data and trees for all the multiple - * > various tabulator tables for all this data all organized in list format with - * > full granularity." + * Design intent: present all the tabulator data and trees for the various tables + * in list format, at full granularity. * * The tables are produced by library/scripts/research/build-tabulator-tables.mjs - * (the M+V of IEMV) — flat scalar rows, one row per fact, validated before write. + * — flat scalar rows, one row per fact, validated before write. * * WHY THE CAVEATS RENDER: a list view strips context. Someone reading * "Internet 12.6%" needs to know it is a NATIONAL figure, and someone reading a From 06a48a9b429a1ac3a02b89c10220129c7e9c9006 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Thu, 1 Oct 2026 00:21:17 +0000 Subject: [PATCH 2/4] plugin-designs: neutral comments in shared/ownerless maps Rewrite code comments across doxa-research-map, upg-neighbor, research-map-plus-grid, rudder-voice, people-groups-grid, big-picture, prayer-walk-planner and all-people-groups to drop internal role names from measurement and provenance notes, keeping each technical fact. Comments only; behaviour unchanged. --- .../all-people-groups/all-people-groups.vue | 2 +- plugin-designs/big-picture/big-picture.vue | 4 +- .../doxa-research-map/research-map.vue | 62 +++++++++---------- .../scripts/check-clustering-modes.mjs | 2 +- .../scripts/check-language-code-link.mjs | 14 ++--- .../scripts/check-reduced-motion-jumps.mjs | 8 +-- .../people-groups-grid/people-groups-grid.vue | 6 +- .../prayer-walk-planner.vue | 2 +- .../research-map-plus-grid.vue | 2 +- .../scripts/check-i18n-keys-exist.mjs | 4 +- .../scripts/check-linked-vocabulary.mjs | 2 +- .../scripts/check-no-free-identifiers.mjs | 2 +- plugin-designs/rudder-voice/rudder-voice.vue | 8 +-- plugin-designs/upg-neighbor/src/campaigns.vue | 4 +- .../src/composables/useNeighborT.js | 2 +- plugin-designs/upg-neighbor/src/mobilize.vue | 8 +-- .../upg-neighbor/src/whenStyleReady.js | 2 +- 17 files changed, 67 insertions(+), 67 deletions(-) diff --git a/plugin-designs/all-people-groups/all-people-groups.vue b/plugin-designs/all-people-groups/all-people-groups.vue index 1f6e813e0..8d63e81fd 100644 --- a/plugin-designs/all-people-groups/all-people-groups.vue +++ b/plugin-designs/all-people-groups/all-people-groups.vue @@ -194,7 +194,7 @@ const mapData = useMapData({ // all 12,379 features, 3.7 MB of GeoJSON built and re-tiled TWICE (first paint, then the DOXA recolour); // slim, it is 1.25 MB, built once. The popup reads the row by id. The DOXA recolour no longer rebuilds // the 12,379 with all their fields: DOXA pins are a small source of their own drawn on top, and the base -// is re-sent once, slim, WITHOUT them (an invisible twin per DOXA group still cost a draw: rega measured). +// is re-sent once, slim, WITHOUT them (an invisible twin per DOXA group still cost a draw: measured). let rows = [] // the decoded rows; a feature's id is its index here let doxaIds = new Set() // row indexes in the DOXA set (empty until the prayer API answers) let doxaBySlugRop = new Map() // rop3 → { slug, name } for the pray link diff --git a/plugin-designs/big-picture/big-picture.vue b/plugin-designs/big-picture/big-picture.vue index 001487bd5..2c93cf194 100644 --- a/plugin-designs/big-picture/big-picture.vue +++ b/plugin-designs/big-picture/big-picture.vue @@ -146,7 +146,7 @@ watch(textDir, reflectDir) // The host's people-group LIST (library/lists/), handed to both children as the only key of their // profile-config, so nothing else about them changes. Absent = the default list. -// ★ THE LOCALE TRAVELS WITH THE LIST (rega, row 47: big-picture rendered 31 Arabic text nodes +// ★ THE LOCALE TRAVELS WITH THE LIST (measured: big-picture rendered 31 Arabic text nodes // through profile-config against 79 through ?lang=, and check:host-locale-contract measured 402 // against 888). This handed each child ONLY the list, so the one documented channel a partner has // for asking a nested element to speak Arabic — its profile-config — arrived empty of any locale. @@ -155,7 +155,7 @@ watch(textDir, reflectDir) // Threading it costs nothing and is what ProfileLoader would have done had one existed beneath this // composite, which is exactly the (C) failure mode: a composite that BAKES its children in has no // ProfileLoader under it, so it must do that job itself. -// This is ONE identified gap, not a claim to have closed the whole 402/888 difference; rega +// This is ONE identified gap, not a claim to have closed the whole 402/888 difference; a later pass // re-measures. const listConfig = computed(() => { const cfg = {} diff --git a/plugin-designs/doxa-research-map/research-map.vue b/plugin-designs/doxa-research-map/research-map.vue index 55a475787..00ad52feb 100644 --- a/plugin-designs/doxa-research-map/research-map.vue +++ b/plugin-designs/doxa-research-map/research-map.vue @@ -529,7 +529,7 @@ const legendTopVar = computed(() => { // Languages tabs it reserved 56px for a toolbar it never draws, and only those two tabs, because // they are exactly the set showsFlyTools() returns true for. Every other tab took the 14px branch // and looked right, which is why it was reported as two tabs misbehaving. - // MEASURED by rega at 1440x900 on main e1d0bc20: the band from the map's top edge (y 44) to the + // MEASURED at 1440x900 on main e1d0bc20: the band from the map's top edge (y 44) to the // legend card (y 100) is 56px of EMPTY map on both tabs, with no LegendTools anywhere in the strip. // So the gap was dead space, not a toolbar the reader had not registered. const toolsShown = showLegendTools.value && showsFlyTools(activeLegendType?.value ?? activeLegendType) @@ -698,7 +698,7 @@ watch(() => activeTabId?.value, async (newTabId, oldTabId) => { // ★ SCROLL THE TAB BAR, NOT THE PAGE. This was // btn.scrollIntoView({ inline: 'center', block: 'nearest', behavior: 'smooth' }) // and 'nearest' does not mean "do not scroll the page" — it means "scroll every scrollable - // ancestor the least amount needed", and the HOST PAGE is an ancestor. MEASURED by rega's embed + // ancestor the least amount needed", and the HOST PAGE is an ancestor. MEASURED in the embed // sweep: a partner page carrying this map below the fold jumps to y≈640 the moment it mounts, on // a phone, where Simple Research is the default tab. The reader asked for nothing; the page moved // under them. @@ -788,10 +788,10 @@ const mapData = useMapData({ // then force it visible (country search stays on the current tab — d7e741b — so // the polygon layers, normally hidden off the Regions tab, must be shown here). // ★ EVERY region paint write goes through this, or the pre-warm above is undone the first time a -// highlight is cleared. Found by cross-reading exp-shepherd's country-posters port (73438b43b), which +// highlight is cleared. Found by cross-reading the country-posters port (73438b43b), which // wraps all eighteen of its clears while mine still wrote nine RAW constants — a raw value makes the // property constant again, so the next highlight recompiles the shader variant the pre-warm exists to -// have already compiled. rega measured 0 ms on a fresh tab; a reader who clears a selection first was +// have already compiled. Measurement showed 0 ms on a fresh tab; a reader who clears a selection first was // paying it again, which no run so far has exercised. // regionIdle now comes from the library (useLegendMapBridge), which already called it — this file // was defining a copy and then passing it in. See check:region-paint-single-source. @@ -932,7 +932,7 @@ const legend = useLegendData({ // ★ REMOVED: provide('legendRows', legend.rows). useLegendData returns `items`, never `rows`, so // this provided undefined from the day it was written, and nothing in the repo injects 'legendRows' // — LegendDesktop and LegendMobile read the `legend` key instead, which is what the comment above -// used to claim was happening. exp-shepherd found the same line in countries-map, where it was not +// used to claim was happening. the same line was found in countries-map, where it was not // merely dead: it made Export poster throw (NE-17, their d6916e05e). A provide that is undefined and // a comment that describes a contract nobody implements are worse together than either alone, so // both go. If a consumer ever needs these rows, it should provide legend.items and say so then. @@ -1117,14 +1117,14 @@ provide('getActivePinColor', (properties) => { // already (fam:/lang:/dial: + region:/block:/country: + bloc:/cluster:/pg:/pgic:), // so this returns null for them and zoomToLegendRow falls back to node.filter. // ─── ONE WRITER FOR THE REGION POLYGONS ────────────────────────────────────── -// ★ MEASURED (rega, main 373b7979b): a single WAGF row click produced NINE regions-* paint writes — +// ★ MEASURED (main 373b7979b): a single WAGF row click produced NINE regions-* paint writes — // fill-opacity, line-color and line-width, three times each inside ~110 ms — because two paths painted // the same highlight from DIFFERENT sources: onSemanticTreeSelect from node.isoCodes, applyDimFilter // from mapLayers.regionIsoMap, each triggering the other through mapStore. Two sources for one visual // is not just wasted work; it is how they drift, and it already cost a debugging cycle when we had to // establish WHICH of them had cleared the highlight. // -// ★ AND THE IDLE STATE IS DATA-DRIVEN ON PURPOSE. rega measured the row click compiling a new shader +// ★ AND THE IDLE STATE IS DATA-DRIVEN ON PURPOSE. Measurement showed the row click compiling a new shader // variant: 5.5 s on MapLibre, 11.1 s on Mapbox (SwiftShader), because that click was the first moment // these three properties stopped being constants. Same defect as the pins, same fix: the idle value is // ['case', ['has', 'iso_3166_1_alpha_3'], x, x] — both branches identical, so not one pixel changes — @@ -1143,7 +1143,7 @@ function prewarmRegionPaint(m) { // Was a THIRD local copy of the idle expression, under a different name — byte-identical body. // The library's regionIdle replaces it exactly. const wrap = regionIdle - // ★ SKIP WHAT IS ALREADY DATA-DRIVEN, and note the test is not "is it an array". exp-shepherd wrote + // ★ SKIP WHAT IS ALREADY DATA-DRIVEN, and note the test is not "is it an array". The country-posters port wrote // their copy to skip any array, reasoning that an expression is already data-driven so there is no // variant to warm. That is right for this layer — line-color arrives as a match on a feature property // — but it is right by accident: a ZOOM expression like ['interpolate',['linear'],['zoom'],…] is also @@ -1163,10 +1163,10 @@ function prewarmRegionPaint(m) { // exactly that reverse. Mapbox then classifies the property as composite and reaches for an // interpolation factor the expression cannot supply — the class of // this.expression.interpolationFactor is not a function - // rega saw once on Mapbox at L54, on the clear → other-row path. A missed pre-warm costs a frame; an + // a run saw it once on Mapbox at L54, on the clear → other-row path. A missed pre-warm costs a frame; an // illegal paint costs the layer, so when the two rules disagree this one wins. // - // exp-shepherd's port skips ANY array and is immune to this by accident; the difference between us + // the country-posters port skips ANY array and is immune to this by accident; the difference between us // was never about zoom expressions being data-driven, it was about which mistake is recoverable. const readsZoom = (e) => Array.isArray(e) && (e[0] === 'zoom' || e.some(readsZoom)) const warm = (layer, prop) => { @@ -1185,9 +1185,9 @@ function prewarmRegionPaint(m) { function paintRegionScope(m, isoCodes) { if (!m || !m.getLayer('regions-fill')) return - // ★ CANONICAL FIRST, OR THE COMPARE BELOW IS A LIE (rega, L43: still 9 writes per click, not 3). + // ★ CANONICAL FIRST, OR THE COMPARE BELOW IS A LIE (measured at L43: still 9 writes per click, not 3). // The two sources build the same region from different lists — node.isoCodes and - // mapLayers.regionIsoMap[slug] — and they do not agree on ORDER. rega had already told me that in + // mapLayers.regionIsoMap[slug] — and they do not agree on ORDER. The measurement had already shown that in // the very first stack trace ("a case over ['IND',…]" then "a case over ['MYS',…], a different // literal order") and I wrote a JSON-string compare anyway, which can never match two orderings of // the same set. Sorting and de-duplicating makes the expression a function of the SET, which is what @@ -1755,7 +1755,7 @@ async function ensureRegionsLoaded() { if (regionsData && map.value) { mapLayers.addRegionsLayer?.(regionsData, 'doxa-regions') // ★ PRE-WARM HERE, which is the only moment that helps. These layers are added on first visit - // to the Regions tab, and rega measured the first ROW click paying 5.5 s (MapLibre) / 11.1 s + // to the Regions tab, and measurement showed the first ROW click paying 5.5 s (MapLibre) / 11.1 s // (Mapbox) of shader compile because that click was when their paint first became data-driven. // Making the paint data-driven at layer-add moves that compile here, where a 6.4 MB GeoJSON is // already loading, instead of into the middle of a gesture. @@ -1904,7 +1904,7 @@ function pinBaseAlpha() { // matchExpr: an expression to dim by, null to clear dimming, undefined to re-apply what is current // (which is what the slider's watcher needs — it changes the scale, not the selection). // ★ THE UNDIMMED VALUE IS DATA-DRIVEN TOO, AND THAT IS THE WHOLE POINT (reported bug: "the research map -// isn't connecting with the legend"; rega's CPU profile, 2026-09-28). A legend click on a big affinity +// isn't connecting with the legend"; a CPU profile). A legend click on a big affinity // row appeared to do nothing for ~2 s. It was not the echo guard, not the legend's DOM (34 rows before, // 34 after) and not expression evaluation (the JS filter scan over 2,106 features against a 700-id list // measures 14 ms). It was ONE task of 3.2-3.5 s whose self time was getShaderParameter + getProgram- @@ -1918,7 +1918,7 @@ function pinBaseAlpha() { // and the program compiles during boot alongside every other one. A selection then only re-uploads // attribute values, which is the cheap path. // -// The trade, stated: boot compiles one more program (tens of ms on a real GPU; rega measured seconds +// The trade, stated: boot compiles one more program (tens of ms on a real GPU; measurement showed seconds // only because that box rasterises on the CPU via SwiftShader). Paying it at load beats freezing the // map mid-gesture, and the variant was going to be compiled on first interaction anyway. function applyPinOpacity(m, matchExpr) { @@ -1928,7 +1928,7 @@ function applyPinOpacity(m, matchExpr) { // ['has','uniqueId'] reads a feature property, which is what makes it data-driven; both outcomes are // `a`, so a pin without the property renders exactly as before. const value = _pinMatchExpr ? ['case', _pinMatchExpr, a, 0] : ['case', ['has', 'uniqueId'], a, a] - // ★ ONE WRITE PER DISTINCT VALUE. rega counted circle-opacity rewritten 4-8 times for a single click + // ★ ONE WRITE PER DISTINCT VALUE. Measurement counted circle-opacity rewritten 4-8 times for a single click // (+1.52, +1.57, +1.94, +5.17 s): the selection handler, the glow sync and the slider watcher all end // up here, and each write re-uploads the per-feature attribute. Every writer already routes through // this function, so the collapse belongs here and nowhere else. Compared as text because the value is @@ -2325,7 +2325,7 @@ watch(() => profileConfig?.value?.externalFilters, (raw) => { try { // ★ AN EMPTY VALUE THE HOST DID NOT SET MUST NOT CLEAR WHAT THIS PAYLOAD JUST LIT. This is the // The report "the research map isn't connecting with the legend" on the WAGF Regions tab, found by - // rega's stack trace (l40): the highlight painted at +51 ms and was wiped at +438 ms by + // a stack trace (l40): the highlight painted at +51 ms and was wiped at +438 ms by // clearAllHighlights, reached from applyDimFilter({kind:null}) through the selectedRegion watcher — // so selectedRegion had gone FALSY while externalRegion still read "asia". // @@ -2426,7 +2426,7 @@ watch(() => profileConfig?.value?.externalFilters, (raw) => { // ★ EACH HOOK IS ALSO HELD LOCALLY, so the unmount path can release ONLY WHAT IS STILL OURS. // Two of these maps can share a page (research-map-plus-grid composes one beside a grid, and the // gallery can show another): B mounts and overwrites A's hooks, then A unmounts. An unconditional -// delete would strip the hooks belonging to the map still on screen, and rega would report a verify +// delete would strip the hooks belonging to the map still on screen, and it would report a verify // hook missing on a map that is perfectly healthy — a false failure costing more to chase than this // costs to write. Declared out here rather than inside the block below because a const inside it is // invisible to onBeforeUnmount. Same pattern gospel used in d3597f3d1. @@ -2534,7 +2534,7 @@ function emitFilterState() { // // The NAME still goes out because this map's own legend selects by name; the CODE goes out for // anyone matching rows. Both halves get the form they can actually use. - // ★ THE LOOKUP HAS TO MATCH THE WAY THE LEGEND BUILT THE LABEL (rega, 2026-09-26, main 49992a5d: + // ★ THE LOOKUP HAS TO MATCH THE WAY THE LEGEND BUILT THE LABEL (measured on main 49992a5d: // MapLibre, BOTH locales, Languages > Language > "Arabic" -> languageCode:"" -> grid 2,107 -> 0). // // WHAT I GOT WRONG. This found a row whose language LABEL equals the selected name with `===`. @@ -2543,7 +2543,7 @@ function emitFilterState() { // splitting the API label at the comma. MEASURED against the live source (2,107 rows, all 2,107 // carrying primary_language as {value,label}): there is NO row whose label is "Arabic". What // exists is "Arabic, Sudanese", "Arabic, Levantine", "Arabic, Gulf", ... So the exact match could - // never hit, in any locale — which is why rega saw it fail identically in en and ar, and why the + // never hit, in any locale — which is why it failed identically in en and ar, and why the // locale fix that prompted this code was right about the DISEASE and wrong about this line. // // This is the derived-value trap, one tier down from where I last wrote it up: a value that @@ -2586,7 +2586,7 @@ function emitFilterState() { const detail = { region: mapStore?.selectedRegion || '', religion: religionName, - // ★ A DIALECT'S NAME COMES FROM ITS LABELS, NOT ITS KEY (rega, row 43 case 3: this reported + // ★ A DIALECT'S NAME COMES FROM ITS LABELS, NOT ITS KEY (a measured case: this reported // ", Afro-Asiatic__Arabic__Sudanese"). `selectedDialect.key` is the TREE NODE ID — // family__baseLang__dialect — and the watcher fifteen lines above says so in as many words; // I read that comment and then used the key as a display name anyway. Worse, selectedLanguage @@ -2605,7 +2605,7 @@ function emitFilterState() { languageCodes: langCodes, } // ★ AN EMPTY REPORT AFTER A NON-EMPTY ONE IS AMBIGUOUS, SO IT IS NOT SENT IMMEDIATELY. - // rega, row 43 case 3 at 52eeb0db: coalescing worked — one event per click — and in 3 of 4 runs + // measured at 52eeb0db: coalescing worked — one event per click — and in 3 of 4 runs // that one event was EMPTY, so the grid stayed at 2,107. The cascade behind a dialect click // passes through a fully-cleared state: mapStore.selectLanguage() sets selectedDialect = null // BEFORE it sets the language, and the clear was the last write my watcher saw. The settle timer @@ -2642,7 +2642,7 @@ function emitFilterState() { host.dispatchEvent(new CustomEvent('map-filtered', { detail, bubbles: true, composed: true })) } -// ★ ONE EVENT PER SETTLED SELECTION (rega, row 43 case 3: a dialect click narrowed the grid in +// ★ ONE EVENT PER SETTLED SELECTION (a measured case: a dialect click narrowed the grid in // only ONE of four runs, with a correct languageCode in all four). // // THE CAUSE IS A BURST MEETING A GUARD. Clicking a dialect does not change one store value; it @@ -2665,7 +2665,7 @@ const EMIT_SETTLE_MS = 60 // of delay on a clear — about a fifth of a second, well under what a reader notices, and far below // the composite's own 1.2s push window so it cannot collide with that. // ★ A CEILING ON BELIEVING A CLEAR — NOT A GUESS AT HOW LONG THE CASCADE TAKES. -// rega, row 43 case 3 at 835ec1ac: the retry budget catches the transient on MapLibre and NOT +// measured at 835ec1ac: the retry budget catches the transient on MapLibre and NOT // reliably on Mapbox (and not at all in ar/mapbox), because 3 x 60ms is still a duration I picked // without being able to measure the thing it has to outlast. That is the THIRD time I have tuned a // number on one machine for this one defect, so the number's JOB changes rather than its value. @@ -2682,7 +2682,7 @@ let _emptyWaitStartedAt = 0 let _lastEmitWasFilled = false function emitFilterStateSettled() { // ★ THE ECHO GUARD MUST BE READ WHEN THE CHANGE HAPPENS, NOT WHEN THE TIMER FIRES. - // rega, row 50: a region row click emitted {region:"asia"} and then an EMPTY event, on both + // measured: a region row click emitted {region:"asia"} and then an EMPTY event, on both // engines. It passed only because the composite's 1.2s push window happened to swallow the // second one — a pass that depends on a swallow is not a pass. // @@ -2809,7 +2809,7 @@ function applyFitSlugs(slugs) { : null // ★ REDUCED MOTION DRIVES THE MAP DIRECTLY, and that is not belt-and-braces. - // MEASURED by rega with the browser's prefers-reduced-motion: reduce set: the framing move still + // MEASURED with the browser's prefers-reduced-motion: reduce set: the framing move still // animated for ~5s on MapLibre and ~6.7s on Mapbox — essentially the same as without it, where a // jump is ~0ms. So the preference was being honoured in THIS file and thrown away downstream: // useMapFly's flyToCoords(coords, zoom) takes NO options argument at all, so the `{ duration: 0 }` @@ -2840,7 +2840,7 @@ function applyFitSlugs(slugs) { // // The checkbox force-set 'mst' "regardless of what's in the store", and the picker wrote to a // property mapStore never declared — so choosing Native drew nothing, and had it worked, one tick -// of the checkbox would have snapped it back to MST anyway. MEASURED as inert by exp-shepherd; the +// of the checkbox would have snapped it back to MST anyway. MEASURED as inert; the // second half is what makes fixing only the picker the wrong fix, because the control would have // worked until the reader touched the other one. // @@ -2916,7 +2916,7 @@ async function onMapReady(normalizedPeopleGroups) { // added with a CONSTANT "circle-opacity": 1 (see addLanguageFamilyLayer), and applyPinOpacity is // otherwise first reached from a legend click — so without this line the expression shape below is // only ever the CLEARED state and the first selection is still the moment the variant is compiled, - // which is the 3.2-3.5s freeze rega profiled. Found by reading the built bundle rather than the + // which is the 3.2-3.5s freeze seen in profiling. Found by reading the built bundle rather than the // source: the addLayer constant is right there in the shipped JS. // matchExpr is left UNDEFINED on purpose — "re-apply what is current" — so a selection already // restored from a share-link hash is preserved instead of being cleared at boot. @@ -3022,7 +3022,7 @@ const reannounceInfoPending = () => { if (!appReady.value && !mapError.value) an watch(mapError, (e) => { if (e) announceInfoPending(false) }) // ★ THE PRAYER LINE'S TABLE IS FETCHED AFTER THE MAP MOUNTS, when the browser is idle, not when a print starts: the // print waits at most 3 s for it (openPoster), and on a slow phone network a fetch begun at the tap missed that window -// (rega: the line dropped in 1 of 2 runs). loadPacketStrings caches the promise, so the print reads it at once; it +// (the line dropped in 1 of 2 runs). loadPacketStrings caches the promise, so the print reads it at once; it // never rejects, and a failed fetch is retried by the print. 48 KB gzipped, once per page. onMounted(() => { const prefetch = () => import('@map/packet/packetStrings.js').then(({ loadPacketStrings }) => loadPacketStrings(resolveAssetsBase(profileConfig?.value))).catch(() => {}) @@ -3135,7 +3135,7 @@ onMounted(async () => { window.addEventListener('resize', _resyncScrollZoom) }) -// ★ THE MAP IS TORN DOWN NO MATTER WHAT ELSE FAILS. rega's heap snapshots (leak-722ac7789) found +// ★ THE MAP IS TORN DOWN NO MATTER WHAT ELSE FAILS. heap snapshots (leak-722ac7789) found // every unmounted research map still alive, held by window.__doxaLogoOwner -> Map -> div.rm-map-canvas // -> ShadowRoot -> app, and that global is released only when the map's 'remove' event fires. So a // single throw anywhere in this hook stranded the entire application in memory, one copy per mount. @@ -3158,7 +3158,7 @@ onBeforeUnmount(() => { step(() => selectedPin.cleanup?.()) step(() => mapStore.unregisterMap?.(mapId)) // Every verify hook this component plants is an arrow closing over it, so each one left behind - // keeps the component, its shadow root and the whole app alive (rega, leak-722ac7789). They are + // keeps the component, its shadow root and the whole app alive (leak-722ac7789). They are // released as a set: they are installed as a set, and releasing three of four leaks just as much // as releasing none. Each is checked before deleting so a later mount's hook is never removed. // Written out one per line, not looped over an array of names, SO THE CHECK CAN READ IT. diff --git a/plugin-designs/doxa-research-map/scripts/check-clustering-modes.mjs b/plugin-designs/doxa-research-map/scripts/check-clustering-modes.mjs index 0804c46c9..6f4e22a5c 100644 --- a/plugin-designs/doxa-research-map/scripts/check-clustering-modes.mjs +++ b/plugin-designs/doxa-research-map/scripts/check-clustering-modes.mjs @@ -4,7 +4,7 @@ * different. A control that does nothing is worse than a control that is absent: it tells the * reader the map cannot do what it can. * - * THE DEFECT, MEASURED BY exp-shepherd AND CONFIRMED HERE. The side menu offers four clustering + * THE DEFECT, MEASURED AND CONFIRMED HERE. The side menu offers four clustering * options; choosing "Native" changed nothing on the map. Two separate reasons, and only fixing both * makes the control real: * diff --git a/plugin-designs/doxa-research-map/scripts/check-language-code-link.mjs b/plugin-designs/doxa-research-map/scripts/check-language-code-link.mjs index 53d07cf44..1c0cda10c 100644 --- a/plugin-designs/doxa-research-map/scripts/check-language-code-link.mjs +++ b/plugin-designs/doxa-research-map/scripts/check-language-code-link.mjs @@ -2,7 +2,7 @@ /** * check-language-code-link.mjs — the map's language selection must reach the grid, or narrow nothing. * - * THE BUG (rega, 2026-09-26, main 49992a5d, MapLibre, BOTH locales). Languages > Language > + * THE BUG (measured on main 49992a5d, MapLibre, BOTH locales). Languages > Language > * "Arabic": the map emitted `map-filtered` with {language:"Arabic", languageCode:""}, the composite * handed the grid an empty code, and the grid went 2,107 -> 0. An empty grid reads as "no results", * which is the worst shape a wiring bug can take — the reader believes the data. @@ -48,11 +48,11 @@ * E. no tier may produce a value that selects zero rows. That is the user-visible invariant and * it is asserted directly, not inferred. * F. a DIALECT reports a NAME and not a tree node id, and the emitter sends ONE event per - * settled selection rather than a burst. Both from rega's row 43 case 3. + * settled selection rather than a burst. Both from a measured case. * G. that ONE event is not the cascade's transient EMPTY state. Same case, second measurement: * the coalescing worked and the single event was EMPTY in 3 of 4 runs. * - * NO NETWORK, NO BROWSER (Playwright is rega's alone). The fixture is committed and was taken from + * NO NETWORK, NO BROWSER (Playwright is the browser-QA lane's alone). The fixture is committed and was taken from * the live source; refresh it with --refresh-fixture when the source's language set changes. * * NEGATIVE-TESTED 2026-09-26, each FAILS: @@ -221,7 +221,7 @@ if (matchesLanguage) { } // ── E. the dialect tier: a name, and one event ─────────────────────────────────────────────── -// rega, row 43 case 3, on BOTH engines in BOTH locales: clicking "Arabic, Sudanese" emitted the +// Measured on BOTH engines in BOTH locales: clicking "Arabic, Sudanese" emitted the // right languageCode and narrowed the grid in only ONE of four runs, while the `language` slot read // ", Afro-Asiatic__Arabic__Sudanese". // THE NAME: selectedDialect.key is the TREE NODE ID (family__baseLang__dialect) and @@ -258,7 +258,7 @@ if (matchesLanguage) { } // ── G. an empty report after a filled one is re-taken, and the re-take is BOUNDED ──────────── -// rega, row 43 case 3 at 52eeb0db: coalescing landed — one event per click — and in 3 of 4 runs +// measured at 52eeb0db: coalescing landed — one event per click — and in 3 of 4 runs // that one event was EMPTY, so the grid stayed at 2,107. The cascade behind a dialect click passes // through a fully-cleared store state (mapStore.selectLanguage sets selectedDialect = null BEFORE // setting the language), and the settle timer fired inside it. @@ -272,7 +272,7 @@ if (matchesLanguage) { if (!/_lastEmitWasFilled/.test(src) || !/const isEmpty/.test(src)) { fails.push('G research-map.vue no longer guards an all-empty report. A dialect click passes through a fully-cleared store state, so the settled read can be taken mid-cascade and ship {language:"",languageCode:""} — which the composite correctly reads as "the reader cleared everything".') } else if (!/EMPTY_SETTLE_CEILING_MS/.test(src)) { - // ★ THE BOUND'S SHAPE CHANGED AND THE INVARIANT DID NOT. It used to be a retry COUNT; rega + // ★ THE BOUND'S SHAPE CHANGED AND THE INVARIANT DID NOT. It used to be a retry COUNT; it was // measured that 3 x 60ms catches the cascade on MapLibre and not on Mapbox, so the count became // a TIME CEILING — the difference being what the number is FOR. A count is a guess at how long // the cascade takes, which cannot be known from here; a ceiling is how long before a clear is @@ -285,7 +285,7 @@ if (matchesLanguage) { } // ── H. the echo guard survives the coalescing ──────────────────────────────────────────────── -// rega, row 50: a region click emitted the selection and then an EMPTY event, passing only because +// Measured: a region click emitted the selection and then an EMPTY event, passing only because // the composite's 1.2s push window swallowed the second. emitFilterState has always opened with // `if (applyingExternal) return` — a change pushed DOWN by the host is not a change to report back // up — and that worked while the emit ran synchronously inside the watcher. Debouncing moved the diff --git a/plugin-designs/doxa-research-map/scripts/check-reduced-motion-jumps.mjs b/plugin-designs/doxa-research-map/scripts/check-reduced-motion-jumps.mjs index cb22b9a25..0ad4f7440 100644 --- a/plugin-designs/doxa-research-map/scripts/check-reduced-motion-jumps.mjs +++ b/plugin-designs/doxa-research-map/scripts/check-reduced-motion-jumps.mjs @@ -5,7 +5,7 @@ * ★ A READER OF THIS MAP IS PHOTOSENSITIVE. This is not a polish item: a camera that sweeps the globe every * time a list is filtered is the strobe class this repo has already paid for once. * - * THE DEFECT, measured by rega in a real browser with the preference set: the framing move still + * THE DEFECT, measured in a real browser with the preference set: the framing move still * animated for ~5.0s on MapLibre and ~6.7s on Mapbox — indistinguishable from no preference at all, * where a jump is ~0ms. The preference WAS being read correctly in research-map.vue and then thrown * away one layer down: useMapFly's `flyToCoords(coords, zoom)` takes NO options argument, so the @@ -13,13 +13,13 @@ * options)` does accept one — two functions in one file, different signatures, and nothing at the * call site to show it. * - * ★ WHY THIS RUNS WITHOUT A BROWSER, WHICH IS THE POINT. rega found it by watching movestart → - * moveend for six seconds; only rega can do that, and only occasionally. What can be checked any + * ★ WHY THIS RUNS WITHOUT A BROWSER, WHICH IS THE POINT. it was found by watching movestart → + * moveend for six seconds; only a real browser can do that, and only occasionally. What can be checked any * time, in milliseconds, is the DECISION: given the preference, which camera call does the code * make? So this lifts the real camera block out of the SFC, runs it against a mocked matchMedia and * a recording map, and asserts the call that comes out. * - * It cannot prove the engine honours duration 0 — that is rega's half. It proves we ASK for a jump, + * It cannot prove the engine honours duration 0 — that is the browser half. It proves we ASK for a jump, * which is the half that was wrong. * * ASSERTIONS: diff --git a/plugin-designs/people-groups-grid/people-groups-grid.vue b/plugin-designs/people-groups-grid/people-groups-grid.vue index 57ceeee08..bb950f5d0 100644 --- a/plugin-designs/people-groups-grid/people-groups-grid.vue +++ b/plugin-designs/people-groups-grid/people-groups-grid.vue @@ -257,7 +257,7 @@ const filtersBackdrop = computed(() => { }) const prayBaseUrl = computed(() => props.prayBaseUrl || cfg.value.prayBaseUrl || 'https://pray.doxa.life') // ★ THE URL IS A SOURCE OF TRUTH FOR THE DATA TOO, not just for the chrome. -// MEASURED by rega at ?lang=ar and ?lang=es: this grid's CHROME translated and its DATA stayed +// MEASURED at ?lang=ar and ?lang=es: this grid's CHROME translated and its DATA stayed // English — country names, affinity names, religion labels — because the `&lang=` on the fetch was // built from props and profile-config ONLY. A reader who asked for Arabic got Arabic buttons around // English content, which reads as a half-finished translation rather than the wiring bug it is. @@ -420,7 +420,7 @@ const t = computed(() => { const EAGER_IMAGES = 5 const truthy = (v) => !(v === false || v === 'false' || v === '0' || v === 0) -// ★ THE PRESET'S KEYS WERE NEVER REACHING THESE (rega RQ20). The "driven" preset asks for +// ★ THE PRESET'S KEYS WERE NEVER REACHING THESE (measured, RQ20). The "driven" preset asks for // show-search:false and show-filters:false and the page rendered both anyway, with 0 console // errors — because nothing was failing. ProfileLoader PROVIDES profile-config; it does not bind // its keys as props. So props.showSearch stayed at its default of true and the preset was inert. @@ -1153,7 +1153,7 @@ onMounted(() => {