Commit graph

1110 commits

Author SHA1 Message Date
Doxa Maps
5362d84bc6 Host floor: re-probe only when the host may have changed kind, and never move a scrolled child
The measure-once design missed a host restyled from sized to height:auto after mount WITH in-flow content: it
stayed sized at its content height instead of getting the floor back, as the old probe did.
- After mount, follow() re-probes only when the reading says the host may have changed kind: floor on and the
  host shorter than the floor (styled after mount, or capped), or floor off and the host changed size (it may now
  follow its content). The re-probe saves every scrolled descendant (through shadow roots) and puts it back
  before the frame paints, so no reader state is lost. A window-height change on a content-sized host still
  writes nothing.
- A host capped below the floor (max-height) is latched by the probe that finds it, until it reaches the floor
  again, so it is never re-probed in a loop. The 1 s post-flip window is gone.
- check:host-floor gains arm H (sized → auto with 420 px of content: the floor returns, at most one flip, the
  scrolled child keeps its scrollTop) and counts re-probes in D/E. Poisons: the old per-resize probe, no capped
  latch, no re-check of a sized host, no scroll restore.
2026-10-02 10:06:37 +00:00
Doxa Maps
cd55cfd877 Host floor: one module, a latch for a max-height host, and a gate that pins measure-once
- library/elements/hostFloor.js holds the decision ProfileLoader uses: probeOnce() at mount, follow() on every
  host resize (reads only; at most one flip of the floor).
- A host CAPPED below the floor (max-height) follows its content up to the cap. It is found at mount, or, if
  the cap arrives later, by the host shrinking right after a flip; either way it is latched as content-sized
  and never flipped again, so it cannot loop. The post-flip check runs before the collapse rule, so a capped
  host with empty content is latched rather than flipped back and forth.
- check:host-floor (gates:pre; self-test in gates:post): a stub DOM with a scrolled child that clamps when the
  loader collapses. After mount, host resizes never write the loader nor move the child; a sized host fills;
  late sizing flips once; a max-height cap (at mount: 0 flips; after mount: at most one flip and one revert)
  never loops; a collapsed host gets the floor back; an inline host is left alone. Poisons: the old per-resize
  probe, and a missing latch.
2026-10-02 10:01:46 +00:00
Doxa Maps
c7b77b0a12 Merge origin/development into studio/poster-registry 2026-10-02 09:35:21 +00:00
Doxa Maps
0d09a72bf2 check:preview-flag-dev-only: the built tree may not even NAME the preview flag
Tightened before the India tab lands. A built bundle that READS globalThis.DXM_PREVIEW_UNRELEASED would ship the
withheld path itself, behind a global that any embedding page or console can set before the element loads, so
withheld content would print from production.
- A: no file under public/ names the flag at all (was: no assignment).
- B: every source line that reads OR writes it carries import.meta.env.DEV (was: writes only), so each read
  compiles away in a build.
- Self-test: a built setter, a built read, an unguarded source setter and an unguarded source read must each
  fail; the DEV-guarded forms and comments pass.
2026-10-02 09:26:40 +00:00
Doxa Maps
21e2200029 Poster sections: one type registry per page; the element takes a columns attribute
- ONE REGISTRY PER PAGE. Every bundle inlines its own copy of posterTypes.js, and <dxm-poster-section> is
  defined by whichever bundle loads first, so with a module-level Map that element saw only its own bundle's
  types: type="upg100-list" rendered "none" when the country-posters bundle had defined it. The registry now
  lives on the page (globalThis.__DXM_POSTER_TYPES__, created once): every copy registers into it and reads
  from it; a name registered twice keeps the first (a dev warning; the built-in country is silent); every
  registration is announced on window (dxm-poster-type-registered), and PosterSectionView looks again when
  its type arrives after it asked.
