From 461156ed3360721b43338d786aa5baf43c763424 Mon Sep 17 00:00:00 2001 From: Omar Eid Date: Fri, 7 Aug 2026 07:56:05 -0500 Subject: [PATCH 1/2] Track B: the wrapper, and the store that will not take it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PLAN.md §Track B says "Capacitor iOS, then Android". On the licences this repo actually vendors that order inverts: Android is reachable and the App Store is the blocked one. A GPL'd binary on Apple's store needs a §7 additional permission from every copyright holder. Hifth cannot assemble one. The Quranic Arabic Corpus grants the GPL and then says CHANGING IT IS NOT ALLOWED — a §7 grant is a change to the terms and only Kais Dukes can make it. quran-tajweed is CC BY 4.0, whose §2(a)(5)(B) forbids the technological measures FairPlay applies. KFGQPC's own terms are still unread (board item #55), and a store submission is exactly the context where that stops being deferrable. Three things fell out of writing it down, none of them fixed here: - assets/adj/** carries span/toSpan values computed by sharedRuns out of the GPL'd QAC morphology (build-adjacency.mjs:45, :287, :342). LICENSES.md:17 names only Waqar144's terms. Wrong today, independent of Track B. - Track B's payload has narrowed to one load-bearing promise. The corpus bundling is done by Loop 6b, the iPad spread became a web concern, and navigator.share exists. What survives is iOS deep links into an installed app — on the platform whose store is the blocked one. - ShareSheet.tsx builds share URLs from window.location.origin, which under a wrapper is capacitor://localhost/. Every shared hop link would be unopenable by the recipient. Measured while here: the whole corpus is 27.87 MB gz across 1,584 files, which retires the delivery plan's On-Demand-Resources concern outright. Nothing is built and nothing should be until §⑦ ② is settled by someone qualified. This file is the scoping of record and the reason for the gate. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EuhvbUKjGesE3uMhjCzBGt --- docs/design/track-b-native.md | 196 ++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 docs/design/track-b-native.md diff --git a/docs/design/track-b-native.md b/docs/design/track-b-native.md new file mode 100644 index 0000000..15b7f78 --- /dev/null +++ b/docs/design/track-b-native.md @@ -0,0 +1,196 @@ +# Track B: the wrapper, and the store that will not take it + +> Read this *before* writing a line of Capacitor config. The blocker is not technical and +> it is not iOS-specific engineering — it is a licence Hifth does not own, on data Hifth +> cannot drop, and the order [`PLAN.md`](../PLAN.md) §Track B states is not achievable in +> that order. + +**Status:** scoping of record for Track B. Nothing is built and nothing should be until the +question in ① is settled. Everything below is measured against the repo at +[`5dc227d`](../../) or cited to a file; the licence reading is an argument, and §⑦ ② names +what would settle it properly. + +## How to read this, and what it is not + +`docs/decisions/loop-*.md` record what a finished loop settled; +[`docs/design/`](.) is the document you consult *before* changing something. Track B has no +loop and no code, so this file is the whole of it. + +Its companions, cited rather than restated: + +- [`SOURCES.md`](../../SOURCES.md) — every upstream's terms, verbatim, with provenance. + This file argues from those terms; it does not re-derive them, and where it quotes it + quotes the same words `gate:license-copy` binds to `Colophon.tsx`. +- [`LICENSES.md`](../../LICENSES.md) — the per-path bucket map. §③ argues one of its rows + is wrong. +- [`docs/research/2026-07-20-mobile-svg-pwa.md`](../research/2026-07-20-mobile-svg-pwa.md) + §6 — the iOS deep-link caveat that is the *stated* reason Track B exists. + +**This is not a plan to ship an app.** It is the reason the plan that exists says the wrong +thing, and what a correct one would have to answer first. + +--- + +## ① The order in `PLAN.md` is backwards + +[`PLAN.md`](../PLAN.md) §Track B reads "Capacitor iOS, then Android", with Android as a +"~95% shared code" fast-follow. On the licences this repo actually vendors, that order +inverts: **Android is reachable and the App Store is the blocked one.** + +Hifth is GPL-3.0-or-later ([`LICENSES.md`](../../LICENSES.md), and the reasoning for plain +GPL over AGPL is there too). A GPL'd binary on Apple's App Store is the oldest known +conflict in this space: Apple's terms impose per-device installation limits and DRM that +GPL §6 and §10 do not permit a distributor to add. The projects that ship anyway — +Signal, OsmAnd, VLC's eventual settlement — all do it the same way, by having **every +copyright holder** grant an additional permission under GPL §7. + +Hifth cannot assemble that grant, because it is not the only copyright holder in the +shipped bytes. + +## ② What is in the way, specifically + +Three vendored corpora, three different problems, and only one of them is fixable by us. + +**The Quranic Arabic Corpus** (`packages/etl/data/roots/`, © 2011 Kais Dukes) is the hard +one. Its own header — quoted verbatim in [`SOURCES.md`](../../SOURCES.md#quranic-arabic-corpus) +and pinned into the app's colophon by `gate:license-copy` — grants the GPL and then says +copies may be distributed but **"CHANGING IT IS NOT ALLOWED"**. `SOURCES.md` already records +that this is in tension with GPL §5 and explains how Hifth satisfies both readings: vendor +the file verbatim, derive the shards at build time. That resolution works for a website. It +does not extend to granting a §7 App Store permission, because a §7 additional permission is +a *change to the licensing terms*, and it can only be granted by the copyright holder. Kais +Dukes is not reachable through a repo commit. + +**quran-tajweed** (`assets/skins/**`) is CC BY 4.0, and CC BY 4.0 §2(a)(5)(B) forbids +applying "Effective Technological Measures" to the licensed material where doing so +restricts the rights the licence grants. App Store FairPlay is exactly such a measure. This +one is real but narrower than the QAC problem: the skin is one edition among several and +could in principle be omitted from a store build. The QAC-derived data cannot — see ③. + +**KFGQPC** (`assets/pages/**`, `packages/etl/data/**`) is neither GPL nor CC; it is "each +source's own terms", and [board item #55](../issues.md) — confirming those terms with a +human at qurancomplex.gov.sa — is still open. A store submission is precisely the context +in which "we have not read the terms" stops being deferrable. + +## ③ `LICENSES.md:17` understates the exposure + +`LICENSES.md` buckets `apps/web/public/assets/adj/**` under "Free use with attribution +(inherited) — Waqar144's", i.e. the mutashabihat dataset's terms alone. That was true when +the shards carried only edge endpoints. It is no longer true. + +[`build-adjacency.mjs:45`](../../packages/etl/scripts/build-adjacency.mjs) imports +`wordsByAyah` and `sharedRuns` from +[`morphology.mjs`](../../packages/etl/scripts/morphology.mjs), whose own header states what +it reads: the Quranic Arabic Corpus morphology. `spansOf` (`:287`) calls `sharedRuns`, and +the result is written into every shard at `:342` as `span` / `toSpan`. So the shipped +adjacency shards contain values *computed from* GPL'd data — under the same strict reading +of "derivative" that this repo applies to itself elsewhere, `assets/adj/**` is a GPL +derivative and the row in `LICENSES.md` names one of its two parents. + +This matters here and not on the web, and that asymmetry is the point: on a static site the +GPL is satisfied by construction (the browser is handed the whole bundle; §4–6 are already +discharged, which is the argument `LICENSES.md` makes for plain GPL over AGPL). Inside a +store binary it is the thing that has to be licensed, and the licence has a hole in it. + +**This row should be corrected regardless of whether Track B ever happens**, because it is +wrong today. It is ⑦ ① below. + +## ④ What Track B was actually for, and how much of it survives + +The stated payload in `PLAN.md` is: bundle the corpus offline, native share sheet, +**Universal Links**, haptics, state restoration, iPad spread, App Store review notes. + +Reading them one at a time against what the web build now does: + +| Promise | Still worth a wrapper? | +|---|---| +| Corpus bundled, offline by default | **No.** Loop 6b ships pin-a-juz packs over Cache Storage, and §⑤ says the *whole* print is smaller than the delivery plan assumed. | +| Universal Links | **This is the one.** Research §6 is a genuine platform limit: a tapped hop link cannot open an installed iOS PWA. | +| Native share sheet | Partly — `navigator.share` already exists; the wrapper buys the fallback, not the feature. | +| iPad two-page spread | **No.** [`PLAN.md:1038`](../PLAN.md) already records this became a web concern; `desktop.md` shipped it. | +| Haptics, state restoration | Nice, small, not a reason. | + +So the honest summary is that Track B has narrowed to **one** load-bearing promise — deep +links into an installed app on iOS — and that promise is on the platform whose store is the +one blocked. `PLAN.md:1297` also cites this as "research §5"; §5 is *"Offline: quota is a +non-issue; eviction is the issue"* and §6 is the deep-link caveat. The citation is off by +one and is ⑦ ③. + +## ⑤ The corpus is smaller than the risk register assumes + +Measured, not estimated — `pnpm gate:assets` on the tree at time of writing: + +``` +26834.4 KB gz 604 files pages/hafs-kfqc + 885.6 KB gz 604 files words/hafs-kfqc + 532.3 KB gz 147 files roots/hafs-kfqc + 207.7 KB gz 115 files skins/hafs-kfqc + 79.5 KB gz 114 files adj/hafs-kfqc +gate:assets — OK (28539.5 KB gz across 1584 files in 5 trees) +``` + +**27.87 MB gzipped, 1,584 files.** That is under every app-store size threshold that would +have forced staged delivery, and it retires the delivery plan's On-Demand-Resources / +asset-pack concern outright: an iOS or Android binary can simply contain the whole mus'haf. +One fewer reason to build Track B, and one fewer risk if it is ever built. + +## ⑥ One thing that would break the day a wrapper shipped + +[`ShareSheet.tsx`](../../apps/web/src/components/ShareSheet.tsx) builds its share URL from +`window.location.origin + window.location.pathname`. Under a Capacitor wrapper that origin +is the local WebView scheme — `capacitor://localhost/` on iOS, `http://localhost/` on +Android — so every shared hop link would be **unopenable by the recipient**, on any device, +including the sender's own browser. + +It is a small fix (a configured canonical origin rather than the live one) and it is written +down here rather than fixed now for the reason the repo applies elsewhere: a change with no +caller is a change nobody will test. But it is the concrete answer to "how much of the web +build survives wrapping unchanged", and the answer is *not all of it* — which is worth +knowing before anyone budgets Track B as "wrap and ship". + +## ⑦ Open questions, and what would answer each + +### ① `LICENSES.md` buckets `assets/adj/**` under one of its two upstreams · **confirmed** + +The shards carry `span` / `toSpan` values computed by `sharedRuns` out of the GPL'd QAC +morphology (`build-adjacency.mjs:45`, `:287`, `:342`), and the row names only Waqar144's +mutashabihat terms. Independent of Track B and wrong today. + +**What would answer it:** an edit to the row, naming both parents — and a decision about +whether `gate:license-copy`'s reach should extend to `LICENSES.md`'s bucket table, since the +drift here was introduced by a *feature* (`word-D1`, the spans) rather than by anyone +touching a licence file. A gate that notices "an asset tree gained a new upstream" is the +shape that would have caught it. + +### ② Whether the GPL/App-Store reading in ①–③ is right · **open** + +Everything above is argued from licence text by a non-lawyer. The conclusion — that Hifth +cannot assemble a §7 additional permission because one copyright holder is unreachable and +another's terms forbid changes — is the kind of claim this repo requires evidence for, and +"I read the licence" is not the same standard as `gate:*`. + +**What would answer it:** a licensing opinion from someone qualified, scoped to the three +upstreams by name. Until then Track B stays gated and this document stays the reason. + +### ③ `PLAN.md` states an unachievable order and one wrong citation · **open** + +§Track B says "Capacitor iOS, then Android"; §② says the store that blocks is Apple's, so +the reachable order is Android first. `PLAN.md:1297` cites research §5 for the deep-link +caveat, which is §6. + +**What would answer it:** editing both, in a change that also links here — deliberately +*not* done in the commit that introduced this file, because a roadmap edit that changes a +loop's stated order should be its own decision with its own record, not a footnote to a +scoping doc. + +### ④ Whether Track B should exist at all after ④ and ⑤ · **open** + +Its payload has narrowed to one promise (iOS deep links into an installed app) on the one +platform whose store is blocked. The remaining honest options are: drop Track B; ship +Android only and accept the asymmetry; or keep waiting on ⑦ ② and treat the iOS deep-link +gap as a documented limitation the onboarding already respects (research §6 says onboarding +"must not promise link-into-app on iOS", and it does not). + +**What would answer it:** web v1.0 shipping and someone using it. Track B was always gated +on that, and the gate has done its job — a year of platform work was not spent on a wrapper +whose reason has since been half-dismantled by the web build itself. From bdd2c11f9a253a36f819ef6f67e6e1a09b6b4441 Mon Sep 17 00:00:00 2001 From: Omar Eid Date: Fri, 7 Aug 2026 07:56:15 -0500 Subject: [PATCH 2/2] Register Track B's four questions, and point the map at them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/issues.json gains the four rows from the new doc's §⑦, so the register and the document agree the way gate:issues requires: adj-shards-have-two-upstreams confirmed defect — LICENSES.md:17 gpl-and-the-app-store open risk — needs a lawyer track-b-order-is-unachievable open defect — blocked on the above track-b-payload-has-narrowed open question — blocked on web v1.0 The first is confirmed rather than suspected because the code path is cited and checkable: build-adjacency.mjs imports sharedRuns from morphology.mjs and writes its output into every shard. The second is owned by the user, not the agent — a non-lawyer reading licence text is not the standard the rest of this repo holds itself to, and saying so is the honest form of the finding. docs/map.json points provenance at the doc. That feature's gates all satisfy the obligations of a static site, where the browser is handed the whole bundle and §4–6 are discharged by construction. None of them says anything about a store binary, which is a different distribution under the same licences — so the pointer is where a reader learns the gates stop. docs/issues.md is generated (pnpm issues:doc). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EuhvbUKjGesE3uMhjCzBGt --- docs/issues.json | 39 +++++++++++++++++++++++++++++++++++++++ docs/issues.md | 8 ++++++-- docs/map.json | 5 +++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/docs/issues.json b/docs/issues.json index 9a2d4c7..dd92ecd 100644 --- a/docs/issues.json +++ b/docs/issues.json @@ -419,6 +419,45 @@ "note": "ANSWERED 2026-08-07: the label now reads forwards. The one-line fix the row asked for has been made, and the line above the histogram gained a note saying which way the sign runs and that it read the other way for as long as it existed — the row is kept rather than deleted because a label that was wrong from the day it was written is the kind of thing that gets re-introduced by whoever next writes a histogram. `answered` and not `fixed` on purpose: what changed is a console.log string and there is no test that would fail if somebody inverted it again, while the correctness that IS tested — oracleOf's sign convention, pinned in tajweed-fold.test.mjs — was never wrong. Recording that gap is worth more than claiming a closure this repo's definition of `fixed` would refuse. ORIGINAL NOTE FOLLOWS. probe-tajweed-words.mjs prints its miss histogram under 'distance to the expected letter (negative = the fold ran long)'. The convention in lib/tajweed-fold.mjs — documented on oracleOf and pinned by its tests — is the opposite: delta is actual minus stated, so POSITIVE means the letter sits later than the offsets say, which is the fold running long. Numbers unaffected, sentence inverted, one line. Deliberately not fixed in the commit that found it: probe-tajweed-words.mjs and tajweed-words.probe.json were owned by a concurrent session, and a one-word edit that collides is worse than a filed item. Whoever next touches that file should fix the label and delete this row." }, + { + "id": "adj-shards-have-two-upstreams", + "source": { "file": "docs/design/track-b-native.md", "item": "①" }, + "status": "confirmed", + "severity": "defect", + "owner": "agent", + "note": "LICENSES.md buckets apps/web/public/assets/adj/** under 'Free use with attribution (inherited) — Waqar144's', naming the mutashabihat dataset alone. That was true when the shards carried only edge endpoints and stopped being true when word-D1 added the spans. build-adjacency.mjs:45 imports wordsByAyah and sharedRuns from morphology.mjs, whose header states what it reads — the GPL'd Quranic Arabic Corpus morphology; spansOf (:287) calls sharedRuns and the result is written into every shard at :342 as `span` / `toSpan`. So the shipped adjacency shards carry values COMPUTED FROM GPL'd data, and under the same strict reading of 'derivative' this repo applies to itself elsewhere they are a GPL derivative with one of their two parents unnamed. Independent of Track B and wrong today, which is why it is `confirmed` rather than parked with the rest of that document's rows. It matters more inside a store binary than on the web, and the asymmetry is the point: a static site discharges GPL §4–6 by handing the browser the whole bundle, which is LICENSES.md's own argument for plain GPL over AGPL, while a wrapped binary is the thing that has to be licensed. What would answer it: correct the row to name both parents, and decide whether gate:license-copy's reach should extend to the bucket table — the drift here was introduced by a FEATURE rather than by anyone touching a licence file, so the gate that would have caught it is one that notices an asset tree gaining a new upstream." + }, + + { + "id": "gpl-and-the-app-store", + "source": { "file": "docs/design/track-b-native.md", "item": "②" }, + "status": "open", + "severity": "risk", + "owner": "user", + "blockedBy": ["a licensing opinion"], + "note": "Track B's blocker is a licence Hifth does not own. A GPL'd binary on Apple's App Store conflicts with the per-device and DRM terms GPL §6 and §10 do not let a distributor add; the projects that ship anyway (Signal, OsmAnd) do it by having EVERY copyright holder grant an additional permission under §7. Hifth cannot assemble that grant. The Quranic Arabic Corpus header — quoted verbatim in SOURCES.md and pinned into the colophon by gate:license-copy — grants the GPL and then says copies may be distributed but 'CHANGING IT IS NOT ALLOWED'; SOURCES.md already records that tension and resolves it for a website by vendoring verbatim and deriving at build time, but a §7 additional permission IS a change to the licensing terms and only the copyright holder can grant it. quran-tajweed's CC BY 4.0 §2(a)(5)(B) separately forbids applying Effective Technological Measures, which FairPlay is — narrower, because the skin is one edition and could be omitted from a store build, where the QAC-derived data cannot (see adj-shards-have-two-upstreams). And KFGQPC's own terms are still unread by a human (board item #55), which a store submission is exactly the context that stops making deferrable. All of this is argued from licence text by a non-lawyer, and 'I read the licence' is not the standard this repo holds gates to. What would answer it: a licensing opinion from someone qualified, scoped to the three upstreams by name. Until then Track B stays gated and docs/design/track-b-native.md stays the reason." + }, + + { + "id": "track-b-order-is-unachievable", + "source": { "file": "docs/design/track-b-native.md", "item": "③" }, + "status": "open", + "severity": "defect", + "owner": "agent", + "blockedBy": ["gpl-and-the-app-store"], + "note": "PLAN.md §Track B reads 'Capacitor iOS, then Android', with Android as a ~95%-shared-code fast-follow. On the licences this repo vendors that order inverts: the store that blocks is Apple's, so the reachable order is Android first and iOS gated on gpl-and-the-app-store. The same section carries a second, smaller error: it cites the iOS deep-link caveat as 'research §5', and §5 of docs/research/2026-07-20-mobile-svg-pwa.md is 'Offline: quota is a non-issue; eviction is the issue' — the deep-link caveat is §6. Both are one-line edits. Deliberately NOT made in the commit that introduced the scoping doc: a roadmap edit that changes a track's stated order should be its own decision with its own record, not a footnote to a document nobody has reviewed yet. Blocked on the licensing opinion for the same reason — if that opinion comes back saying the §7 route is available after all, the order it dictates changes again, and editing the roadmap twice is worse than editing it once." + }, + + { + "id": "track-b-payload-has-narrowed", + "source": { "file": "docs/design/track-b-native.md", "item": "④" }, + "status": "open", + "severity": "question", + "owner": "user", + "blockedBy": ["web v1.0 and somebody using it"], + "note": "Track B's stated payload was: bundle the corpus offline, native share sheet, Universal Links, haptics, state restoration, iPad two-page spread, App Store review notes. Read one at a time against what the web build now does, most of it has already been delivered or dismissed. Offline-by-default is Loop 6b's pin-a-juz packs, and the whole print is 27.87 MB gz across 1,584 files measured by gate:assets — under every store threshold that would have forced staged delivery, which retires the delivery plan's On-Demand-Resources risk outright. The iPad spread is recorded at PLAN.md:1038 as having become a web concern and desktop.md shipped it. navigator.share already exists; the wrapper buys the fallback, not the feature. Haptics and state restoration are small and are not a reason. What is left is ONE load-bearing promise — Universal Links, i.e. a tapped hop link opening an installed app, which research §6 confirms is a genuine iOS platform limit — and it is on the one platform whose store is blocked. The honest remaining options: drop Track B; ship Android only and accept the asymmetry; or treat the iOS deep-link gap as a documented limitation, which onboarding already respects (research §6 says it must not promise link-into-app on iOS, and it does not). Not decidable from here: what would answer it is web v1.0 shipping and someone using it. Worth recording that the gate did its job — Track B was always gated on v1.0, and in the waiting its reason was half-dismantled by the web build itself rather than by an argument." + }, + { "id": "etl-map-should-generate-itself", "source": { "file": "docs/design/etl-pipeline.md", "item": "①" }, diff --git a/docs/issues.md b/docs/issues.md index 54c6142..1a5b76b 100644 --- a/docs/issues.md +++ b/docs/issues.md @@ -1,5 +1,5 @@ - + # Open items @@ -26,13 +26,17 @@ code, never reproduced. `open` — undecided, nothing blocking. `blocked` — th and unavailable. `answered` — decided, nothing owed in code. `fixed` — closed in code *and* in a test that would fail if it came back; the gate refuses the word without one. -## Open — 22 +## Open — 26 | item | status | severity | owner | waiting on | | --- | --- | --- | --- | --- | +| [`LICENSES.md` buckets `assets/adj/**` under one of its two upstreams](design/track-b-native.md#-licensesmd-buckets-assetsadj-under-one-of-its-two-upstreams--confirmed) | confirmed | defect | agent | — | | [Arabic number agreement outside `distance`](design/i18n.md#-arabic-number-agreement-outside-distance--open) | open | defect | user | a hafiz | | [Does a real fore-edge stack vary?](design/page-transition.md#-does-a-real-fore-edge-stack-vary--open) | open | question | user | — | | [Whether this document should be generated rather than written](design/etl-pipeline.md#-whether-this-document-should-be-generated-rather-than-written--open) | open | question | agent | — | +| [Whether the GPL/App-Store reading in ①–③ is right](design/track-b-native.md#-whether-the-gplapp-store-reading-in--is-right--open) | open | risk | user | a licensing opinion | +| [`PLAN.md` states an unachievable order and one wrong citation](design/track-b-native.md#-planmd-states-an-unachievable-order-and-one-wrong-citation--open) | open | defect | agent | gpl-and-the-app-store | +| [Whether Track B should exist at all after ④ and ⑤](design/track-b-native.md#-whether-track-b-should-exist-at-all-after--and---open) | open | question | user | web v1.0 and somebody using it | | [The CI frame budget is a number from an emulator](backlog.md#-the-ci-frame-budget-is-a-number-from-an-emulator--blocked) | blocked | risk | agent | perf-verdict-on-device | | [Does the fold read at all?](design/page-transition.md#-does-the-fold-read-at-all--blocked) | blocked | question | user | a hafiz on the acceptance phone | | [The same measurement on real mid-tier Android](backlog.md#-the-same-measurement-on-real-mid-tier-android--blocked) | blocked | risk | user | an Android phone | diff --git a/docs/map.json b/docs/map.json index 42c8ea0..ad4298e 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1097,6 +1097,11 @@ "file": "scripts/check-source-offer.mjs", "symbol": "probe", "note": "The offer, followed the way a stranger would follow it: anonymously, no gh and no token, because signed in as ourselves a private repo looks public. Named `check-` and not `gate-` because it reaches the public internet and is deliberately not in `pnpm gates` — it runs on demand (`make source-offer`) and from the public-deploy workflow." + }, + { + "file": "docs/design/track-b-native.md", + "symbol": "Android is reachable and the App Store is the blocked one", + "note": "Where the vendored licences stop being paperwork and start deciding a roadmap. Every gate above satisfies the obligations of a static site, where the browser is handed the whole bundle and GPL §4–6 are discharged by construction; none of them says anything about a store binary, which is a different distribution under the same licences. The doc is the argument that Track B's stated order is not achievable, and §⑦ ② is honest that a non-lawyer reading licence text is not the standard `gate:*` holds everything else to." } ], "extend": [