feat(04-04): ONBD-03 home-screen hooks + the boot wiring + the ?dest= harness profile

- homescreen.ts: wireHomeScreen behind the BOTH-halves Bot API 8.0
  guard; 'added' hides (no nag), 'unknown' (always iOS) shows the
  neutral prompt — indeterminate, never an error; homeScreenAdded
  hides; a refused addToHomeScreen is caught, the affordance stays;
  .btn-secondary in the existing strip — no new furniture; NO
  beforeinstallprompt/manifest/service worker (T-04-38)
- main.ts: locale derivation moved above the bindings block; stage 13
  reads BOTH destination carriers, seeds the memory-only holder, builds
  the destination/unavailable surface (null when no id — Phase 3 boot
  byte-identical, D-12); the live register shows the destination
  surface; the ARAHARAH-DEST state-token signal fires unconditionally
- index.html: ?dest=<id> harness profile threaded to the mock's
  startParam; the block stays inside __ARAHARAH_HARNESS__
- HS1-HS9 green (54/54), web:typecheck green
This commit is contained in:
araharah-executor
2026-10-24 01:36:30 +08:00
parent 6e421e6b59
commit c2d78b0c8f
3 changed files with 140 additions and 7 deletions
+10 -2
View File
@@ -9,7 +9,7 @@
<body>
<div id="app"></div>
<script type="module">
/* D-11 Mock-Telegram profile: ?mock=android|ios|tdesktop|macos|web + ?scheme=light|dark + ?pin=1 + ?locale=en|ms + ?fixdelay + ?sessiondelay
/* D-11 Mock-Telegram profile: ?mock=android|ios|tdesktop|macos|web + ?scheme=light|dark + ?pin=1 + ?locale=en|ms + ?fixdelay + ?sessiondelay + ?dest=<id>
Harness-only: served from web/dist-harness, never deployed.
The WHOLE block below is inside `if (__ARAHARAH_HARNESS__)` — Vite's `define`
replaces that identifier with `false` in the production build, so the branch is
@@ -22,6 +22,13 @@
const profile = q.get("mock") || "android";
const scheme = q.get("scheme") === "dark" ? "dark" : "light";
const locale = q.get("locale") === "ms" ? "ms" : "en";
/* The ONBD-02 destination profile (?dest=<id>, 04-04): the value needs
* NO stub on the reader path — page.goto preserves the query string, so
* window.location.search already carries it and the app's real
* readDestinationId parses it. It is threaded to the mock as startParam
* so the SECONDARY carrier (the signed initData's start_param field) is
* exercisable from the harness too. */
const dest = q.get("dest") || null;
/* Boot-stage photography knobs (harness-only): at localhost speeds the
whole session→chain→fix sequence resolves in a few ms, so the staged
BOOT-01 (validating) and BOOT-02 (acquiring) cards cannot hold on
@@ -32,7 +39,7 @@
const fixDelayMs = Number.parseInt(q.get("fixdelay") || "0", 10);
// Set BEFORE main.ts is imported — this is the marker main.ts's install guard checks.
window.__ARAHARAH_MOCK__ = { profile, scheme, locale };
window.__ARAHARAH_MOCK__ = { profile, scheme, locale, dest };
// Stub the endpoints the app calls, OUTSIDE any dead-code-eliminated branch. These
// live in the runner page (not in main.ts) precisely so no import.meta.env guard can
@@ -67,6 +74,7 @@
grantLocation: profile !== "tdesktop",
deliveryDelayMs: fixDelayMs > 0 ? fixDelayMs : undefined,
telegramFix: { lat: 3.1513, lng: 101.6958, accuracyM: 12, headingDeg: null },
startParam: dest ?? undefined,
});
}