- COLUMNS (carried from the Poster Sections plugin PR so the element's library lands once): columns="1".."5"
  maps to profile-config.columns and to PosterWall's existing columns prop; absent or out of range is
  today's default, and a reader's saved per-row choice still wins.
- check:poster-type-registry (gates:pre; self-test in gates:post): two independent copies of the module side
  by side, as two bundles on one page; a type registered through one is found through the other; first wins;
  announced. The self-test's per-bundle registry fails.
2026-10-02 08:29:16 +00:00
Doxa Maps
078378199a The pilot's hot-reload server previews withheld content; no built bundle can
globalThis.DXM_PREVIEW_UNRELEASED lets a page show what is withheld from the public (the whole-India country
poster). defineMapElement.js, every element's first module, now sets it behind import.meta.env.DEV: true only
under the Vite dev server (the pilot's hot-reload preview), a compile-time false in every build, so the build
drops the line. The built tree, which goes to the research landing and DX Life's /dx-maps, never carries it.
check:preview-flag-dev-only (gates:pre; self-test in gates:post): no file under public/ assigns the flag in any
spelling a minifier writes, and every source assignment is behind import.meta.env.DEV (2 planted defects).
2026-10-02 07:56:01 +00:00
Doxa Maps
3056db68a6 Gates that read the poster wall's markup read the lifted PosterSection too: check:packet-variants (its card-deck and packet tapes) and check:poster-fetch-guard (no direct poster fetch) 2026-10-02 07:23:19 +00:00
Doxa Maps
a3225e072f check:poster-wall-host-seams: load any .vue PosterWall imports, and prove it with arm L
The gate compiled PosterWall.vue alone, as a client component, and runs
Vite without the Vue plugin. A child component imported by PosterWall
(a section component, which a refactor is about to add) would fail to
load, turning the gate red on correct code.

One resolveId/load hook (enforce 'pre', so Vite's resolver does not load
the raw SFC first) now client-compiles PosterWall and every .vue it
imports, each at its real path, so their own relative imports resolve as
in the build; the earlier '../../' path rewrite is gone. Arm L loads a
parent fixture that renders a child .vue by relative import
(internal/fixtures/poster-wall-host-seams/) and asserts the child's text.
It fails without the hook and without 'pre'.
2026-10-02 06:39:49 +00:00
Doxa Maps
d533431997 Phones: one top bar on a website too; maps fill a sized host, so the legend is never cut off
- WEB MODE GETS THE TOP BAR BACK. The corner ☰ with no header was rejected on a real phone. Both shell modes
  now show the one top bar on a phone, the ☰ at its start and the language at its end; web mode's bar takes no
  camera inset (the shell is not at the top of the screen in a website). The corner circle and the drawer-foot
  language are gone. check:shell-header renders both modes (13 planted defects).
- THE FLOOR NEVER EXCEEDS A SIZED HOST. ProfileLoader's 100svh floor is for a host sized by its content (the
  scroll-page leaf). Inside a host with a definite height (DX Life's map slot, overflow hidden) it made the map
  taller than the host, which clipped the map's bottom and its legend footer, and tied the map's height to the
  window's. ProfileLoader now MEASURES the host (the floor at 0 and at a huge value: a sized host keeps its
  height) and drops the floor inside a sized one, re-measuring when the host resizes (a ResizeObserver on the
  host, not a window resize).
- LegendDesktop caps itself at the map's height (100% - 80px), not the window's (100vh - 80px).
2026-10-02 05:27:37 +00:00
Doxa Maps
326eccb465 Phone drawer: starts closed from the first paint; the language sits at its foot
- On a phone the drawer started OPEN (navOpen = initialNavOpen) and mounted() closed it, so every load drew it
  on screen and slid it away (measured: up to ~1.6 s, both shells, app and web mode). data() now reads the
  same (max-width: 760px) query, so the first render is already the phone's closed state; mounted() still
  tracks breakpoint crossings.
- In web mode the language at the drawer's foot sat right under the last row: margin-top:auto needs the nav's
  flex column (.has-rail-end), which only the desktop rail-end set. The phone drawer's foot sets it too.
- check:shell-header asserts the flex column in web mode (14 planted defects).
2026-10-02 05:04:36 +00:00
Doxa Maps
6032512edf Phones: one header on a website, and maps that hold their size while you scroll
ONE HEADER ON A WEBSITE. Inside a host site that has its own header, the shell's 44px phone bar stacked a
second white bar under it. VerticalTabsLayout gains shellMode (prop, or the host element's shell-mode
attribute): web | app | auto.
- app (a Capacitor or standalone app, or a DX Maps leaf page): the phone bar, unchanged.
- web: no bar. The rail opens from a 40px corner ☰ at the pane's bottom-start, which publishes its footprint
  (--map-fab-clearance / --map-fab-beside) so the legend sheet, the pin hint and back-to-top step aside; the
  language menu moves to the drawer's foot.
- auto: the host's shell-mode attribute, else app for Capacitor, display-mode standalone or a leaf
  (window.MAP_OWNS_PAGE), else web.
Desktop is unchanged. check:shell-header renders both modes (13 planted defects); check:nav-reachable-mobile
accepts the corner ☰.

MAPS HOLD THEIR SIZE. ProfileLoader floored every map at min-height 100dvh, and the leaf pages' slot did the
same. dvh follows the mobile URL bar, so scrolling grew every map mid-scroll and moved its legend sheet. Both
now use 100svh (the viewport with the bar showing, which never changes on scroll), with 100vh where svh is
unsupported.
2026-10-02 04:44:33 +00:00
Doxa Maps
52802bd471 The exclusion list and the hygiene detector no longer match the export's own content rule (bracket forms, a pattern built from parts) 2026-10-01 16:32:23 +00:00
Doxa Maps
6d4fc6cccc Merge remote-tracking branch 'origin/development' into upg100/phone-bigjob 2026-10-01 13:30:56 +00:00
Doxa Maps
c4b756b65a Merge remote-tracking branch 'origin/development' into upg100/pg-names
# Conflicts:
#	package.json
2026-10-01 13:25:01 +00:00
Doxa Maps
98eeb4183d UPG-100 batch HUD: the message line sits at the top, where nothing covers it
On a phone the first-visit PinHint toast sits over the HUD's bottom edge, and the
message line under the buttons was covered there. A hit-test across the text
found the toast at 30%, and the screenshot read "This needs a" and no more.
The line (Copy's flash, the phone ceiling's notice, failures, the print's
progress) now sits under the hint at the top of the HUD, at 11px instead of 9px.
check:batch-selection-export pins it above the action rows.
2026-10-01 13:01:11 +00:00
Doxa Maps
ea5a5bf8ae Merge origin/development into gospel/b14-gate-fp 2026-10-01 12:50:29 +00:00
Doxa Maps
eeda3f168c Merge remote-tracking branch 'origin/development' into upg100/phone-bigjob 2026-10-01 12:48:41 +00:00
Doxa Maps
c78a829810 UPG-100 batch HUD: on a phone, the block notice and the print's progress are visible
.upg-status is display:none below 768px (the legend sheet owns the bottom edge),
so the phone ceiling's "This needs a desktop or laptop computer." and the print's
progress ("fetching people groups…", "printing 905 people groups…") were written
only where a phone shows nothing. A reader tapped Prayer List and nothing visible
happened.

hudSay writes a batch action's message to the batch HUD's line (.upg-hud-flash,
now a polite live region, visible at every width) as well as to the status
badge. The block notice stays 6 s and failures 5 s. The print's progress is
mirrored into the same line whenever no flash is up, and is cleared when the
print ends.

check:batch-selection-export arm C checks that the notice, every batch action's
failure text and the progress reach the HUD line, that no batch action writes
via flashStatus alone, and that no rule hides .upg-hud-flash. Four mutants each
fail, including "notice written only to .upg-status".
2026-10-01 12:48:39 +00:00
Doxa Maps
1fde892d4b UPG-100 batch selection: on a phone, a selection too big to print asks for a computer
Building a selection's Prayer list or Card deck is never the problem (the whole
selection is ready in under 30 s on a 4×-throttled phone). PRINTING it is: in a
browser capped at 2.5 GB, the print of 1,857 groups (101 sheets, a 138 MB PDF)
finished, and 2,209 groups (113 sheets) crashed the page at 1× and at 4×. A phone
tab has roughly half that memory, so above 1,000 groups (PHONE_GROUP_CEILING,
with the measurement beside it) a phone or tablet gets the house text
"This needs a desktop or laptop computer." (poster.phoneLimitAll, as Country
Posters shows for whole India) and nothing starts. India alone (905) still
prints on a phone. A desktop is never blocked. Copy and CSV stay allowed.

