doxa-maps/library/scripts/posters/series.json
Doxa Maps 11129455e4
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
posters: SERIES is the one switch; header wording joins it; country mode fixed
rega read the rendered page and found a fourth leak site my gate had passed: a
SERIES=country poster still printed 'UNENGAGED PEOPLE GROUPS', 'Unengaged of West
Africa', 'Series: List of 100 UPG's · map 11 of 28' and a side box calling it one
of a 30-map set. I had reported that PASS to three agents as proof the render was
clean. It was not proof: the gate's vocabulary was a HAND LIST of the phrases I
had already found, so it could not see framing I never enumerated.

ONE SWITCH (dx-shepherd's call). SERIES=country now implies the country zone
source, the series name and the header strings. COUNTRIES=1 is kept as an ALIAS
that resolves to SERIES=country, so runs that predate series.json keep working
and now get the matching packet too. Two parameters for one concept is exactly
what let rega's render take the new packet path with a UPG-100 header.

The five header strings move into series.json: kicker, title qualifier, series
name, side-box heading and body. One file owns the wording.

THE GATE NO LONGER DEPENDS ON WHAT I HAPPENED TO KNOW. Its vocabulary is DERIVED
from series.json -- every string a series declares becomes that series' own
fingerprint, so adding wording polices it from that moment. Strings shared
between series are dropped (they identify nothing) and a 12-character floor keeps
short phrases from matching innocent prose. The hand list is kept and merged for
phrases no series declares, like 'Project 7000'.
It also strips HTML and CSS comments before matching: generate.mjs ships design
notes into the SVG that QUOTE these strings, and a correct country poster failed
on five of them. A detector that does not know the comment syntax of what it
reads attacks the documentation of the thing it protects.

FOUND WHILE WIRING IT, a pre-existing break: COUNTRY MODE HAS NOT RUN AT ALL.
generate.mjs read plugin-designs/country-posters/data/countries.json, but
ddde518a8 moved that data to library/data/country-posters.json and the reader was
never updated -- no file at that path on main, so every COUNTRIES=1 run died on
ENOENT. Both paths are now tried, newest first, with an error naming the command
that writes it. Country mode builds 173 countries for the first time.
(node --check passed on the fix while existsSync was still unimported -- a parse
check is not a will-it-run check, and the free variable sat in the one branch my
tests had never reached.)

Verified: country header now reads 'Unreached People Groups / Pray for Republic
of The Gambia / What is a Country Prayer Map?'; the UPG-100 default header is
unchanged; the stale poster still fails as country with 11 real hits, so the
comment strip did not blind the check; COUNTRIES=1 alias renders correctly; all
four packet gates PASS.
2026-09-28 04:57:44 +00:00

149 lines
9.6 KiB
JSON

{
"_meta": {
"purpose": "What differs BETWEEN poster/packet series. One entry per series; SERIES=<id> selects it.",
"why": [
"The country posters shipped rendering the UPG-100 packet's framing: the 'UNENGAGED PEOPLE",
"GROUPS' kicker, 'This packet is 1 of {n} UPG-100 lists', the UPG-100 narrowing funnel, and a",
"below-map block telling the reader to divide the set among thirty disciples. Coherent for ~30",
"UPG-100 zones; incoherent for ~170 countries. Reported by the Driver, 2026-09-28.",
"There was no series parameter anywhere: packet.mjs and packet-render.js knew only one series,",
"so 'the packet' and 'the UPG-100 packet' were the same thing and nothing could disagree.",
"",
"ONE mechanism for BOTH surfaces (dx-shepherd's call): packet.mjs AND generate.mjs read this",
"file, because the leak was in two independent places -- the packet strings and the poster's",
"own furniture (generate.mjs NETWORKS), which is not a packet string at all. Fixing only the",
"first would have left 'Thirty disciples' printing on every country poster."
],
"default": "upg100 -- absent or unknown SERIES resolves to upg100, so existing runs are unchanged.",
"keys": {
"label": "human name, for logs and error messages",
"dataDir": "repo-relative folder holding clusters.json and the selector/normalize/legend modules",
"funnel": "false DROPS the narrowing-funnel page entirely (it is a UPG-100 argument)",
"strings": "overrides merged OVER packet-strings.json's <locale> block, per key",
"networks": "the three below-map blocks generate.mjs prints; ENGLISH ONLY -- see note",
"poster": "the page-1 poster HEADER wording; ENGLISH ONLY, same reason as networks",
"countryMode": "true selects the COUNTRIES zone source (one sheet per country)"
},
"poster_keys": {
"kicker": "the small line above the title (generate.mjs:2426)",
"titleQualifier": "the coloured words before the region name, e.g. 'Unengaged of' (:2427)",
"seriesName": "the name in quotes on the Series line and in the side box (:1877, :1907, :2115)",
"sideBoxHeading": "the right-hand explainer's heading (:2097)",
"sideBoxBody": "that explainer's first paragraph (:2115)"
},
"one_switch": [
"SERIES is the ONE switch (dx-shepherd, 2026-09-28). SERIES=country implies the country zone",
"source, the country series name and the country header strings. COUNTRIES=1 is kept as an",
"ALIAS that sets SERIES=country, so runs that predate this file keep working AND now get the",
"matching packet. Two parameters for one concept is what let rega's country render take the new",
"packet path while its header stayed UPG-100."
],
"english_only_note": [
"`networks` is English-only ON PURPOSE, not an oversight. generate.mjs performs no localization",
"at all: measured zero occurrences of PACKET_LANG, packet-strings or i18n in the file, and its",
"1,728 non-ASCII characters are entirely typographic (box-drawing, em-dashes, middots) with no",
"CJK, Arabic, Cyrillic or Devanagari -- so no translated string has ever been in it",
"(verified independently by regions-plugin, 2026-09-28). The poster surface is English end to",
"end; `strings` below is the half that carries 11 locales."
],
"translation_status": [
"The `country` English below is a DRAFT taken from the Driver's dictated shape and is NOT signed",
"off -- see _draft_awaiting_driver on that entry. NO translations are to be made from it: a",
"paraphrase multiplied by 11 locales is 11 wrong strings. When he signs off the English, the",
"strings go to a HUMAN translator via dx-shepherd, which is this file's established practice --",
"all 11 locales of packet-strings.json carry real translations, never English echoes."
]
},
"upg100": {
"label": "UPG-100 — unengaged people groups, ~30 zoned lists",
"dataDir": "plugin-designs/my-upg-100-list/data",
"countryMode": false,
"funnel": true,
"strings": {},
"poster": {
"kicker": "Unengaged People Groups",
"titleQualifier": "Unengaged of",
"seriesName": "List of 100 UPG's",
"sideBoxHeading": "What is a Prayer List of 100 UPG?",
"sideBoxBody": "This map is one of a {approxLists}-map set called the {seriesName} — a large, overwhelming target in the thousands, organised into clear groupings and displayed on maps and prayer lists."
},
"networks": [
["1 · Thirty disciples.",
"Each follower of Jesus takes their own map and prayer list, and sets apart a place to pray — some have hung a people-group map over their bed."],
["2 · Thirty churches.",
"Each church dedicates a wall in one of its places of prayer, and keeps copies of the prayer list available for distribution."],
["3 · Thirty indigenous leaders.",
"Find leaders on the ground in these areas and give them the map and prayer list, to raise awareness of their unengaged neighbours."]
]
},
"country": {
"label": "Country — one poster per country, ~170 of them",
"dataDir": "plugin-designs/my-upg-100-list/data",
"countryMode": true,
"funnel": false,
"poster": {
"kicker": "Unreached People Groups",
"titleQualifier": "Pray for",
"seriesName": "Country Maps",
"sideBoxHeading": "What is a Country Prayer Map?",
"sideBoxBody": "This map is one of a {approxLists}-map set called the {seriesName} — one sheet for each country, naming the unreached people groups who live there so a reader can pray for them by name."
},
"_poster_why": [
"THE FOURTH LEAK SITE, found by rega reading the rendered page rather than a checker's verdict:",
"a SERIES=country poster still printed 'UNENGAGED PEOPLE GROUPS', 'Unengaged of West Africa',",
"'Series: List of 100 UPG's · map 11 of 28' and a side box calling it 'one of a 30-map set",
"called the List of 100 UPG's'. My check:series-isolation passed because its vocabulary was a",
"HAND LIST of the phrases I had already found -- a PASS from it was only ever a lower bound.",
"seriesName 'Country Maps' is the Driver's own wording, recorded in a generate.mjs design note",
"dated 2026-08-01: 'we'll call this series the Country Map series... inside of the quotes say",
"Country Maps. So that series should be a parameterized field.' The kicker says UNREACHED rather",
"than UNENGAGED because a country sheet lists the unreached groups living there, which is a",
"wider set than the unengaged -- see _draft_awaiting_driver; this wording is part of that draft."
],
"_funnel_why": [
"The funnel narrows every people group on earth down to THIS UPG-100 list (Project 2000/7000/",
"4700/700). That argument does not describe a country poster, and a page of true numbers about",
"the wrong thing is worse than no page. Dropped for country by dx-shepherd, 2026-09-28.",
"Dropping it also removes 12 of the 17 series-specific keys from the translation bill: a page",
"that does not render needs no locales."
],
"_draft_awaiting_driver": [
"THE ENGLISH BELOW IS A DRAFT, NOT APPROVED. It follows the shape the Driver dictated on",
"2026-09-28 but he has not signed off the wording. regions-plugin has asked him to dictate the",
"three blocks as he wants them printed. Do not translate, print at scale, or quote as final",
"until that lands; replace this key with the approved text when it does."
],
"strings": {
"map_page_kicker": "PRAY FOR THIS COUNTRY",
"map_page_sub": "A prayer list of {count} unreached people groups who live here",
"points_intro": "One hour with God, five minutes each. Pray these twelve for the peoples of this country.",
"christian_lede": "This is the same grid — one human life in weeks. Now each box is a share of the people in this country. The shaded boxes are the evangelical share of their population; the rest are waiting."
},
"_strings_why": [
"FOUR keys, not seventeen. Judged by what each string SAYS rather than by matching UPG-100",
"vocabulary: 12 of the 17 are funnel_* keys and drop with the page above; `points` -- the 12",
"prayer points -- is INVARIANT, because those points are about a PEOPLE and a country poster is",
"still praying for the peoples within it; only its framing sentence (points_intro) names the",
"packet. christian_lede is ADAPTED, not replaced: the % Christian vs lost page is just as",
"meaningful for a country, so only 'the people in this list' is reworded.",
"Everything not listed here -- pray_blessed / pray_know / pray_do, the rhythms, the wheel, the",
"list header -- is series-invariant and inherited unchanged."
],
"networks": [
["1 · Disciples.",
"Ask a disciple which country God has put on their heart, then give them that country's poster to print and prepare."],
["2 · Churches.",
"List the churches you know and ask each the same question, so every church has a poster to pray over together."],
["3 · Indigenous leaders.",
"Ask which leaders you know who live in one of these countries, and give them their own country's map to pray for it specifically."]
],
"_networks_why": [
"NOT a find-and-replace of thirty with a hundred and seventy. 'Divide the set among thirty",
"disciples' is coherent at 30 and incoherent at ~170 (172 countries + China + India, per",
"emit-countries.mjs), so the Driver replaced the SHAPE: not 'split the set' but 'ask which one,",
"then give them that poster'. The numbers are gone from the headings for the same reason."
]
}
}