Some checks are pending
build-gate / build (push) Waiting to run
The menu is position:fixed with viewport coordinates. That resolves against the
viewport only while nothing establishes a containing block for fixed
descendants. VerticalTabsLayout -- the cap-5 shell that hosts every plugin as a
tab -- sets contain:layout paint on .vtl-content, inside .vtl-main{left:256px}.
Measured at 1600x900, same component, two hosts:
standalone research-dashboard ...... dLeft=0 dTop=4 six of six
inside plugin-studio dashboard tab . dLeft=256 dTop=111 every one
256 is the rail width and 111 the header height. Reported as the menu landing
"in a random spot further down to the right"; it was never random.
An earlier probe measured six triggers at four viewport widths and passed, so
the card was closed while the bug was still there. Every number was accurate.
They were answers about a surface the user never looks at -- widening across
more widths could not have found it, because the variable was the host.
Fix measures the containing block instead of assuming it: a fixed probe at 0,0
inserted in the menu's own parent reports the origin the menu resolves against.
When nothing captures, that origin is 0,0 and the standalone numbers are
unchanged bit-for-bit.
Not fixed by dropping contain from the layout: it is load-bearing there,
stopping a rail collapse from reflowing a heavy mounted map.
check:fixed-anchoring measures both hosts and treats an unmeasured host as a
failure. Negative-tested: reverting the subtraction fails the studio host with
dLeft=256 while standalone still passes -- it fails exactly where the old probe
passed.
Also cards a second symptom of the same cause, not yet fixed: fixed-position
modal scrims written inset:0 stretch to the content pane instead of the
viewport, leaving the rail clickable behind an open modal.
115 lines
15 KiB
JSON
115 lines
15 KiB
JSON
{
|
||
"name": "doxa-maps",
|
||
"version": "0.1.0",
|
||
"license": "Apache-2.0",
|
||
"private": true,
|
||
"description": "A portable bundler that generates embeddable JAMstack maps — one library, many map bundles that embed on any site, compose into a lazy-loaded SPA, or wrap a Capacitor Android/iOS app.",
|
||
"type": "module",
|
||
"scripts": {
|
||
"dev": "bun x vite",
|
||
"build": "bash internal/build-lock.sh",
|
||
"build:watch": "bun x vite build --watch",
|
||
"preview": "bun x vite preview",
|
||
"clean": "node internal/clean.mjs",
|
||
"build:bundle": "bun x vite build",
|
||
"tree": "node internal/generate-tree.mjs",
|
||
"gallery": "node internal/generate-gallery.mjs # writes public/__gallery/index.html — the ARCHIVED bundle-index gallery, from public/doxa-maps/manifest.json. It is NO LONGER the root page: as of 2026-09-22 `/` mounts <plugin-studio> in BOTH trees (the built root page is written by `bun run tree`), and the gallery is the opt-in index at /__gallery. Archived, not deleted — the dev server imports renderGallery()/readBuildConfig() from this module.",
|
||
"check:drop": "node internal/drop-portability-check.mjs",
|
||
"check:parse": "node internal/inline-parse-check.mjs",
|
||
"verify": "node library/scripts/research/verify-all.mjs",
|
||
"verify:full": "node library/scripts/research/verify-all.mjs --full",
|
||
"serve": "python3 -m http.server 4173 --bind 0.0.0.0 --directory public",
|
||
"serve:shell": "python3 -m http.server 4174 --bind 0.0.0.0 --directory library/layouts/app-wrapper-material",
|
||
"cap:sync": "./node_modules/.bin/cap sync android # NOT `bunx` — bunx is not on PATH in this environment (command not found, exit 127), which broke cap:sync -> apk:debug -> phone at step one. The CLI IS installed locally (@capacitor/cli 7.6.9); invoke the local bin directly. The rest of package.json already uses the spaced `bun x` form.",
|
||
"cap:verify": "test -f deployment/capacitor/android/app/src/main/assets/public/index.html && echo \"OK webDir copied\" || (echo \"FAIL: empty assets/public -> blank white screen. Check webDir.\" && exit 1)",
|
||
"check:tauri": "node internal/check-tauri-config.mjs",
|
||
"tauri:build": "./node_modules/.bin/tauri build",
|
||
"apk:debug": "bun run build && bun run cap:sync && bun run cap:verify && cd deployment/capacitor/android && ./gradlew assembleDebug",
|
||
"apk:install": "adb install -r deployment/capacitor/android/app/build/outputs/apk/debug/app-debug.apk",
|
||
"phone": "bun run apk:debug && bun run apk:install",
|
||
"shell": "node internal/install-shell.mjs --no-token # OPTIONAL, not part of build: overlays a layouts/ wrapper onto public/ for local use (the served root is the generated index.html); --no-token so the local credential is never copied into the served root",
|
||
"posters": "cd library/scripts/posters && SPARSE=1 OFFLINE=1 VITE_API_BASE_URL=https://pray.doxa.life FORMAT=3x3 node generate.mjs",
|
||
"posters:one": "cd library/scripts/posters && SPARSE=1 OFFLINE=1 VITE_API_BASE_URL=https://pray.doxa.life FORMAT=3x3 node generate.mjs # ONLY=<zoneKey> to build one",
|
||
"posters:shoot": "cd library/scripts/posters && DSF=2 node shoot.mjs",
|
||
"posters:gallery": "cd library/scripts/posters && node build-gallery.mjs && node build-hd-gallery.mjs",
|
||
"posters:export": "cd library/scripts/posters && node export-public.mjs",
|
||
"posters:previews": "cd library/scripts/posters && python3 make-previews.py",
|
||
"token": "node internal/write-token.mjs",
|
||
"smoke": "node internal/smoke.mjs",
|
||
"smoke:embeds": "node internal/embed-smoke.mjs",
|
||
"smoke:gallery": "node internal/plugin-gallery-smoke.mjs",
|
||
"smoke:playground": "bun run smoke:gallery",
|
||
"smoke:share": "node internal/share-roundtrip-smoke.mjs",
|
||
"probe:legend-columns": "node internal/legend-columns-probe.mjs",
|
||
"sync:dropin": "node internal/sync-dropin.mjs",
|
||
"deploy:dev": "bun run build && node internal/sync-dropin.mjs --from-config --prune # destination + allowlist come from vite.doxa-maps-build-config.json (dropin.dest / dropin.include); DOXA_DROPIN_DEST=<dir> overrides the destination",
|
||
"check:public-hygiene": "node internal/public-hygiene-check.mjs",
|
||
"check:label-joins": "node internal/check-label-joins.mjs",
|
||
"check:dxlife": "node internal/check-dxlife-untouched.mjs",
|
||
"build:unlocked": "bun run check:template-literal && bun run check:sfc-parse && bun run clean && bun run token && for d in plugin-designs/*/; do BUNDLE=$(basename \"$d\") bun x vite build || exit 1; done && bun run tree && bun run check:drop && bun run check:parse && bun run verify && bun run check:sri && bun run check:public-hygiene && bun run check:label-joins && bun run check:descriptions && bun run check:no-abs-paths && bun run check:dep-names && bun run check:composite-srcs && bun run check:embed-targets && bun run check:nested-token && bun run gallery",
|
||
"check:template-literal": "node internal/template-literal-check.mjs",
|
||
"verify:map-paint": "node internal/verify-map-paint.mjs",
|
||
"check:sri": "node internal/sri-consistency-check.mjs",
|
||
"check:composite": "node internal/check-composite-freshness.mjs # a COMPOSITE is a COPY taken at its own build time: fails if a nested child's source is newer than the parent's bundle. NOT in build:unlocked on purpose — there everything was just built, so it could never catch the real case (a PARTIAL build). Run it before PUBLISH.",
|
||
"check:shots": "node internal/check-shot-freshness.mjs # a README screenshot that predates the bundle it shows is a picture telling a lie — and it looks IDENTICAL to a current one. Compares each shot's PNG against the BUILT BUNDLE it renders (not raw sources: an unbuilt edit is not yet in any leaf). Fix: node internal/readme-shots.mjs",
|
||
"check:library-index": "node internal/check-library-index.mjs # the DERIVED library menu must not fall behind library/. Compares the index against the newest library SOURCE (not a bundle — this generator scans library/ directly, with no build step between). Fix: bun run library-index",
|
||
"check:quoted-scripts": "node internal/check-quoted-scripts.mjs # documentation/README-SECTION-3-cli-commands.md QUOTES the scripts block verbatim; it had silently drifted TWICE (a stale bunx cap:sync, and build:unlocked missing check:public-hygiene + check:label-joins). package.json is what RUNS — update the DOC.",
|
||
"capability-exemplars": "node internal/generate-capability-exemplars.mjs # regenerate documentation/reference-capability-exemplars.md — the DERIVED answer to \"which bundle is the capability-N example?\", a question answered WRONGLY in three separate artifacts (a gate, the README, the /plugin-designer skill).",
|
||
"check:a11y-button-names": "node internal/check-a11y-button-names.mjs # every VISIBLE button must have an accessible name (aria-label / aria-labelledby / visible text — a `title` is a TOOLTIP and does NOT count). Measures the RENDERED DOM through shadow roots: a source grep cannot answer this (132 `<button>` hits, most with visible text). Needs a browser, so NOT in build:unlocked and NOT in CI. ALL=1 sweeps every profile.",
|
||
"check:catalog-identity": "node internal/check-catalog-identity.mjs # proves the LIVE server serves the CATALOG’s exact bytes, by hashing each live bundle and comparing sha384 against the manifest’s own integrity field. An HTTP 200 cannot do this: /app/doxa-maps/ returns 200 with a 2872-byte HTML SIGN-IN PAGE. Network-dependent, so NOT in build:unlocked and NOT in CI; SKIPs cleanly when unreachable. CATALOG=<dir> also requires the live manifest to match a catalog checkout.",
|
||
"check:catalog-currency": "node internal/check-catalog-currency.mjs",
|
||
"check:capability-exemplars": "node internal/check-capability-exemplars.mjs # REGENERATES and content-compares (not mtimes: a full build rewrites manifest.json every time, so an mtime rule would cry wolf after every build and get switched off).",
|
||
"check:capability-citations": "node internal/check-capability-citations.mjs # a doc that names a bundle as \"capability N\" must match manifest.json, which is what the BUILD computed. README captioned doxa-vision-card as cap-1; it ships 2 instances so it is parameterized (cap-2). The SAME error was fixed once in verify-5-capabilities.mjs and never reached the README — two copies of one fact, nothing forcing agreement.",
|
||
"check:shot-distinctness": "node internal/check-shot-distinctness.mjs # two README slots must not show the SAME view. README shipped \"List — page 1\" and \"page 2\" as the same picture: the shot chased a Next control and a scroll that DO NOT EXIST, every attempt inside try/catch so the miss was silent, and the PNGs differed by 0.16% render noise so no checksum caught them. Keys on url+VIEWPORT — same url at a different vp (deploy2 mobile) is intended.",
|
||
"check:shot-fidelity": "node internal/check-shot-fidelity.mjs # warns when THIS machine cannot RENDER what the shots must SHOW. `bun run shots` printed 13x OK while every emoji rendered as a tofu box — a glyph fallback loads perfectly (0 console errors, 0 HTTP>=400), so the generator cannot see it. Reports by default; --strict to block once an emoji font is installed.",
|
||
"shots": "node internal/readme-shots.mjs # regenerate documentation/readme-images/*.png (fetches its own Mapbox token SERVER-SIDE, so the browser CORS block does not apply). Was UNREACHABLE — present but invoked by no script, which is how the 12 PNGs silently rotted a day behind the UI.",
|
||
"library-index": "node internal/generate-library-index.mjs # regenerate documentation/reference-library-index.md — the DERIVED menu of the 84 reusable library pieces an author can import instead of rebuilding. Was UNREACHABLE, and the index did not exist at all: its header promised 'can't drift from the code' while nothing ever ran it.",
|
||
"check:done-evidence": "node internal/check-done-evidence.mjs # a card may not reach status:done with NO bluf AND NO fields — the Doxa team inherits this board and an evidence-less 'done' cannot be reconciled against the code. 10 pre-existing are baselined by id; the list should only ever SHRINK.",
|
||
"check:wp-embed": "php deployment/wordpress/tests/wp-embed-contract-test.php",
|
||
"check:mobile": "bun run cap:sync && bun run cap:verify # deploy-2 CONTRACT check: needs NO JDK/SDK/device. cap sync is a file copy + plugin wiring, so it runs anywhere; cap:verify then asserts assets/public/index.html exists. Guards the SOFT FAILURE capacitor.config.json warns about: a wrong webDir yields an EMPTY assets/public and a BLANK WHITE SCREEN at launch, not an error.",
|
||
"check:settled": "node internal/settled-tree-gate.mjs",
|
||
"verify:5-caps": "node internal/verify-5-capabilities.mjs",
|
||
"verify:gate1": "node internal/acceptance/big-picture-acceptance.mjs # the Gate-1 chain end-to-end against LIVE data: header emits research-filter -> composite passes props down -> the REAL cap-2 grid re-filters -> count reflected back up. Asserts the NEGATIVE (a filter that must return 0 does) and RESET. Was an ORPHAN — present in internal/acceptance/ but invoked by NO script, so it could never report anything.",
|
||
"check:descriptions": "node internal/check-profile-descriptions.mjs # every shipped profile must say what it is (reads the BUILT manifest)",
|
||
"check:no-abs-paths": "node internal/check-no-absolute-paths.mjs # no /home/… or /Users/… in any TRACKED file (a clone must work on any machine)",
|
||
"check:dep-names": "node internal/check-dependency-names.mjs # every declared dep is a REAL package name (a rename once rewrote @capacitor/* and broke bun install in a clone)",
|
||
"check:embed-targets": "node internal/check-embed-targets-exist.mjs # every embed.iframe src in manifest.json must resolve to a file that EXISTS. Those snippets ARE deployment-method 1 (iframe) — a partner pastes them verbatim — and NOTHING else asserts their targets are still emitted, because every other gate walks only files that exist and is blind to ABSENCE. `--self-test` poisons a copy of the manifest and asserts the gate NOTICES: a gate that cannot fail is worse than no gate.",
|
||
"check:composite-srcs": "node internal/check-composite-srcs.mjs",
|
||
"check:nested-token": "node internal/check-nested-token-delivery.mjs",
|
||
"check:nav-reachable": "node internal/check-nav-reachable-mobile.mjs # a cap-5 shell must have ONE on-screen control that opens its tab rail at phone width (needs `bun run serve` on 4173; browser gate, not in build:unlocked)",
|
||
"verify:browser-all": "node internal/verify-browser-all.mjs # runs ALL 7 browser gates over the built tree in one command (needs `bun run serve` on 4173 + MAPBOX_TOKEN). Every gate listed was RUN before being listed. Only smoke:share --plugin-gallery mode is out of scope; it needs the vite dev server.",
|
||
"check:shot-fonts": "node internal/check-shot-fonts.mjs # can THIS machine render the emoji the UI uses? Run BEFORE `bun run shots` — no font = tofu boxes in every committed PNG, which every other shot gate passes. Deliberately NOT in build:unlocked: it reports an ENVIRONMENT condition (this box has no emoji font), and a gate that always fails in the build makes the build useless.",
|
||
"smoke:share-all": "sh -c 'B=${BASE_URL:-http://127.0.0.1:4173}; exec node internal/share-roundtrip-smoke.mjs --url \"$B/doxa-maps/cities-internet/connectivity-map/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/country-posters/countries-map/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/demo-map/demo-map/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/doxa-research-map/research-map/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/doxa-simple-map/doxa-simple-map/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/gospel-resources/resources-map/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/my-upg-100-list/upg-100-list/index.html?tk=$MAPBOX_TOKEN\" --url \"$B/doxa-maps/my-upg-100-list/upg-100-mfe/index.html?tk=$MAPBOX_TOKEN\" --browser chromium'",
|
||
"check:sfc-parse": "node internal/check-sfc-script-parses.mjs # every .vue script block must parse as the BUILD parses it — catches the LIVE-CSS backtick that check:template-literal cannot see (it reads CSS comments only). 0 false positives on 83 files, where 3 lookahead heuristics scored 98 and 136.",
|
||
"check:url-resolver": "node internal/check-url-resolver.mjs # cap-5 resolve() must not prefix a rooted URL (the dev-surface 404 class)",
|
||
"smoke:studio": "node internal/smoke-studio.mjs # 5s DEV-surface check: / mounts the studio, tabs>0, 0 4xx (exit 2 = dev server down)",
|
||
"check:manifest-covers": "node internal/check-manifest-covers-discovery.mjs # every DISCOVERED (non-gated) bundle must be in the built manifest",
|
||
"check:csv-shape": "node internal/check-csv-export-shape.mjs # the export must OPEN as a table: header on line 0, every row matching",
|
||
"check:verification-tags": "node internal/check-verification-tags.mjs",
|
||
"check:fixed-anchoring": "node internal/check-fixed-anchoring.mjs"
|
||
},
|
||
"devDependencies": {
|
||
"@capacitor/android": "^7.6.9",
|
||
"@capacitor/cli": "^7.6.9",
|
||
"@capacitor/core": "^7.6.9",
|
||
"@tauri-apps/cli": "^2.11.5",
|
||
"@vitejs/plugin-vue": "^5.0.4",
|
||
"playwright": "1.61.1",
|
||
"terser": "^5.46.0",
|
||
"vite": "^5.4.21",
|
||
"vite-plugin-css-injected-by-js": "^3.5.2"
|
||
},
|
||
"dependencies": {
|
||
"@maplibre/maplibre-gl-geocoder": "^1.7.0",
|
||
"jspdf": "^4.2.1",
|
||
"maplibre-gl": "^5.6.0",
|
||
"pinia": "^2.3.1",
|
||
"topojson-client": "^3.1.0",
|
||
"vue": "^3.5.20",
|
||
"vue-i18n": "^9.14.5",
|
||
"world-atlas": "^2.0.2"
|
||
},
|
||
"engines": {
|
||
"node": ">=18.0.0"
|
||
}
|
||
}
|