diff --git a/internal/check-poster-browser-equiv.mjs b/internal/check-poster-browser-equiv.mjs index fc3b3552e..4bfd5dff4 100644 --- a/internal/check-poster-browser-equiv.mjs +++ b/internal/check-poster-browser-equiv.mjs @@ -21,19 +21,50 @@ * is absent the check cannot run: NOT MEASURED (75). If it is present and the Node generator fails or * writes nothing, that is a FAILURE — a broken driver must not read as "not measured". */ -import { readFileSync, existsSync, rmSync } from 'node:fs' +import { readFileSync, existsSync, rmSync, mkdtempSync } from 'node:fs' import { spawnSync } from 'node:child_process' import { join } from 'node:path' +import { tmpdir } from 'node:os' import { pathToFileURL } from 'node:url' const REPO = new URL('..', import.meta.url).pathname const P = join(REPO, 'library/scripts/posters') const CACHE = join(P, 'out/_records.json') +// ★ A COMMITTED FIXTURE SO THIS GATE CAN MEASURE ON A FRESH CHECKOUT. out/_records.json is +// gitignored (library/scripts/*/out/**) and is written only by `generate.mjs` against a live API, +// so on CI and on any box without credentials this gate exited 75 EVERY run — chained in gates:pre +// and inert. The runner reported that honestly as NOT MEASURED rather than as a pass, but an +// identical ⊘ every run is indistinguishable from an unwired gate. +// AN EQUIVALENCE CHECK NEEDS THE SAME INPUT ON BOTH SIDES, NOT FRESH INPUT, so a fixed fixture +// loses nothing it was measuring. The fixture is the 124 PUBLIC records the two arms actually +// consume — Nepal's 34 (the country arm) and the 90 slugs the Gujarat zone selects (the zone arm) — +// carrying the same fields the served maps show. +// VERIFIED against the full 2,106-record cache: identical zone pins IN THE SAME ORDER, identical +// Nepal set, count 90, pop 3,164,770, series {2209, 28, 1}. Record ORDER is load-bearing (it drives +// draw and label order), so the fixture keeps the cache's order and is deliberately not sorted. +// NAMED equiv-*, NOT records-*: internal/build-packet-fixtures.mjs walks this directory for +// /^records-.*\.json$/ and builds EVERY match as a packet against one fixed zone (Tibet), so that +// shape is the only variable. A records-* file with no Tibet groups therefore fails that build by +// construction — which is exactly what this fixture did until it was renamed. Two different kinds +// of fixture share one directory; the prefix is what keeps them apart. +const FIXTURE = join(P, 'fixtures/equiv-records-npl-ind.json') +const SOURCE = existsSync(CACHE) ? CACHE : FIXTURE const ASSETS = join(REPO, 'public/dx-maps/assets') const DATE = '2026-09-29' -if (!existsSync(CACHE)) { - console.log('POSTER-BROWSER-EQUIV: NOT MEASURED (exit 75) — no offline records cache at library/scripts/posters/out/_records.json;') - console.log(' run `node generate.mjs` once with an API configured to write it.') +// ★ THIS GATE WRITES NOTHING SHARED. generate.mjs's default out/ is gitignored but SHARED, and +// check:zone-census counts the sheets in out/posters/ to decide whether every selectable zone has +// one. Running the generator here for a byte comparison left asia-india-gujarat.packet.html and +// country-npl.html behind, and zone-census read those two as a half-finished poster build: it went +// from NOT MEASURED to FAIL, naming 28 zones with no poster. A checker must not change what the +// next checker measures, so the generator is pointed at a private temp dir that is removed below. +const WORK = mkdtempSync(join(tmpdir(), 'equiv-')) +// Registered on 'exit' rather than written at the end: this gate exits 1 on a mismatch and 75 on a +// missing precondition, so a trailing cleanup line would be skipped on exactly the runs that ran the +// generator. 'exit' fires for all of them, and for a throw. +process.on('exit', () => { try { rmSync(WORK, { recursive: true, force: true }) } catch { /* best effort */ } }) +if (!existsSync(SOURCE)) { + console.log('POSTER-BROWSER-EQUIV: NOT MEASURED (exit 75) — no records to measure with: neither the offline cache') + console.log(' (library/scripts/posters/out/_records.json) nor the committed fixture (library/scripts/posters/fixtures/).') process.exit(75) } if (!existsSync(join(ASSETS, 'boundaries/world-adm0.geojson'))) { @@ -52,10 +83,13 @@ let failed = false if (!same) failed = true } function nodeSheet(env, file) { - const out = join(P, 'out/posters', file) + const out = join(WORK, 'posters', file) rmSync(out, { force: true }) const r = spawnSync('node', ['generate.mjs'], { cwd: P, encoding: 'utf8', timeout: 240000, - env: { PATH: process.env.PATH, HOME: process.env.HOME, OFFLINE: '1', VITE_API_BASE_URL: 'http://offline.invalid', POSTER_DATE: DATE, ...env } }) + // RECORDS_FILE is SOURCE, the very file the browser arm read. Feeding the two sides from the + // same records is what makes this an equivalence check rather than two independent renders — + // and it is what lets the Node side run at all without a live API having written the cache. + env: { PATH: process.env.PATH, HOME: process.env.HOME, OFFLINE: '1', VITE_API_BASE_URL: 'http://offline.invalid', POSTER_DATE: DATE, RECORDS_FILE: SOURCE, OUT_DIR: WORK, ...env } }) if (r.status !== 0 || !existsSync(out)) { console.log(` ✗ the Node generator did not write ${file} (exit ${r.status})\n${(r.stderr || r.stdout || '').slice(-400)}`) failed = true @@ -64,7 +98,11 @@ function nodeSheet(env, file) { return readFileSync(out, 'utf8') } const json = (p) => JSON.parse(readFileSync(p, 'utf8')) -const records = json(CACHE) +const records = json(SOURCE) +// SAY WHICH INPUT WAS MEASURED. The full cache widens coverage to all 175 countries where it +// exists; the fixture is the floor that makes the gate mean something everywhere else. A reader +// comparing two runs has to know which one produced the numbers below. +console.log(`POSTER-BROWSER-EQUIV: measuring with ${SOURCE === CACHE ? 'the offline cache out/_records.json' : 'the committed fixture fixtures/equiv-records-npl-ind.json'} — ${records.length} record(s).`) const assetsBase = pathToFileURL(ASSETS).href const results = [] diff --git a/library/scripts/posters/fixtures/equiv-records-npl-ind.json b/library/scripts/posters/fixtures/equiv-records-npl-ind.json new file mode 100644 index 000000000..eecd3a138 --- /dev/null +++ b/library/scripts/posters/fixtures/equiv-records-npl-ind.json @@ -0,0 +1 @@ +[{"slug":"agaria","name":"Agaria","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"25000","latitude":"23.24272500","longitude":"69.67236400","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"agri","name":"Agri","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"70000","latitude":"23.59500000","longitude":"72.96300000","primary_language":"mar","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Marathi","religion_label":"Hinduism"},{"slug":"anjana-patel-gujarati","name":"Anjana Patel (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"349000","latitude":"22.85345800","longitude":"72.14596900","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"bafan","name":"Bafan","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"600","latitude":"23.25708900","longitude":"69.66866000","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"bairagi-gujarati","name":"Bairagi (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"510000","latitude":"21.52446100","longitude":"70.45606100","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"bamcha","name":"Bamcha","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"5700","latitude":"22.25631400","longitude":"71.19128600","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"baniya","name":"Baniya","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"217000","latitude":"26.97589200","longitude":"85.34782000","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"banjania","name":"Banjania","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"35000","latitude":"24.18310300","longitude":"72.42584200","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"barae","name":"Barae","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"60500","latitude":"26.87503500","longitude":"85.57834900","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"barot","name":"Barot","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1700","latitude":"23.58788100","longitude":"72.36511900","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"barthari","name":"Barthari","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"16500","latitude":"22.79271400","longitude":"73.54118600","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"bhand","name":"Bhand","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"17000","latitude":"29.64410500","longitude":"80.50954500","primary_language":"urd","religion":"MSN","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Urdu","religion_label":"Islam - Sunni"},{"slug":"bhediyar","name":"Bhediyar","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"30500","latitude":"26.97077500","longitude":"85.32420100","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"bhodala","name":"Bhodala","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"14500","latitude":"22.82636400","longitude":"69.35677200","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"bodo","name":"Bodo","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A018","label":"Tibetan Peoples"},"population":"4900","latitude":"26.78124000","longitude":"88.08058000","primary_language":"brx","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Boro (India)","religion_label":"Hinduism"},{"slug":"borpi","name":"Borpi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"950","latitude":"20.60325300","longitude":"72.93564700","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"byangsi","name":"Byangsi","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A018","label":"Tibetan Peoples"},"population":"2700","latitude":"29.83070200","longitude":"81.88682300","primary_language":"bee","religion":"BLA","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Byangsi","religion_label":"Buddhism - Tibetan"},{"slug":"caki","name":"Caki","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1300","latitude":"22.83470000","longitude":"69.35487500","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"champta","name":"Champta","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"4400","latitude":"22.26265100","longitude":"70.77523800","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"chidmar","name":"Chidmar","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"21000","latitude":"28.05609700","longitude":"81.62803200","primary_language":"npi","religion":"HOF","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism - Folk"},{"slug":"churaute","name":"Churaute","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"8400","latitude":"26.66000000","longitude":"86.89000000","primary_language":"npi","religion":"MSN","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Islam - Sunni"},{"slug":"cunara","name":"Cunara","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"2500","latitude":"22.28140300","longitude":"70.75392200","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"dafer","name":"Dafer","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"275","latitude":"21.05444500","longitude":"70.53110500","primary_language":"kfr","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Hinduism"},{"slug":"dangasiya","name":"Dangasiya","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"4400","latitude":"22.77258900","longitude":"71.59743100","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"dasnami-bawa","name":"Dasnami Bawa","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"7300","latitude":"21.80000000","longitude":"70.75000000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"depala","name":"Depala","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"650","latitude":"22.98000000","longitude":"71.47000000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"dhobi","name":"Dhobi","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"126000","latitude":"27.00708400","longitude":"84.99578800","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"dhunia","name":"Dhunia","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A019","label":"Himalayan Peoples"},"population":"2100","latitude":"26.80680900","longitude":"85.83611800","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"dudhwala","name":"Dudhwala","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"2900","latitude":"22.30716100","longitude":"73.18121300","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"dura","name":"Dura","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"8800","latitude":"28.16038500","longitude":"84.30856200","primary_language":"npi","religion":"BOF","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Buddhism - Folk"},{"slug":"baloch","name":"Eastern Baloch","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A005","label":"Persian-Median"},"population":"97000","latitude":"21.29145000","longitude":"70.40546400","primary_language":"urd","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Urdu","religion_label":"Islam - Sunni"},{"slug":"gadhai","name":"Gadhai","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"750","latitude":"21.62000000","longitude":"71.23000000","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"galiara","name":"Galiara","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"550","latitude":"21.76577200","longitude":"72.15525800","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"gangai","name":"Gangai","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"53500","latitude":"26.44488200","longitude":"87.44065300","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"garmatan","name":"Garmatan","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"70","latitude":"22.45078100","longitude":"70.05878100","primary_language":"kfr","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Hinduism"},{"slug":"garvi","name":"Garvi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1300","latitude":"21.51835000","longitude":"70.45524700","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"gavli","name":"Gavli","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"17000","latitude":"22.29984200","longitude":"70.79480000","primary_language":"hin","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Hindi","religion_label":"Hinduism"},{"slug":"ghantiya","name":"Ghantiya","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"350","latitude":"21.76227500","longitude":"72.14930300","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"golarana","name":"Golarana","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"950","latitude":"23.81568600","longitude":"72.94855600","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"gosain-gujarati","name":"Gosain (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"85000","latitude":"21.34285000","longitude":"71.30763100","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"gyasumdoba","name":"Gyasumdoba","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"5800","latitude":"28.71230700","longitude":"84.25504200","primary_language":"gyo","religion":"BLA","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gyalsumdo","religion_label":"Buddhism - Tibetan"},{"slug":"hajjam-gujarati","name":"Hajjam (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"47000","latitude":"23.24377200","longitude":"69.67550500","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"halaypotra","name":"Halaypotra","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"4200","latitude":"23.68558300","longitude":"69.47986700","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"halkhor","name":"Halkhor","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"6200","latitude":"27.02597300","longitude":"84.91060100","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"haluwai","name":"Haluwai","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"86500","latitude":"26.76295500","longitude":"86.22268100","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"hingora","name":"Hingora","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"400","latitude":"23.26111100","longitude":"68.82666700","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"hingorza","name":"Hingorza","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"400","latitude":"23.07086400","longitude":"70.12964200","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"jaine","name":"Jaine","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1700","latitude":"27.70000000","longitude":"85.33333300","primary_language":"npi","religion":"OJA","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Other - Jainism"},{"slug":"jat-muslim","name":"Jat Muslim","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"645000","latitude":"23.71461400","longitude":"69.84301100","primary_language":"snd","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Sindhi","religion_label":"Islam - Sunni"},{"slug":"juneja","name":"Juneja","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"225","latitude":"23.89463300","longitude":"69.73679400","primary_language":"hin","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Hindi","religion_label":"Islam - Sunni"},{"slug":"kahar-gujarati","name":"Kahar (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"9000","latitude":"22.45279900","longitude":"72.78759700","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"kaike","name":"Kaike","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A019","label":"Himalayan Peoples"},"population":"2400","latitude":"28.87070000","longitude":"83.14550000","primary_language":"kzq","religion":"EAN","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kaike","religion_label":"Ethnoreligion - Animism"},{"slug":"kamalia","name":"Kamalia","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"13500","latitude":"23.50260000","longitude":"72.04440300","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"kamar","name":"Kamar","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"15000","latitude":"27.75240800","longitude":"85.01562400","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"kambodia-bhagat","name":"Kambodia Bhagat","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1300","latitude":"24.29063900","longitude":"71.74266100","primary_language":"rwr","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Marwari (India)","religion_label":"Hinduism"},{"slug":"kanu","name":"Kanu","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"164000","latitude":"26.99105800","longitude":"85.05256400","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"kapadi","name":"Kapadi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"6300","latitude":"23.65680000","longitude":"69.70260000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"kasar-gujarati","name":"Kasar (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"45500","latitude":"23.02671100","longitude":"72.46388800","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"kasbati","name":"Kasbati","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"25000","latitude":"21.52218400","longitude":"70.45787700","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"kathi","name":"Kathi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"19000","latitude":"22.30306700","longitude":"70.79685000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"kayastha","name":"Kayastha","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"79000","latitude":"26.48037300","longitude":"87.27548800","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"ker","name":"Ker","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"425","latitude":"23.81270000","longitude":"68.77225800","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"khalpa","name":"Khalpa","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"53500","latitude":"23.58796100","longitude":"72.36932500","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"khaskeli","name":"Khaskeli","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"600","latitude":"23.29216900","longitude":"70.33883800","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"khatik-gujarati","name":"Khatik (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"35000","latitude":"21.16693300","longitude":"73.54342200","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"langa","name":"Langa","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"475","latitude":"23.24051400","longitude":"69.66505600","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"lodha","name":"Lodha","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"42500","latitude":"27.51882000","longitude":"83.30012300","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"machhiyara","name":"Machhiyara","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"190000","latitude":"22.47000000","longitude":"70.07000000","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"majothi","name":"Majothi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"750","latitude":"23.65540000","longitude":"69.70300000","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"makalu-sherpa","name":"Makalu Sherpa","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A018","label":"Tibetan Peoples"},"population":"1600","latitude":"27.62575000","longitude":"87.23230000","primary_language":"xsr","religion":"BLA","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Sherpa","religion_label":"Buddhism - Tibetan"},{"slug":"makrani","name":"Makrani","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"33000","latitude":"21.51840000","longitude":"70.46710000","primary_language":"bcc","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Balochi, Southern","religion_label":"Hinduism"},{"slug":"mali","name":"Mali","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"19500","latitude":"27.01946300","longitude":"84.87856000","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"mallah","name":"Mallah","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"199000","latitude":"26.45474500","longitude":"87.29000100","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"mandali-muslims","name":"Mandali Muslims","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1700","latitude":"23.07730000","longitude":"72.08140000","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"marwadi","name":"Marwadi","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"75500","latitude":"26.47709600","longitude":"87.28312400","primary_language":"npi","religion":"HOF","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism - Folk"},{"slug":"mer","name":"Mer","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"6100","latitude":"21.63987500","longitude":"69.63065300","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"mir","name":"Mir","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"48500","latitude":"22.30716100","longitude":"73.18121300","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"miyana","name":"Miyana","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"41500","latitude":"23.70606400","longitude":"69.82952500","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"moghol-gujarati","name":"Moghol (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"6500","latitude":"23.54242100","longitude":"70.87557300","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"mujavar","name":"Mujavar","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"700","latitude":"23.68846134","longitude":"69.20593142","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"muslim-khatri","name":"Muslim Khatri","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"73500","latitude":"23.23557000","longitude":"69.67482800","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"muslim-lakhera","name":"Muslim Lakhera","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"2200","latitude":"22.82086200","longitude":"73.74778600","primary_language":"urd","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Urdu","religion_label":"Islam - Sunni"},{"slug":"muslim-patel","name":"Muslim Patel","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1500","latitude":"21.19500000","longitude":"72.81944400","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"mutwa","name":"Mutwa","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1400","latitude":"23.66612300","longitude":"69.60040000","primary_language":"kfr","religion":"HOF","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Hinduism - Folk"},{"slug":"narsinghpura","name":"Narsinghpura","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"75000","latitude":"22.60993000","longitude":"73.46264000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"nayak-muslims","name":"Nayak Muslims","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"8500","latitude":"22.30181900","longitude":"70.75141100","primary_language":"hin","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Hindi","religion_label":"Islam - Sunni"},{"slug":"node","name":"Node","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"3800","latitude":"23.42421100","longitude":"69.67644500","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"nurang","name":"Nurang","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A019","label":"Himalayan Peoples"},"population":"475","latitude":"26.48275700","longitude":"87.52729300","primary_language":"npi","religion":"HOF","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism - Folk"},{"slug":"padhar","name":"Padhar","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"37500","latitude":"22.77271400","longitude":"71.98728200","primary_language":"guj","religion":"HOF","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism - Folk"},{"slug":"pahari-nagarkotis","name":"Pahari Nagarkotis","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1500","latitude":"27.70000000","longitude":"85.33333300","primary_language":"phj","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Pahari","religion_label":"Hinduism"},{"slug":"panar","name":"Panar","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1800","latitude":"21.17048900","longitude":"72.83739400","primary_language":"hin","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Hindi","religion_label":"Islam - Sunni"},{"slug":"paradhi","name":"Paradhi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"8700","latitude":"22.84046100","longitude":"69.72556100","primary_language":"kfr","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Hinduism"},{"slug":"patanwadia","name":"Patanwadia","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"55000","latitude":"23.03340300","longitude":"72.58285000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"patni-jamat","name":"Patni Jamat","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1700","latitude":"23.84862300","longitude":"72.12710500","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"patni-vankars","name":"Patni Vankars","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"325","latitude":"23.03340000","longitude":"72.58440000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"pomla","name":"Pomla","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1300","latitude":"21.17000000","longitude":"72.83000000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"puma","name":"Puma","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A019","label":"Himalayan Peoples"},"population":"5500","latitude":"27.00500000","longitude":"86.87200000","primary_language":"pum","religion":"BLA","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Puma","religion_label":"Buddhism - Tibetan"},{"slug":"rajbhar","name":"Rajbhar","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"41500","latitude":"27.43318400","longitude":"83.84738100","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"raji-nepal","name":"Raji","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A019","label":"Himalayan Peoples"},"population":"3100","latitude":"28.50063400","longitude":"80.92791500","primary_language":"rji","religion":"HOF","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Raji","religion_label":"Hinduism - Folk"},{"slug":"rathodia","name":"Rathodia","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"700","latitude":"22.30392900","longitude":"73.40310100","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"raysipotra","name":"Raysipotra","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1500","latitude":"23.67123700","longitude":"69.71388000","primary_language":"kfr","religion":"MOF","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Folk"},{"slug":"royma","name":"Royma","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"425","latitude":"23.66555100","longitude":"69.90090200","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"sagar","name":"Sagar","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"18500","latitude":"21.52218400","longitude":"70.45787700","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"sandhai-muslims","name":"Sandhai Muslims","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1500","latitude":"21.52333900","longitude":"70.45605000","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"saranias","name":"Saranias","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"5900","latitude":"23.83557500","longitude":"72.99882800","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"sayyid-gujarati","name":"Sayyid (Gujarati)","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"176000","latitude":"21.10977300","longitude":"73.39480400","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"shaikh-bhojpuri","name":"Shaikh (Bhojpuri)","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"323000","latitude":"27.01233600","longitude":"84.86936800","primary_language":"bho","religion":"MSN","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Bhojpuri","religion_label":"Islam - Sunni"},{"slug":"shravan","name":"Shravan","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"50","latitude":"21.53231900","longitude":"70.45185700","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"siddi","name":"Siddi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"34500","latitude":"21.16930300","longitude":"70.59704300","primary_language":"guj","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Islam - Sunni"},{"slug":"sompura-salat","name":"Sompura Salat","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"21500","latitude":"22.30000000","longitude":"70.78000000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"sudhi","name":"Sudhi","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A019","label":"Himalayan Peoples"},"population":"154000","latitude":"26.76260100","longitude":"85.91716400","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"surel","name":"Surel","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"350","latitude":"27.98000000","longitude":"85.93000000","primary_language":"npi","religion":"H","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Nepali","religion_label":"Hinduism"},{"slug":"tai","name":"Tai","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"23000","latitude":"23.12632000","longitude":"72.04277500","primary_language":"urd","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Urdu","religion_label":"Islam - Sunni"},{"slug":"targala","name":"Targala","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"42500","latitude":"23.58796100","longitude":"72.36932500","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"theba","name":"Theba","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"750","latitude":"23.25708900","longitude":"69.66866000","primary_language":"kfr","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Islam - Sunni"},{"slug":"tirgar","name":"Tirgar","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"17500","latitude":"22.73910000","longitude":"72.44890000","primary_language":"guj","religion":"HOF","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism - Folk"},{"slug":"tseku","name":"Tseku","country_code":"NPL","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A018","label":"Tibetan Peoples"},"population":"6500","latitude":"27.12243000","longitude":"87.85420000","primary_language":"tsk","religion":"BLA","country_code_label":"Nepal","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Tseku","religion_label":"Buddhism - Tibetan"},{"slug":"turi-barot","name":"Turi Barot","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"13500","latitude":"22.73020800","longitude":"71.63766900","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"vadi","name":"Vadi","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"16500","latitude":"21.49100000","longitude":"70.10400000","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"vahivanca-barot","name":"Vahivanca Barot","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"6600","latitude":"23.58733600","longitude":"72.37486900","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"},{"slug":"vayati","name":"Vayati","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"16000","latitude":"23.82529400","longitude":"72.98514200","primary_language":"gbl","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gamit","religion_label":"Hinduism"},{"slug":"vyapari","name":"Vyapari","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1000","latitude":"23.12363800","longitude":"72.05274200","primary_language":"urd","religion":"MSN","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Urdu","religion_label":"Islam - Sunni"},{"slug":"wagheri","name":"Wagheri","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1500","latitude":"22.33122300","longitude":"70.21605600","primary_language":"kfr","religion":"HOF","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Kacchi","religion_label":"Hinduism - Folk"},{"slug":"wandharo","name":"Wandharo","country_code":"IND","wagf_region":"asia","wagf_block":"south_asia","rop1":{"value":"A012","label":"South Asian Peoples"},"population":"1900","latitude":"22.71979400","longitude":"71.64931700","primary_language":"guj","religion":"H","country_code_label":"India","wagf_region_label":"Asia","wagf_block_label":"South Asia","primary_language_label":"Gujarati","religion_label":"Hinduism"}] diff --git a/library/scripts/posters/generate.mjs b/library/scripts/posters/generate.mjs index 22f7ff936..3ab20ba26 100644 --- a/library/scripts/posters/generate.mjs +++ b/library/scripts/posters/generate.mjs @@ -34,7 +34,13 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); const DATA = process.env.UPG100_DATA_PATH ? resolve(process.env.UPG100_DATA_PATH) : resolve(__dirname, '..', '..', '..', 'plugin-designs', 'my-upg-100-list', 'data'); -const OUT = join(__dirname, 'out'); +// OUT_DIR lets a caller write somewhere private instead of the shared out/. out/posters/ is +// gitignored but SHARED, and other gates read it: check:zone-census counts the sheets there to +// decide whether every selectable zone has a poster. A checker that runs this generator for its own +// comparison therefore has to write elsewhere, or it leaves two real sheets behind and the next gate +// reads them as a half-finished poster build. Measured: exactly that turned check:zone-census from +// NOT MEASURED into FAIL ("28 selectable zone(s) have NO poster") on a fresh checkout. +const OUT = process.env.OUT_DIR ? resolve(process.env.OUT_DIR) : join(__dirname, 'out'); const POSTERS = join(OUT, 'posters'); mkdirSync(POSTERS, { recursive: true }); @@ -116,7 +122,11 @@ const FIELDS = 'slug,name,country_code,wagf_region,wagf_block,rop1,population,la // ── fetch the live pins (the only network call; happens at GENERATE time only) ─ async function loadRecords() { - const cache = join(__dirname, 'out', '_records.json'); + // RECORDS_FILE lets a caller name the offline input instead of only the API-written cache. The + // equivalence check needs BOTH sides fed from the same records, and out/_records.json is + // gitignored — so without this the Node side could only ever run where a live API had already + // written that file, which is what left that gate inert on every fresh checkout. + const cache = process.env.RECORDS_FILE || join(__dirname, 'out', '_records.json'); if (process.env.OFFLINE) { try { return readJSON(cache); } catch { /* fall through */ } } const url = `${API}/api/people-groups/list?fields=${FIELDS}&lang=en`; const resp = await fetch(url, { headers: { accept: 'application/json' } }); diff --git a/package.json b/package.json index bb5502428..2135c7882 100644 --- a/package.json +++ b/package.json @@ -619,7 +619,7 @@ "check:gospel-set-fit": "the set charts FIT the canvas they are given. renderWorldCopies:false puts a hard floor under the zoom at log2(canvasWidth/512) — one world must fill the canvas WIDTH — and on a wide, short figure that floor is too close for the drawing's own height, so the outermost groups fall outside the frame (measured at 1440: 54 outside in ar, 97 in en, which is what proved it was the width and not RTL). Pure arithmetic against the components' own projection, so no browser and no drift. Negative control: the old 0.17 extentFraction still fails 796x249 at 271px of 169, so a pass cannot be vacuous. Also asserts both charts share one footprint, or the same population reads as a different size when a reader switches tabs.", "check:sentence-slots": "a translated SENTENCE that carries values stays ONE key, through library/composables/useSentence.js. Four properties that all fail silently: a translator can REORDER the clauses (the slots follow the message, not the call); a missing slot leaves its placeholder VISIBLE rather than rendering null or an empty gap, while 0 and '' are real values; slotted markup (a bold count, a dir=ltr island) goes in as a VALUE and is never translated around; and English renders as it did before the migration. Exists because the pattern it replaces built sentences by concatenating translated fragments around untranslated text — 'languages have', 'people.' — which in Arabic gives Arabic words in English clause order: grammatically broken, and worse than leaving it English because it looks translated. Sentinels are private-use (U+E000+n) so nothing in the i18n pipeline may rewrite them, and any sentinel already in a message is stripped before ours are placed — without that a stray swallowed a slot and the arm still passed, which is how this gate found its own weakness.", "check:people-group-records": "the records half of the print standard selects EXACTLY the set it is asked for, two-sided: a country selector returns that country and not another, an unknown selector returns nothing rather than every group on earth, one fetch per language serves every item, and a failed fetch is not cached so the next click retries.", - "check:poster-browser-equiv": "a map sheet GENERATED IN THE BROWSER (library/packet/posterSheets.js, the print standard: generate at the click) is byte-identical to the one the Node generator writes, given the same records: it runs the real generate.mjs for one UPG-100 zone (the map-only packet sheet, an India zone so the ADM1 path runs) and one country, draws both through the browser feed (the SERVED boundaries, data/zone-sheet.js, the library name table) and compares bytes. The drawing code is one factory (poster-render.js); this guards the FEED, which is what can still drift. NOT MEASURED without the generator's offline records cache.", + "check:poster-browser-equiv": "a map sheet GENERATED IN THE BROWSER (library/packet/posterSheets.js, the print standard: generate at the click) is byte-identical to the one the Node generator writes, given the same records: it runs the real generate.mjs for one UPG-100 zone (the map-only packet sheet, an India zone so the ADM1 path runs) and one country, draws both through the browser feed (the SERVED boundaries, data/zone-sheet.js, the library name table) and compares bytes. The drawing code is one factory (poster-render.js); this guards the FEED, which is what can still drift. Measures on a fresh checkout: it reads the API-written cache (out/_records.json) when present and otherwise the committed fixture (library/scripts/posters/fixtures/equiv-records-npl-ind.json, the 124 public records the two arms consume), feeds BOTH sides from that same file via RECORDS_FILE, and says which input it measured.", "check:poster-render-pinned": "the map-sheet generator a browser imports at print time (served at assets/lib/poster-render.js, not bundled) is integrity-pinned like every embed, because it executes on partner pages: the pin in library/packet/poster-render.integrity.js equals the sha384 of the source and of the served copy (a stale pin names `bun run pin:poster-render`), a TAMPERED copy is refused and its code never runs (a planted side effect stays unset), and the genuine copy loads and draws.", "pin:poster-render": "rewrite library/packet/poster-render.integrity.js from library/packet/poster-render.js — run after any change to the generator; check:poster-render-pinned fails until it is.", "check:board-map-options": "the GEOGRAPHIC map caller must state whiteboard/boundaries EXPLICITLY, never inherit them. library/maps/whiteboard-map.js defaults to whiteboard:true/boundaries:false (it was extracted for the whiteboard case), the inverse of what a real map needs, so a caller relying on defaults renders a blank basemap. check:gospel-whiteboard cannot see this — it asserts chart geometry and imports no component."