country-posters: a phone can export too — and the gate was shutting the panel
Some checks are pending
build-gate / build (push) Waiting to run

Same gap as my-upg-100-list. countries-map.vue provided onSemanticTreeSelect to
the mobile sheet but not onLegendExport, so its embedded SemanticTreeLegend
rendered with exportEnabled defaulting to false. Fixed the same way, gated on
the profile's own EXPORT_FEATURE_ENABLED so the phone never gets an affordance
the desktop deliberately hides.

Mutation-tested, which is what shows the provide is load-bearing: without it
mobile reports 3 .stl-export elements with 0 having a real box, and fails. With
it, 6 present and 3 boxed, and passes.

I deferred this last tick as "another agent's profile". That was my assumption,
not a recorded rule. The swarm lane assignment maps FILES, and
countries-map.vue appears in no lane — while SemanticTreeLegend.vue, which I
have been editing throughout, is in one. Treating profile directories as
ownership boundaries is a reasonable default, but it is not what the swarm
recorded, and it cost a known two-line fix a full tick.

A second defect turned up in my own gate. check:legend-export-reachable clicked
the legend toggle unconditionally. That is right for my-upg-100-list, whose
sheet starts closed, and exactly wrong for country-posters, whose sheet opens
expanded: 8 rows visible before the click, 0 after. The gate was closing the
panel it came to inspect and then reporting "no selectable row" — which reads as
a product defect and was purely the probe. It now toggles only when nothing is
selectable yet, and both profiles pass.

Also re-verified two cards already marked done, after the previous tick found
part (a) of the legend card shipped-but-broken. Legend part (b), "remove or
demote Zone", holds: zero occurrences of "zone" in the rendered legend. The
per-map share policy holds at the rendered layer — upg-100 has no share button,
prayer-progress has exactly one — with smoke:share-all green across all twelve
published bundles and its coverage set checked against the policy's own list.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 18:21:14 +00:00
parent 795382fabc
commit e7f84bb84d
8 changed files with 134 additions and 115 deletions

View file

@ -56,8 +56,17 @@ async function probe(browser, { name, width, height, mobile }) {
const before = await page.evaluate(`(${WALK})(document).filter(e => (e.className||'').toString().includes('stl-export')).length`)
// On a phone the legend starts closed — open it first, or every row query returns nothing.
// ⚠ ONLY OPEN THE SHEET IF IT IS SHUT. This clicked the toggle unconditionally, which is
// right for my-upg-100-list (its sheet starts CLOSED) and exactly wrong for country-posters,
// whose sheet opens EXPANDED — measured 2026-09-24: 8 rows visible before the click, 0 after.
// The gate was closing the panel it came to inspect and then reporting "no selectable row",
// which reads as a product defect and is purely the probe. Toggle only when there is nothing
// to select yet.
const openedSheet = await page.evaluate(`(() => {
const all = (${WALK})(document)
const vis = (e) => { const r = e.getBoundingClientRect(); return r.width > 2 && r.height > 2 }
const rowsNow = all.filter(e => (e.className||'').toString().includes('stl-row')).filter(vis).length
if (rowsNow > 0) return false
const b = all.filter(e => e.tagName === 'BUTTON')
.find(e => /show or hide the legend|toggle.?legend/i.test(e.getAttribute('aria-label') || ''))
if (!b) return false

View file

@ -968,6 +968,16 @@ function _findNodeInTree(nodes, predicate) {
// and never reached mapStore.selectFamily → applyDimFilter, so the
// dim-on-select / restore-on-deselect path never ran (qa: 2026-05-03 iter-18).
provide('onSemanticTreeSelect', (node) => onSemanticTreeSelect(node))
// The SAME export handler the desktop legend gets via @export, reaching the mobile sheet the
// same way @select does. Without it <LegendMobile>'s embedded SemanticTreeLegend rendered with
// exportEnabled defaulting to FALSE, so a phone reader could browse the countries and had no
// way to export a poster or a packet — measured 2026-09-24, the same gap fixed on
// my-upg-100-list, with the same two causes (no export wiring, and no :tabs so there was no
// selectable row to export in the first place).
// ⚠ RESPECTS EXPORT_FEATURE_ENABLED. The desktop passes :export-enabled="EXPORT_FEATURE_ENABLED",
// so providing unconditionally would give the phone an affordance the desktop deliberately
// hides whenever that flag is off.
provide('onLegendExport', EXPORT_FEATURE_ENABLED ? onExport : null)
// Resolves the active tab's strategy → color for a given feature, used by
// useSelectedPin.js so the selection-pin matches the underlying dot color
// (qa: 2026-05-06 user feedback). research-mfe tab strategyKeys already

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
<script src="../country-posters.js" integrity="sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo" crossorigin="anonymous"></script>
<script src="../country-posters.js" integrity="sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
<script src="../country-posters.js" integrity="sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo" crossorigin="anonymous"></script>
<script src="../country-posters.js" integrity="sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
<script src="../country-posters.js" integrity="sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo" crossorigin="anonymous"></script>
<script src="../country-posters.js" integrity="sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -154,7 +154,7 @@
"bundle": "country-posters",
"scriptUrl": "./country-posters/country-posters.js",
"output": "doxa-maps/country-posters/country-posters.js",
"integrity": "sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo",
"integrity": "sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc",
"elements": [
"country-posters-map"
],
@ -174,7 +174,7 @@
"scriptUrl": "./country-posters/country-posters.js",
"embed": {
"iframe": "<iframe src=\"./country-posters/countries-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
}
},
{
@ -188,7 +188,7 @@
"scriptUrl": "./country-posters/country-posters.js",
"embed": {
"iframe": "<iframe src=\"./country-posters/country-poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
}
},
{
@ -202,7 +202,7 @@
"scriptUrl": "./country-posters/country-posters.js",
"embed": {
"iframe": "<iframe src=\"./country-posters/country-posters-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-+uSJg/LdhuPzecJG34oeevbtghdX7Pqaop+MyNzs4tyqd3/1frmrwQimIJgcv/yo\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-amheyqep13c83pKspBiNh8x4DIm5S/L7ifL34zSxsAe+LbpB0YW7DPH+a30ba6Xc\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
}
}
]