dx-base measured two defects in the A8 draft for text that goes public:
- Links into the private DX Life repo answer 404 to anyone without an account. The live
example is now plain words (README, DEPLOY), and the clone line points at the public repo
(doxa-open/doxa-maps, as DEPLOY already did). DEPLOY's "three ways" becomes the two routes;
the CDN route is retired.
- The web folder row said 536 files, 76 MiB. The folder is 855 files, 119.2 MiB. New
check:readme-size re-measures public/dx-maps and fails when the row is more than 10% off,
printing the line to paste. It passes at 855/119; the old numbers fail.
Rudder was measured slowing after about 1,400 words while a Tauri build
ran. The word count is incidental — it is a proxy for how long the build had
been going. The speech model runs on the CPU (backend/rudder-engine starts it
with --device cpu), and a Rust build saturates every core, so at equal priority
it starves the one process whose latency a person can hear.
Three changes, and the direction of the first is forced rather than chosen:
1. internal/desktop-build.mjs nices the whole build tree to 10, through the one
run() helper every step goes through, so cargo, rustc and the linker inherit
it. We nice the COMPETITOR because an unprivileged process cannot raise its
own priority on Linux — a negative nice needs CAP_SYS_NICE — so "promote the
ASR" would fail with EPERM. If nice(1) is missing the build still runs and
says so, because a silent fallback would look exactly like the fix working.
2. cargo is capped at cores-1. nice decides who wins a CONTESTED core; it does
not stop the build taking all of them, and a fully subscribed machine still
adds scheduling latency to the audio path. An explicit CARGO_BUILD_JOBS is
honoured rather than overridden.
3. yieldCPU reports its error instead of discarding it. It was
`_ = syscall.Setpriority(...)`, which cannot fail visibly — a call that
silently does nothing is indistinguishable from one that worked, and this one
guards something audible.
Also, one real O(n) in the widget, found while checking studio's answer that the
collapsed pill already shows the last words: sendActivity split the ENTIRE draft
on every activity tick to take five words. Measured at 3,000 words: 1.61ms per
tick against 0.051ms for a bounded tail, 31x, with byte-identical output.
Verify the priority work with `ps -o ni=` on the running cargo processes, never
by any of these calls returning.
Two halves, Node only. The helper, against fake responses: a real WebP
is accepted by type or by its bytes; a host's 200 fallback page is
refused as a raster and as a source; HTML labelled octet-stream is
refused; a 404 and a network error are misses for the raster; a network
error on the source is thrown as itself. The callers: neither
usePosterPrints nor PosterWall may fetch posters/ directly again, since
each once carried its own copy and a guard in one did not reach the other.
Poison-tested: restoring the old accept-anything fetch fails 3 checks,
and PosterWall's direct fetches failed the caller check before its switch.
gates:pre: PASS 67, FAIL 0.
PosterWall carried its own copy of the poster fetch, so the fallback-page
guard added to usePosterPrints did not reach it: a missing .webp answered
200 text/html by a host was still handed to the print dialog as the image.
It now uses fetchPosterRaster and fetchPosterSource. A thrown .webp fetch
is still a miss that falls through to the source, and a missing source
still reads "poster not found (<status>)".
On a drop-in host's dev server a missing posters/<id>.webp answered
200 text/html (the app's own page), and export handed that page to the
print dialog as the image. The .html source path had the same hole: the
rasteriser lifts the first <svg> on whatever page it is given.
library/packet/poster-fetch.js now fetches both. A raster counts only if
it is an image: by content-type, or by its first bytes when a host labels
a WebP application/octet-stream. A source counts only if it is a poster
document (its class="stage" element); a 200 that is not one reports 404.
A thrown fetch on the raster stays a miss, so the source fallback still
runs; a thrown fetch on the source is still reported as itself.
Measured against a real local HTTP server with a single-page-app fallback:
real WebP accepted (image/webp and octet-stream), missing WebP refused
(200 fallback page and 404), real source accepted, missing source 404
(200 fallback page and 404), unreachable host a miss for the raster and
"fetch failed" for the source.
usePosterPrints uses it. PosterWall follows in its own commit.
With posterSources on, the tree shipped only the 28 zone poster sources,
so exporting any of the 176 city or 174 country posters said "poster not
found (404)": 350 of 378 posters could not be printed.
Each poster now ships once: its .html source where one exists, else its
.webp. Generating sources for the 350 was not an option: city posters
need OSM street tiles to regenerate (publish-html.mjs), and a source is
the heavy form (about 1 MB each against about 0.1 MB for a raster).
Measured with check:tree-weight: 102.7 MB before, 137.9 MB after, of
160 MB. The 350 rasters are the tracked data/posters/*.webp: all 350 are
existing git blobs, so the repository gains no new pack bytes.
New gate check:posters-exportable (in gates:post). Every poster id, from
data/posters and the wall's previews, must ship a real WebP or a real
poster source (its class="stage" element), so a placeholder or a host's
fallback page cannot pass. It skips when posters are off by config, which
check:poster-degrades covers. Poison-tested: a missing poster and a fake
image each fail.
The five stock labels were English literals in every locale ("Card 2.5 × 3.5 in" in Romanian), in a
file whose own header promises every string comes from the catalogue. The DECIDE card asked whether
paper names translate at all; this takes the middle that answers it for both readings: the NOUN
translates (Card, Postcard, landscape — wall.stockCard / stockPostcard / stockLandscape in all eleven
languages) and the size does not, since "2.5 × 3.5 in" and "A6" are what the paper box says in any
language. A6 has no noun and prints as named; English prints exactly as before.
The list kept its own page-1 map lift (packetMapSvg + packetLabelFor) beside the one in
usePosterPrints, and the two drifted: the list's relabelled country names, the wall's did not, which
is the zh finding rega made in the app. With the composable now taking iso3Names, the list passes it
and deletes its copy, so the list, the wall and any other map print page 1 through one path.
The selection packet borrowed one list's sheet when it held exactly one list. That is now a general
seam: item.mapId names the sheet when it is not the item's own id, and mapId: null says the item has
none, so a multi-zone selection fetches nothing and page 1 says the map is missing. Measured two-sided
through the real printPacket. gates:pre 66/66.
rega measured 13 controls under the 24px minimum in the country map's legend at 390px: the tier tabs
at 22px tall, their info buttons at 18x22, and the row carets. The tabs take a 24px minimum height and
the info buttons a 24px square. The carets grow to 24x24 while a -5px margin returns the extra space,
so the tree's indentation (which shares the caret width) does not move. One library component, so
every map with this legend gets it.
The i18n + RTL audit of Country Posters (the hardcoded-English gate only reads production plugins,
so it had never read this one; its scanner was run on the plugin directly and every hit triaged for
reachability, since the country map mounts one tab):
- 9 strings a reader sees were English in every locale: the search placeholder, the packet title's
"— 50 of N", the map-failed message, the wall's heading, tag, intro, soon message and item nouns,
and the view switcher's legend and label. All read from the catalogue now, reusing the existing
keys where they exist (tabs.selectView/views, the UPG-100 wall's tag and emphasis).
- The wall's section headings are the WAGF region labels in the data, English everywhere; they now
resolve through the Regions dashboard's own WAGF table, which gains its two missing regions.
- The three WAGF tier tooltips had no keys in any locale (legend.tabInfo.region/block/country).
- 0 physical-CSS findings.
PosterWall counted "N countries" as a number plus a 2-form noun pair and defaulted the plural to
noun + "s" — wrong for Russian and Arabic whatever strings it was given. It takes itemCountKey, a
plural catalogue key rendered with the count; useOptionalT forwards a plural count to vue-i18n (the
CLDR map picks ru 4 forms, ar 6, zh 1), and a host without i18n picks the English form by
vue-i18n's own rule. The people-group counts on the section heads and placeholder cards use
wall.peopleGroupCount the same way ("people groups" was hardcoded English on the cards).
The UPG-100 wall: its Americas and Europe section headings had no key (single words, invisible to
the gate), and it counts its lists with wall.listCount.
Checked: plural-forms, i18n-parity, keys-exist, never-translated, and i18n-treeshake against both
bundles built (26 bundles carry every area they ask for); gates:pre 66/66.
Every translated packet printed its references in English — "Matthew 27:27" in Chinese, Arabic
and the other nine — because refs are kept as canonical addresses and were printed verbatim. The
address stays canonical in the data; the BOOK is now named from a per-language table (the ten books
the points cite, in each language's common form: 马太福音, متى, Мф., Matthäus …). A localized
name in a right-to-left script is isolated rtl so it reads on the right with its chapter:verse
intact. Measured: 24 references per packet, 0 English book names left in zh, ar and ru.
Point 4's printed passage is untouched: which licensed translation to print per language is still
an open decision.
A host that draws its map live (the regions country map) has no posters/<id>.html to lift, so its
packets printed page 1 with the missing-map notice. usePosterPrints gains opts.mapImage(item): an
image or data: URL of the host's own map, placed by the renderer (mapFromImage) exactly as a poster
sheet is, the whole page inside the white margin. Order for page 1: an explicit mapSvg, then the
generated map, then the stored sheet. PosterWall forwards it as a prop. Measured two-sided through
the real printPacket: with mapImage the image is page 1 and no sheet is lifted; without it the
stored sheet is.
The composable's header now documents the whole contract — every option, which are optional, and
the row shape — so a map adopting it reads one comment instead of the wall that uses it.
A review of the full-detail packet, page by page:
- Page 1: a poster carries its own title, so the packet's title above it printed two headers and
shrank the map to fit beneath them. A poster sheet now fills the page inside the white margin by
itself; in another language its kicker and title become the packet's own, fitted to the English
width. A map-only sheet keeps the packet's title in the band it leaves empty.
- The life calendar is laid out like the Module 1 "Life Calendar in Weeks": square boxes, week
numbers across the top, the year down the side, a rule between decades, framed and centred. The
first 33 years are shaded as the life of Jesus (1,716 weeks).
- The %-evangelical grid fills from the top in reading order instead of scattering.
- The flow pages had no page padding at all, so their headings sat on the sheet's edge; they keep
the same margin as every other page now.
- The bounded and centered sets are one page, two square panels side by side as on the Module 1
list of 100, each headed by name with a cross at its centre. The centered set is a target of nine
numbered bands, its dots spread through their bands by the shared ringBands geometry (no overlaps,
none on the numbers), and the legend explains every ring with its count.
- The lightweight packet lists every group as a worksheet: a short note, one column header per page,
numbered rows sized for paper with room to tick, no photos or descriptions.
Seven new strings in all eleven languages. check:packet-a1-structure and check:packet-variants
assert the new contract two-sided (a poster page 1 has one header, a map-only page 1 still has the
packet's; every ring is named, a populated one with its count and an empty one with a dash).
The list's own print relabelled the map sheet (mapLabels.js); the wall's print, through
usePosterPrints, lifted the sheet with no relabeller, so a zh packet printed from the wall kept
INDIA, CHINA … on page 1. The generator's ISO3 -> name table is plugin data the library cannot
import, so the host now supplies it: PosterWall iso3Names -> usePosterPrints iso3Names, and the
UPG-100 wall passes its territory-counts table lazily. A host that passes nothing prints exactly as
before. Measured two-sided through the real printPacket on a tracked sheet: without the table the
page carries CHINA and no 中国; with it, 中国 and no CHINA.
check-hardcoded-english judges each quasi of a template literal on its own, which
is correct -- an allow-listed fragment must not drag a whole literal in with it.
But splitting `url(${base}/images/worldmap.svg)` leaves "url(" and
"/images/worldmap.svg)", and `repeat(${n}, minmax(0, 1fr))` leaves "repeat(" and
", minmax(0, 1fr))". The whole string is obviously CSS and the existing CSS shape
matches it; no individual fragment carries a brace or a colon-value pair, so each
one fell through and was reported as user-visible English.
Colon-terminated prefixes failed the same way. The id rule accepts a trailing
hyphen, because `id="country-${code}"` leaves "country-", but a langTree id is
`fam:${x}` / `dial:${x}` and a localStorage key is `pgg-cards-per-row:${profile}`.
Those leave "dial:" and "pgg-cards-per-row:", which no shape described.
Two shapes, both narrow: a CSS function fragment, and a prefix that is one
lowercase token ending at a colon. The fleet total goes 257 to 249 -- five of
mine, three in other owners' plugins -- and every real string still flags, which
I checked in the same breath rather than afterwards: "Search people groups…",
"Show filters", "selected" and "Research map loading…" are all still caught.
Worth saying plainly because the number was about to be routed as work: these
eight were never translation defects. Wrapping "dial:" in t() would have been a
bug, and someone would have done it on the strength of a count.
- Bottom line up front names the persona dx-maps is for, vibe coders, and links to what
they get.
- "Cloud development environment": by default bun run dev is fully local. DX_SYNC_REMOTE and
DX_SYNC_BRANCH in .env.local make it follow a shared branch. It fast-forwards only a clean
checkout on that branch, and never merges over local work. If your own agents also edit
the checkout, it stops following, so push small and often or the landings pile into a merge
conflict.
- The drop-in route's live example pointed at a branch that doesn't exist (research-gallery);
it is research-gallery-drop-in, proven with every production map passing its embed checks.
- One line on SRI where hosts copy snippets: the integrity hash makes a changed bundle
refuse to run, so copy the snippet again after each release.
rega at 390 px: wrapped, the view tabs took five rows (160 px of 844), and the shared 'Tap a coloured dot, someone still needs prayer' hint sat on top of the view's own bottom bar and attribution. On a phone the views are one select in one row (the tabs stay on a wide screen); pinHint is off, as for UPG Neighbor and the Wall.
Measured on the live list: 77 photos are 1024 x 1024 (4 MB each decoded) and drawImage downscaled each of them on every frame it was visible. A loaded photo is now kept at 320 px on its long side (createImageBitmap with resize, or one drawImage into a small canvas where that is missing), and the original is released; the print frame loads the originals itself. Below text zoom no card is measured (the photo box uses an estimate), and at text zoom at most 150 new cards are measured per frame. The overlay's sheets use content-visibility:auto. The host hook reports the counts (photos loaded, thumbnails, fallbacks, cards measured) for the performance probes.
The brief's three sizes. At 3 x 4 and 2 x 3 ft a verse under each of ~2,100 cards would print at 3 pt and 2 pt, so those sizes use the strip layout: cards of name and photo, and one blessing verse per row on a strip under it at 9 pt (33 and 34 verses). 5 x 8 ft keeps a verse under every card at 6 pt. The footer's height now comes from its text (the whole passages), with the journey never below 6 pt; the screen shows the strips as it shows the rest of the poster.
The priestly blessing is Numbers 6:22-27 in full: the Lord's word to Moses and Aaron in small type, the three blessing lines large, and the promise that closes it. Each station of the journey quotes the passage the brief lists: Genesis 12:1-4, Genesis 15:5-6, Galatians 3:13-14, 1 Peter 2:4-8 (the cornerstone, at the centre), Galatians 3:5-7 and 28-29, 1 Peter 2:9-10, Luke 19:9-10. The chart's New Testament verses name their passages (Matthew 21:21, from 21:18-22; Matthew 8:26, from 8:23-27). All WEB, verbatim, checked by script against ebible.org.
The new prayer-list key went into library/i18n/locales, and every bundle inlines
the i18n areas it uses -- so rebuilding regions-dashboard alone left other
consumers shipping the old catalogue. Caught before the landing scan did:
country-posters' committed bundle rebuilt to different bytes, which is the
stale-artifact case the build rule exists for.
build:bundles, then tree, then fix:sri. Nine bundles changed; the rest were
already byte-identical. fix:sri 127 agreed, 0 stale. Verified by rebuilding
country-posters again afterwards and comparing byte-for-byte.
regions-list.vue is bundle source, so the tree alone would have shipped a stale
.js with the English literals still in it. Rebuilt the bundle, regenerated the
tree, then fix:sri -- in that order.
Verified in the built artifact rather than the source: the new prayer-list key is
present in the bundle in Arabic, German and Russian, Country/Countries resolve
through t(), and the old item-noun="country" literal is gone (0 occurrences).
fix:sri 127 agreed, 0 stale. The three leaf HTML diffs are only the new
integrity hash following the rebuilt bundle.
sr's census found item-noun="country", item-noun-plural="countries" and
unit="UPG" passed as literals. All three reach the DOM: PosterWall renders the
noun pair at its section count (n === 1 ? itemNoun : plural) and the unit beside
each row's count, so in Arabic the chrome translated and these stayed English.
The noun pair now goes through t(). Country and Countries were already in the
catalogue in all eleven locales -- Land/Länder, الدولة/الدول, Страна/Страны --
so this adds no strings, and PosterWall keeps making its own singular/plural
choice with the caller supplying both forms, which is what its props are for.
unit stays "UPG" on purpose. It is DX-life's term of art, and their own Arabic
common.json carries the literal "UPG" rather than translating it; matching them
is the point of the port. It is the one entry the census still reports here.
A fourth literal the census did not flag went with them: the prayer-list
"Coming soon" sentence, which reaches exportState.message and so renders too.
That one had no key, so it lands as an English-source key -- the convention
useRegionsI18n exists to serve -- translated in all eleven locales, 77 keys
each, parity green.
MEASURED, this plugin's entries in check:hardcoded-english: 3 before, 1 after.
check:no-new-driver-references went red on development with my landing: the
comment I wrote when removing the SVG download named who set the rule. The gate's
own advice is the fix — the engineering reason is what a reader needs, and it
stands without attribution.
Comment-only: 0 non-comment lines changed, and the minifier strips comments, so
the shipped bundle is byte-unaffected and needs no rebuild. Verified rather than
assumed: the phrase greps 0 in the built artefact either way.
Found by regions, who proved it on bare ced1eb73c before their own cherry-pick
touched anything, and who held their push rather than landing on a red.
The collapsed-legend default and the removal of the SVG download both reach the
bundle. Verified in the artefact rather than the source: the download filename
and the posterSvg key are gone, the print path remains.
regions' fleet audit found the one poster path in the tree that downloaded a
file. The Driver's rule is that a poster action opens the print dialog and never
downloads, and there is no case for an exception here: printPoster builds the
same poster from the same makePoster(), so the download was a second route to one
artefact rather than a capability only it could offer. A reader who needs a file
prints to PDF — the system's own dialog, not a silent write.
The button, the function and the now-unreferenced tree.posterSvg key in all
eleven locales are gone. The comment left in its place names check:poster-action-
print, which regions is extending with this file as its poison case, so a
download added here again fails a gate rather than shipping quietly.
The two CSV export paths in GiGrid and GiResources are deliberately untouched: a
table has no print equivalent, the export is a documented feature that writes a
header line of sources with the data, and the rule — and that gate's own
description — is about POSTER buttons. Flagged to the shepherd rather than left
for the extended gate to trip over.
A4.3. GiMap and GiTree already default their legends closed and read the host's
`legend: 'open'` knob; the centered set hardcoded ref(true), so it was the one
view whose decoder sat over the drawing from the first frame — on the chart where
seeing the target matters most. That was an inconsistency, not a considered
difference.
Changing the ref alone would have shipped NOTHING: applyWidth ran on mount and
set legendOpen back to `!m.matches`, so at any desktop width it reopened
immediately. The bug was in the width rule, not the initial value. Width now only
ever CLOSES the legend — a wide window is not a request to cover the chart, it is
just the absence of the reason to force it shut — and a choice the reader has
made still wins outright.
Checked as a state machine over the cases that matter: desktop with no host knob
closed, desktop with legend:'open' open, phone closed, phone→desktop stays
closed, and a reader who opens it keeps it through a rotation and a resize.
check:composite-freshness found stale on main: none. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
gates:pre's check:packet-offline writes the four fixture packets into the
same directory this gate reads, so after gates:pre that directory is never
empty. A tree that had generated no zone then failed here on all 28 zones,
and gates:post was red on every landing for nothing anyone could fix.
Fixtures exercise the renderer, not a zone. With only fixtures present the
coverage assertion now says it did not run, and the per-packet checks still
run on the fixtures. One zone packet present and all 28 are required, as
before: planted with laos alone, it fails on the other 27.
The board carries a third card schema: proof in an 'evidence' list. 44 cards use it and 12 of them carry
none of the four fields the gate counted, so each false-failed on closing (one already had to be patched
with a redundant bluf). A non-empty list with at least one non-blank entry now counts. The self-test
covers both sides: a real list passes; an empty list, or one of blank entries, still fails.
One hundred and forty-three comments across the research dashboard, the research
map, Big Picture and the two composites attributed a decision to a person: by
name, by quotation, by date, or as "per Driver". Shipped code should carry the
reason a thing is the way it is, not who said so. A reader of the giveaway repo
has no way to ask that person anything, and the name tells them nothing the
reason does not.
So a quotation becomes the requirement it was quoting, a ruling becomes the
ruling, "the Driver reported" becomes what was reported, and a decision still
waiting on an answer now reads as provisional and pending a product decision
rather than as somebody's pending word. Where a comment already stated the
reason -- most of them did -- only the attribution went.
Two things were removed rather than rewritten. A personal medical fact appeared
twice ("the Driver is photosensitive"), once in a comment and once in a gate's
console output where it printed on every run; the motion-safety requirement
stands on its own and now reads that readers may be photosensitive. Internal card
ids that named nobody stayed, since they point at this repo's own history.
The bulk went in three batched passes of meaning-preserving substitutions, and
that is where the risk was: a blind replacement produces sentences that are
grammatically wrong but still look plausible in a diff. Re-reading every changed
line found thirteen -- "the the report describes", "including the two that were
had just complained about", "because was asked for WHITE rings" -- each repaired
individually. The count of remaining references caught the tail three separate
times, when a file type, an escaped apostrophe, and a scripts/ path each fell
outside a filter I had assumed was total.
Comment bodies and two console strings only. All twenty-one files parse, both
meta.json files are still valid JSON, and no declaration moved.
Five comments in the shipped research dashboard cited _qa-cycle documents by
path: three RESEARCH write-ups, one REFERENCE standard, and one scratch probe.
Those files do not ship. A reader of the built plugin gets a path they cannot
open, and the reasoning it was standing in for is lost to them.
In every case the durable finding was already written out directly above the
citation, which was only ever a trailing "and here is where that came from". So
each now ends on the finding itself and the path is gone: that a comfort-tuned
palette anaesthetises the response the map exists to provoke; that a casing which
scales with zoom is what stops dense low-zoom rings swallowing their own fill;
that the real fix for pin contrast is the lightness-conditional stroke, which
holds whichever ramp is selected; and that the palette values come from the live
site rather than being re-invented, which is what stops an embedded dashboard
reading cooler than the page hosting it.
The scratch probe became the METHOD rather than a filename, since a probe is
worth citing only for what it does: contrast every ramp stop against all three
pin targets under both CVD simulations, and re-solve composited over the real
basemap. Compositing over pure white is what made two handed-over candidates
look like they passed, and that is the part a future reader needs.
Comment-only: no declaration moved, and all three files still parse.
The rule: never quote or cite the Driver in shipped code. Every one of these
comments had a real engineering reason attached, and the reason is what a future
reader needs — so the reason stays and the attribution goes.
COUNT IS THE CHECK: 31 before, 0 after, across 8 files.
I was pointed at 18 in region-dashboards. That was one file. Sweeping my own area
as instructed found 31 in eight files: region-dashboards 7, RegionCountryMap 13,
regions-list 5, UupgsList 2, plus regions-mfe.vue, regions-mfe.meta.json,
index.js and check-regions-uses-library.mjs with one each. Reporting the wider
number rather than the one I was given.
HOW EACH WAS REWRITTEN, by kind:
· a REPORTED SYMPTOM keeps the symptom, loses the reporter — "the pins were
reported too small at rest", "the list page was reported slow, with the
posters suspected", "instead of flying to the region, which is exactly the
reported symptom".
· a REQUIREMENT becomes a requirement — the region key is "a map that shows the
regions and countries AND lets a reader select one" rather than a quotation;
the missing fullscreen and zoom controls are "part of the cloned surface"
rather than someone's complaint about a full clone.
· an OPEN DECISION becomes provisional. Two of these: the stat-card divergence
from RegionDetail.vue:176 is now "carried back as a product question", and
the numeral-grouping parity reads "PROVISIONAL, pending a product decision"
instead of waiting on a named person's ruling.
· a CARD ID goes with the name: BUILD-REGIONS-MAP-RESTORE-EDGE-SCROLL-STRIPS
and the round-2 test numbering are internal handles that mean nothing to a
reader of a published bundle.
· a SCOPE RULING is stated as scope: "improve the map's LOOK and add the
all-regions map, which must be intuitive" — the constraint survives, the
quotation does not.
Nothing lost that a reader needs: every measurement, pixel value, file:line
citation into DX-life's source and engine-specific caveat is untouched. What went
is a name, four dates and two internal ids.
SAME PROOF AS THE CITATION COMMIT, because a prose sweep across eight files is
exactly where a stray edit hides:
· the only non-comment changes are an HTML comment in a template and the "note"
field of regions-mfe.meta.json — and `note` is read by nothing: generate-tree
never touches it, and the string does not appear in the built manifest.
· meta.json still parses.
· rebuilding regions-dashboard and country-map reproduces the committed bytes
EXACTLY, and a full `bun run tree` leaves public/ clean — so NO bundle needs
rebuilding for this.
· gates:pre 66/66.
gospel's citation rule, applied to mine: a comment citing a PROBE or MEASUREMENT
(_probe-*, _chk-*) states the FINDING and drops the path. A reader cannot open
_qa-cycle from a published bundle, and the path outlives the file — so the number
has to be in the comment or it is lost.
FOUR CITATIONS, all of the probe kind, so all get the same treatment. Every one
already carried its finding; only the dead path is removed:
RegionCountryMap:36 three engineFor implementations "decide identically in
every engine combination" — now says WHICH combinations
were checked (mapbox-only, maplibre-only, both globals
present) rather than naming the script that checked them.
RegionCountryMap:462 the globe-fill measurement keeps its numbers (zoom 1.229
-> 390.61px = 50.1% of the frame, half the frame dead
space) and loses the probe path.
RegionCountryMap:552 the fit-at-construction comparison keeps both readings
(bounds-at-construction zoom 3.210 / mercator at t=0 vs
fitBounds zoom 2.777 / globe) and the engine version.
region-dashboards:522 "4 of 10 app properties OK", with the five failures that
were one missing thing already spelled out below it.
I did NOT only fix the one line I was pointed at: I swept my own plugin files,
the six library files I own or moved this session, and the seven gates I wrote.
Four citations total, all in these two files; the gates and the other library
files carry none.
COMMENTS ONLY, and proved rather than asserted: the diff filtered to non-comment
lines is empty; check:ported-globals-identical still reports 4/4 byte-identical
emitted CSS; and rebuilding regions-dashboard and country-map reproduces the
committed bytes exactly — comments are stripped at build, so NO bundle needs
rebuilding for this and public/ stays untouched. gates:pre 66/66.
scripts/strip-code.mjs:5 is deliberately left alone: per the same ruling it
explains why a committed gate cannot import from the scratch area, which is a
fact about the boundary rather than a citation across it.
The pull loop follows BRANCH with `git reset --hard FETCH_HEAD` whenever the branch moves.
In the cloud that is the point. On a checkout mounted from someone's machine it would wipe
their commits and uncommitted work. PULL_INTERVAL=0 now skips the loop entirely: no fetch,
no reset, one line in /tmp/pull.log saying so. Every other value behaves as before.
Checked both ways on a throwaway repo whose remote had moved on and whose working copy held an
uncommitted edit: with 0 the commit and the edit stay; with 1 (the control) the loop resets
both, as it always has.
The standing rule is that comments, docs and UI strings say what the code does and why, never who said
what. Several hundred existing lines break it; owners remove them in one sweep per area before the public
giveaway. Until then check:no-new-driver-references (gates:pre) fails any NEW line that refers to the
Driver and baselines the rest, keyed by file and line text with counts rather than line numbers, so
parallel sweeps only ever shrink it. It matches the role word, not a GPU or device driver, and its
self-test proves both that and that a new line beside baselined ones is isolated.
Five physical CSS declarations in the chrome every production map renders, so
under Arabic each of them lands on the wrong side for every map at once:
SemanticTreeLegend's active tab chip drew its border on the left, the share
menu's step list padded from the left, its tab spacing and its auto-spacer both
pushed from the right, and the geocoder's search icon sat at left:7px inside an
input that mirrors. All five become logical properties, which in a left-to-right
reading resolve to exactly what they resolved to before: four insertions against
four deletions in the components, one property each, and the English view cannot
move.
The reason they survived is the more useful half. check-legend-logical-insets
existed and passed, but it read only library/components/legends -- the share menu
is one directory away, and a reader in Arabic does not know which folder a control
came from. So the scan now covers map-controls as well.
Widening it was not enough. It still passed, because its CSS extractor matched a
template literal with the pattern `([^`]*\{[^`]*\}[^`]*)`, which describes a
literal containing ONE brace pair. ShareButton keeps its styles in a 600-line
useShadowStyles literal with hundreds, so the scan captured seven fragments
totalling 7,003 characters of a 629-line file and never saw .share-tab at all. It
was reporting PASS on a directory it was barely reading, which is worse than
having no check: a green gate is read as evidence. Template literals are now
taken whole and kept only when they look like CSS -- 2 blocks, 8,462 characters,
and the rule is finally in scope.
The self-test poisons BOTH directories. Poisoning only a legend would have proved
the check works on the half it always covered, and passed unchanged the day the
wider scan silently narrowed again. Its map-controls arm puts back the exact
declaration this commit removes, and its failure message says what a failure
means.
Seven comments in the library and the app pointed at probes, checks, a report or research notes that
live outside the repository, where a reader of the code cannot follow them. Each now states what was
found and drops the path: the engine-predicate equivalence, the chooser's globe-fill measurement, the
fit-at-construction probe, the worldview clause, the web-boundaries sizes (1,866 KB to 383 KB, every
feature and part kept). The QA corner and the packet generator lose a dead pointer. The app's nav
comment states the three sections and the third dashboard directly instead of quoting a transcript.
rega at 390 px: the tab strip ran past the right edge with no scroll cue, and the flat legend's collapse button measured 19×15 with an English title in every locale. On a phone the tabs wrap (the brand steps aside); the button is 24 px and named by the shared aria keys.
rega measured the header at 390 px: one row, so the title wrapped to five lines and the poster-size select (x=393) and the Bless/Social toggle (x=553) ran off the edge, unreachable. On a phone the title takes one short line and the controls wrap onto rows.
The caption and its eleven locale keys reach the bundle, so this is a real
rebuild rather than a docs-only change. fix:sri reports 127 hashes already
agreed, 0 rewritten; manifest churn is this bundle and the spa manifest's own
self-reference.
The README described fit and fill-all qualitatively but never said what choosing
one costs, which is the number a reader deciding between them needs: on the
default list, fit draws 931 of 2,074 groups and reports the other 1,143, while
fill-all draws all 2,074 with none outside its band and none under a label.
It also records the evidence for WHY this is a mode rather than a setting: 931 at
separation 7, 1,369 at 5, and 1,369 again at 4. That plateau is what shows the
band's depth is binding and not the spacing, and without it the next reader will
reasonably try to tune the number that cannot help.
Every figure here was re-measured against the shipped tables through the
component's own join before being written down, because a stale number in a
README is worse than no number: it reads as fact and nobody re-checks it.