fix(deploy): route /dict through caddy to the gateway (local eval)
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 58s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m30s
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 58s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m30s
The edge caddy @gateway matcher was missing /dict/*, so the client's dictionary
fetch fell to the static landing catch-all: it received a non-dawg blob (200 OK),
which the reader parsed into a bogus finder that reports every word missing — a
valid first move showed as illegal with no network fallback. Add /dict/* to the
gateway route.
Hardening + the cross-test that would have caught it:
- reader: reject a blob whose 32-bit size header != its byte length, so a
non-dawg page or a truncated download now throws and the loader falls back to
the network preview instead of silently validating against garbage.
- eval.parity: an adapter conformance suite that drives evaluateLocal through the
real letter-space path (the server alphabet table, a letter board and letter
placements) against the engine — the algorithm-level validate.parity did not
exercise the adapter. validategen now emits the alphabet table for it.
- a CI deploy probe asserts {edge}/dict reaches the gateway (401), not the landing.
- the DebugPanel reports the feature flag, the bad-connection breaker and the
cached dictionaries with their sizes; its reset also clears the dict cache.
This commit is contained in:
@@ -4,18 +4,39 @@
|
||||
// snapshot (no secrets, no initData values, no IP) and shares it through the OS share sheet (or a
|
||||
// clipboard copy on desktop) — a support aid for reproducing client-specific issues, e.g. the
|
||||
// Telegram Android presentation quirks. Drawn from the top, just under the app header.
|
||||
import { onMount } from 'svelte';
|
||||
import { app, closeDebug, resetOnboarding } from '../lib/app.svelte';
|
||||
import { connection } from '../lib/connection.svelte';
|
||||
import { shareText } from '../lib/share';
|
||||
import { telegramChromeDiag } from '../lib/telegram';
|
||||
|
||||
const report = [
|
||||
`app: ${__APP_VERSION__}`,
|
||||
`locale: ${app.locale} theme: ${app.theme} reduceMotion: ${app.reduceMotion}`,
|
||||
`online: ${connection.online} streamAlive: ${app.streamAlive}`,
|
||||
`userId: ${app.session?.userId ?? '—'} guest: ${app.profile?.isGuest ?? '—'}`,
|
||||
telegramChromeDiag(),
|
||||
].join('\n');
|
||||
// The local move-preview snapshot — the feature flag, the bad-connection breaker and the
|
||||
// dictionaries cached in IndexedDB with their sizes — loads async so a report about the
|
||||
// preview is precise. Dynamically imported so the debug panel keeps the dict code lazy.
|
||||
let dictInfo = $state('local eval: …');
|
||||
onMount(() => {
|
||||
void (async () => {
|
||||
try {
|
||||
const m = await import('../lib/dict');
|
||||
const list = await m.listCachedDicts();
|
||||
const cached = list.length ? list.map((d) => `${d.key}=${(d.bytes / 1024).toFixed(0)}KB`).join(' ') : 'none';
|
||||
dictInfo = `local eval: ${m.LOCAL_EVAL_ENABLED ? 'on' : 'off'} breaker: ${m.dictLoadingDisabled() ? 'TRIPPED' : 'ok'}\ndicts cached: ${cached}`;
|
||||
} catch {
|
||||
dictInfo = 'local eval: n/a';
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
const report = $derived(
|
||||
[
|
||||
`app: ${__APP_VERSION__}`,
|
||||
`locale: ${app.locale} theme: ${app.theme} reduceMotion: ${app.reduceMotion}`,
|
||||
`online: ${connection.online} streamAlive: ${app.streamAlive}`,
|
||||
`userId: ${app.session?.userId ?? '—'} guest: ${app.profile?.isGuest ?? '—'}`,
|
||||
telegramChromeDiag(),
|
||||
dictInfo,
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
let label = $state('Share');
|
||||
async function share(e: MouseEvent): Promise<void> {
|
||||
@@ -35,8 +56,10 @@
|
||||
resetOnboarding();
|
||||
// Also clear the local move-preview dictionary cache (safe — it re-downloads).
|
||||
// Dynamically imported so the debug panel keeps the dict code out of the app bundle.
|
||||
void import('../lib/dict/store').then((m) => m.clearDictCache());
|
||||
void import('../lib/dict/loader').then((m) => m.clearDictInstances());
|
||||
void import('../lib/dict').then((m) => {
|
||||
m.clearDictCache();
|
||||
m.clearDictInstances();
|
||||
});
|
||||
resetLabel = 'Cleared — relaunch';
|
||||
setTimeout(() => (resetLabel = 'Reset visited'), 1800);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user