The device test is isPhonePrint(), the same platform test the print path uses.
check:batch-selection-export arm A7 tests the ceiling both ways. Arm C checks that
Prayer list, Card deck and Poster each ask BEFORE they print, and arm D checks
the string ×11. Four mutants each fail.
2026-10-01 12:08:38 +00:00
Doxa Maps
84d5800106 Merge origin/development into gospel/b14-gate-fp 2026-10-01 11:57:59 +00:00
Doxa Maps
c626a1fc02 Packet fixtures build in their own directory, so the real Tibet zone packet survives check:packet-offline 2026-10-01 10:52:55 +00:00
Doxa Maps
81fd6dc7d5 Landing precondition: a library change's freshness scope includes shipped bundles the manifest does not list (template-bundle) 2026-10-01 10:52:55 +00:00
Doxa Maps
448ef0ac70 Merge development (a77a3280f: the shell header, the docs) into the whole-India landing
# Conflicts:
#	package.json
2026-10-01 10:02:25 +00:00
Doxa Maps
a77a3280f3 Merge origin/development (d6950c008) into studio/shell-header 2026-10-01 09:52:20 +00:00
Doxa Maps
edda4017b3 Merge development (d6a53486f, UPG-100 wall count) into the whole-India landing
# Conflicts:
#	package.json
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/my-upg-100-list/my-upg-100-list.js
#	public/dx-maps/my-upg-100-list/poster-wall/index.html
#	public/dx-maps/my-upg-100-list/upg-100-list/index.html
#	public/dx-maps/my-upg-100-list/upg-100-mfe/index.html
2026-10-01 09:46:12 +00:00
Doxa Maps
2f163e04c1 Large side-lane sheets: photos print in the sheet's own document, and a raster never draws a broken image
Measured on the 60x96 print: every photo beside a name rasterised as the browser's broken-image glyph. An SVG
rasterised through <img> is an isolated document that fetches no external resource, and none of the people-group
photo hosts (media.joshuaproject.net, joshuaproject.net, images.peoplegroups.org and its resizer,
peoplegroupspublic.blob.core.windows.net, s3.doxa.life) sends CORS, so a photo cannot be inlined as data: in the
browser either.
- poster-raster.js: rasterPoster drops every <image> whose href is not data: (the basemap tiles are data: and stay),
  so a download shows the paper, never the glyph. hasExternalImages() says when a sheet carries such photos.
