diff --git a/internal/FINDING-library-diverged-from-wt-packet.md b/internal/FINDING-library-diverged-from-wt-packet.md new file mode 100644 index 000000000..edf8d57bf --- /dev/null +++ b/internal/FINDING-library-diverged-from-wt-packet.md @@ -0,0 +1,68 @@ +# FINDING — library/ has diverged two-ways from wt-packet, and absolute paths were hiding it + +**Found** 2026-09-24, while making `check-i18n-parity` repo-relative. +**Status:** path bugs FIXED; the code divergence is REPORTED, NOT RESOLVED — it needs a decision. + +## What was hiding it + +Three gates in this repo defaulted `REPO` to a hardcoded +`/home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-packet`: + +- `check-i18n-parity.mjs` +- `check-locale-reachable.mjs` +- `check-poster-prints.mjs` + +`doxa-maps-plugin-studio` and `wt-packet` are **separate repos, not worktrees of one**. So each of +these gates opened the *other* repo, graded *its* files, and printed PASS for a tree it had never +read. Not a portability nit — a gate pointed at the wrong target reports the target's health while +saying nothing about its subject. All three are now +`resolve(dirname(fileURLToPath(import.meta.url)), '..')`. + +The moment they read their own tree, two real problems surfaced. + +## 1. The locale tree — FIXED (it was a strict subset) + +`it/ro/zh` were 103 keys behind, and every other locale was short too, including +`buttons.json:share` and `shareSteps` — the exact orphan `check-i18n-parity`'s own header describes +it as having been written to catch. The bug it exists for had reappeared in a second repo, unseen. + +Before copying anything, the direction was **measured**: zero keys existed only here, zero +translations disagreed. A strict subset, so a forward copy was provably lossless. Both repos now +report `162 key(s) of known translation debt` — `regions.json` in it/ro/zh, and nothing else. + +## 2. library/ — NOT FIXED, and must NOT be copied the same way + +`check-poster-prints` fails here with `pk.printPacket is not a function`: this repo's +`usePosterPrints.js` predates the prayer-packet action. The tempting move is the one that worked +for the catalogs — copy wt-packet's version over. **Do not**, without reading each file. + +The same measurement that cleared the catalogs *fails* for these. Every one of the six has lines +that exist ONLY here: + +| file | lines only in wt-packet | lines only in studio | +|---|---|---| +| `library/components/poster/PosterWall.vue` | 12 | 9 | +| `library/composables/useCountryOutline.js` | 45 | 3 | +| `library/composables/useMapClustering.js` | 1 | 1 | +| `library/composables/useMapLayers.js` | 46 | 9 | +| `library/composables/useMapProvider.js` | 16 | 3 | +| `library/composables/usePosterPrints.js` | 33 | 1 | + +That is **two-way divergence, not staleness**. A wholesale copy would silently delete studio-side +work — the identical action that was correct for `locales/` is destructive here. What made the +locale sync safe was not that it looked similar; it was the proof that nothing would be lost. + +## What a resolver needs to decide + +1. Is this repo a **consumer** of wt-packet's library (→ reconcile per hunk, then keep it synced by + a mechanism rather than by hand), or does it legitimately **own** a fork of these six files + (→ then the shared gates should not be shared, and this finding closes)? +2. `usePosterPrints.js` is the concrete instance: is `printPacket` wanted here? If yes, port it + with the 1 studio-only line preserved. If no, `check:poster-prints` should not run in this repo. +3. `check:poster-prints`, `check:locale-reachable`, `check:i18n-parity` and `check:tabs-localized` + are all present here but **absent from `gates:post`**, so none of them gate this repo's build. + `check:no-abs-paths` DOES run, which is why the path fixes were required rather than optional. + +Until (1) is answered, the four gates above are runnable by hand and honest about what they find — +which is strictly better than the previous state, where three of them passed by reading someone +else's files. diff --git a/internal/check-locale-reachable.mjs b/internal/check-locale-reachable.mjs index d3454e888..e0d777eb9 100644 --- a/internal/check-locale-reachable.mjs +++ b/internal/check-locale-reachable.mjs @@ -15,10 +15,15 @@ // path (Polylang on WordPress) keeps working. If someone later makes the pages // lang-less, the URL path alone would silently become the only way in. import { readFileSync, readdirSync, existsSync } from 'node:fs' -import { resolve, join } from 'node:path' +import { resolve, join, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' const REPO = process.env.DOXA_REPO - || resolve('/home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-packet') + // FOURTH instance of this pattern in one flight (check-zone-census, check-share-policy, + // check-poster-prints, now this). DOXA_REPO still wins; only the default becomes portable, + // per the idiom check-no-absolute-paths.mjs prints in its own failure text. A gate that + // hardcodes its author's worktree turns build:unlocked red for every other builder. + || resolve(dirname(fileURLToPath(import.meta.url)), '..') const src = readFileSync(join(REPO, 'library/i18n/index.js'), 'utf8') const SUPPORTED = (src.match(/SUPPORTED_LOCALES = \[([^\]]*)\]/) || [])[1] diff --git a/internal/check-poster-prints.mjs b/internal/check-poster-prints.mjs index f63988ab1..c3f15377a 100644 --- a/internal/check-poster-prints.mjs +++ b/internal/check-poster-prints.mjs @@ -19,10 +19,16 @@ // bundle's API being reachable. import { chromium } from 'playwright' import { readFileSync } from 'node:fs' -import { resolve } from 'node:path' +import { resolve, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' const REPO = process.env.DOXA_REPO - || resolve('/home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-packet') + // Third instance of one pattern this flight (after check-zone-census and + // check-share-policy): a gate authored in one worktree hardcodes THAT worktree as its + // fallback, and check:no-abs-paths — which is inside build:unlocked — turns red for every + // other builder. DOXA_REPO still wins; only the default is made portable, using the idiom + // check-no-absolute-paths.mjs prints in its own failure text. + || resolve(dirname(fileURLToPath(import.meta.url)), '..') const src = readFileSync(resolve(REPO, 'library/composables/usePosterPrints.js'), 'utf8') const frame = readFileSync(resolve(REPO, 'library/composables/printInPlace.js'), 'utf8') // The composable dynamically imports its renderers by RELATIVE path. Under a blob