- PosterWall: printing a generated sheet that carries photos prints THE SHEET ITSELF through printDocument, where
  the photos load, on its own @page (60in 96in), instead of a raster shrunk onto letter. Same HUD steps.
- check:side-lanes: photo arms (0 external images reach the raster; the wall prints such a sheet as a document),
  each with a poison in its self-test.
- check:side-lane-photo-pixels: the pixel side, a browser gate (a data: photo draws red; 99/99 external slots stay
  flat; without the strip 0/99 do). Declared on-demand until its first browser-seat run.
2026-10-01 09:45:33 +00:00
Doxa Maps
d6a53486f6 Merge remote-tracking branch 'origin/development' into upg100/wall-count
# Conflicts:
#	package.json
2026-10-01 09:34:09 +00:00
Doxa Maps
9a40b864bd Merge origin/development (42bc19889) into studio/shell-header 2026-10-01 08:42:57 +00:00
Doxa Maps
1e925c4d71 Gospel checks: the field-card shards are expected from the roster, not read as one file, and German 'Ring' is the same word on purpose 2026-10-01 08:37:17 +00:00
Doxa Maps
b8cf0db0c8 Merge remote-tracking branch 'origin/development' into upg100/pg-names
# Conflicts:
#	package.json
2026-10-01 08:35:25 +00:00
Doxa Maps
8896ad2130 Merge remote-tracking branch 'origin/development' into upg100/wall-count
# Conflicts:
#	internal/check-batch-selection-export.mjs
#	package.json
#	plugin-designs/my-upg-100-list/data/selection-export.js
#	plugin-designs/my-upg-100-list/poster-wall.vue
#	plugin-designs/my-upg-100-list/upg-100-list.vue
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/my-upg-100-list/my-upg-100-list.js
#	public/dx-maps/my-upg-100-list/poster-wall/index.html
#	public/dx-maps/my-upg-100-list/upg-100-list/index.html
#	public/dx-maps/my-upg-100-list/upg-100-mfe/index.html
2026-10-01 08:24:48 +00:00
Doxa Maps
cbafb21921 Merge origin/development (86a81cc44) into studio/shell-header 2026-10-01 07:49:52 +00:00
Doxa Maps
9b0f815e7c Merge origin/development (86a81cc44) into studio/poster-sizes 2026-10-01 07:49:08 +00:00
Doxa Maps
7ea7195646 Pin hint: an inner scroller counts as a scrolling page, a map off the viewport is on one, and a stale lift is dropped
DX Life's /pray at 1440 kept the pill at the viewport's bottom until the map's bottom came into view: the page
scrolls a container, not the document, so the document-only test saw a full-screen page and kept the fold.
pageScrolls now also walks out from the pill, across shadow roots, for an ancestor scroller whose content is
taller than it; a map wholly below or above the viewport is treated as on a scrolling page; and a lift is
cleared when the pill goes off screen, so a lift set while the map was half visible does not survive into the
next view. check:pin-hint-floor adds the inner-scroller, shadow-crossing and map-below-the-fold fixtures; its
self-test refuses 9 planted defects.
2026-10-01 07:11:18 +00:00
Doxa Maps
9e0b52386d Merge origin/development (6dc2206c8) into studio/pinhint 2026-10-01 06:56:45 +00:00
Doxa Maps
ba022f68f9 Merge origin/development (d3b879c94) into studio/pinhint 2026-10-01 06:32:47 +00:00
Doxa Maps
852437e981 Merge remote-tracking branch 'origin/development' into upg100/state-packet 2026-10-01 06:32:09 +00:00
Doxa Maps
cdbda65a06 People-group names: the threshold pinned, no trust without Latin evidence, raw indexing flagged
Folds in the review's four points:
(a) check:pg-name-gate plants a row with EXACTLY two far Latin locales, which must
    show English, so a rule that needs three fails.
(b) A row with fewer than two Latin names cannot be checked (117 rows), so it now
    shows English too. The whole table: 8,172 of 21,419 (38.2%).
(c) The one-reader scan also flags a file that imports the helper but still
    indexes rows itself (`.names[`), with negative controls both ways.
(d) The helper documents that callers always pass `english`.
Seven mutants of the helper each fail the gate.
2026-10-01 06:04:41 +00:00
Doxa Maps
31e5c3e5f9 UPG-100 batch selection: a state-only selection prints its Prayer list and Card deck
The packet and card-deck title named the selection's zones and countries only.
Since India's states bring people, a selection of states alone had no names, and
reduce() threw "Reduce of empty array with no initial value" at the reader.
selectionTitleNames (data/selection-export.js, pure) adds the states and union
territories that brought people. A province with no table is not named. A
selection that brought nobody (Mizoram or Nagaland alone) gives the keyed
"no people groups to print" instead.

check:batch-selection-export arm A6 tests it on the real served table: Gujarāt
alone is titled "Gujarāt", a state + a country names both, a province beside it is
not named, and Mizoram alone reads the keyed text. Its negative control shows the
old naming is empty and reduce() throws. The call site is pinned in arm C. Four
mutants each fail.
2026-10-01 06:00:55 +00:00
Doxa Maps
6e80da212c People-group names: one helper decides when a localized name can be shown
library/utils/peopleGroupName.js (pure) returns a group's name in the reader's
language only when the row's names are transliterations. When two or more of its
Latin-script names (fr pt es tl id de) are far from the English one (bigram Dice
< 0.5), the row was machine-translated as words (Balantak → "Balance",
Balo → "Sac à dos"), and every locale of that group shows English. That is
8,055 of 21,419 rows (37.6%). it and ro have no column and show English; zh
reads zh_CN. A fallback shows the caller's own English name.

check:pg-name-gate (gates:pre) proves it on the real table: the 4 known
translated rows show English in 7 locales, Balangao Bontoc keeps its names,
planted rows are two-sided, the whole-table fallback stays between 30% and 45%,
and no file outside the helper reads pg-names rows (pplr-data-maps is the
exception; the scanner is negative-controlled). Five mutants of the helper each
fail it. No consumer is wired yet.
2026-10-01 05:52:31 +00:00
Doxa Maps
59afad5a33 check:no-fleet-names: names in any case, the plugin agents' names, and the translation catalogues scanned too; the self-test plants each 2026-10-01 05:42:24 +00:00
Doxa Maps
2f7eaae8e3 check:no-fleet-names: source names no build-team member, attributes no request to a user, carries no dated QA tag
A sweep brought tracked source to 0 such lines; this gate keeps it there. It scans every tracked text file
except research data, build output and the translation catalogues, and allows only named lines (a file plus
the exact line, with its reason), never a whole file; the list is empty, since the gate builds its own
patterns from parts. gates:pre runs it; gates:post runs its self-test, which plants each class and checks
the per-line allowance.
2026-10-01 05:36:29 +00:00
Doxa Maps
cc4cbb7955 P assembly: a gate comment names the browser check, not who ran it 2026-10-01 05:32:44 +00:00
Doxa Maps
77751ddcb6 Merge origin/development (53fcf6d09) into studio/p-assembly 2026-10-01 05:32:16 +00:00
Doxa Maps
b6777218e3 Merge remote-tracking branch 'origin/development' into poster-design-plugin/zero
# Conflicts:
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/my-upg-100-list/my-upg-100-list.js
#	public/dx-maps/my-upg-100-list/poster-wall/index.html
#	public/dx-maps/my-upg-100-list/upg-100-list/index.html
#	public/dx-maps/my-upg-100-list/upg-100-mfe/index.html
2026-10-01 05:18:28 +00:00
Doxa Maps
289d31e3f4 Merge remote-tracking branch 'origin/development' into upg100/batch-tap
# Conflicts:
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/my-upg-100-list/my-upg-100-list.js
#	public/dx-maps/my-upg-100-list/poster-wall/index.html
#	public/dx-maps/my-upg-100-list/upg-100-list/index.html
#	public/dx-maps/my-upg-100-list/upg-100-mfe/index.html
2026-10-01 05:12:05 +00:00
Doxa Maps
f3851da57c PosterWall: sectionItemCountKey, so one section can be counted in its own words
The Country Posters India section headed "855 people groups · 37
countries", which is untrue: its cards are India's own and one per state
and union territory. sectionItemCountKey (default null: every section
counted with item-count-key, as before) lets a wall answer, per section,
an i18n plural key, or { key, n } to count n rather than the section's
card count, or null to keep the default.

Walls that do not pass it render byte-identical trees before and after
(a differential render of an upg100-style and a country-posters-style
wall). check:poster-wall-host-seams arm K: a named section counts in its
own key and number, an unnamed one keeps the default; it fails with the
prop ignored.
2026-10-01 05:10:55 +00:00
Doxa Maps
24f3e4176a PosterWall: a section head names its people-group total only when there is one
A section head read "<n> people groups · <items>" always, so a wall whose
cards count no people (Poster Design's gallery of templates) showed
"0 people groups · 4 lists" on every head. The total and its " · " now
leave together when the total is 0, the rule the cards already follow with
v-if="item.count". The head is still one string in one interpolation, so a
section with a total renders exactly the text it always did, whitespace
included: a differential render of an upg100-style wall and a
country-posters-style wall, before and after, gives identical trees.

check:poster-wall-host-seams gains arm J (a head with people keeps its
total; one without reads its items alone); the old head line fails it.
2026-10-01 05:10:55 +00:00
Doxa Maps
4b8e9de925 check:batch-selection-export A5: bound the refused-connection probe at 2 s, so a host running the discard service on port 9 cannot hang the gate 2026-10-01 05:05:30 +00:00
Doxa Maps
0907d96de2 UPG-100: one digit system per sentence, and no raw error after a failed load
The wall intro writes its total in the digits the translated sentence already uses
(countInSentence): ar shows ٢٬١٠٧ beside its own ٢٧ and ٩:١٤, while CLDR's bare
'ar' would have formatted 2,107. Locales whose sentence uses Western digits are
unchanged. The fetching status goes through the same helper.

A people-group load that fails without a catalogue key (the 30 s abort, a dropped
network) now reads as the stall text, "still loading, try again in a moment",
instead of the browser's own English ("signal is aborted without reason"). Keyed
errors keep their own text, and the failed load leaves the cache, so the next Copy
fetches again.

check:upg-count arm E renders the intro through each locale's catalogue and
requires one digit system, with a negative control on the old ar render. Its
separator scan now also reads fr U+202F and ru U+00A0. check:batch-selection-export
arm A5 aborts a real fetch and refuses a real connection; both must read as the
stall text, and the old path must still show the raw message.
2026-10-01 01:06:44 +00:00