From b8f8d4e3795e6a2532d1ca4accf4b70ca5ae0b87 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 9 Oct 2026 12:04:37 +0000 Subject: [PATCH 1/2] PLAN: record that V12 stays postponed after Cap 7 Owner decision (09/10/2026): consented generative chat is not scheduled. The row keeps its pending status, since nothing was built or measured. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01ELAjHYDyxa5zbbdcke1bMA --- PLAN.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/PLAN.md b/PLAN.md index 8a670b4..3876088 100644 --- a/PLAN.md +++ b/PLAN.md @@ -368,12 +368,12 @@ comfort, /ml 0.77 → 0.86 measured), V10 (replayable recipes, forced types, derived dates) — delivered and verified in production. 16 PRs merged, 177 unit tests, 36 e2e. -| Wave | Content | Why | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | -| **V11 — delivered** | **Data drift** in the Data Studio: a reference file, a file to compare → schema differences (columns added/removed/retyped), **PSI per column** (quantile bins from the reference, thresholds 0.1/0.25), new/vanished categories, missing-rate gaps, overall verdict — with a deliberately drifted demo (`cafe-sales-june.csv`) | The MLOps gesture par excellence: checking that a new batch looks like what the model learned on | -| V12 — pending | **Consented generative chat**: a Cloudflare Pages Function (same repo) proxying the Anthropic API — the key lives in a Cloudflare secret, never in the browser; the LLM translates the question into an intent executed **locally** by the V6 engine (only the question and the column schema leave, never the data); explicit consent screen; clean degradation if the secret is not configured | Owner's product decision (21/08/2026): postponed for now | -| **V13 — delivered** | **Complete runs**: tuning, latest Shapley explanation, exploration and forecast attached to the run record — IndexedDB history (with chips), stored-run page, HTML report and v2 share links (subsampled scatter plots in the URL; v1 links remain decodable) | The V5–V8 artifacts did not survive the run | -| **V14 — delivered** | **Generalized prerendering**: static shells for all six sections (the V9 approach extended — inlined CSS, Latin fonts as data:, per-route preloaded façade, header template), Lighthouse /ml 0.86 → 0.99 and /data 1.0 under real throttling (3-run medians); the root stays the SPA fallback (accepted) | The last Lighthouse gap | +| Wave | Content | Why | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | +| **V11 — delivered** | **Data drift** in the Data Studio: a reference file, a file to compare → schema differences (columns added/removed/retyped), **PSI per column** (quantile bins from the reference, thresholds 0.1/0.25), new/vanished categories, missing-rate gaps, overall verdict — with a deliberately drifted demo (`cafe-sales-june.csv`) | The MLOps gesture par excellence: checking that a new batch looks like what the model learned on | +| V12 — pending | **Consented generative chat**: a Cloudflare Pages Function (same repo) proxying the Anthropic API — the key lives in a Cloudflare secret, never in the browser; the LLM translates the question into an intent executed **locally** by the V6 engine (only the question and the column schema leave, never the data); explicit consent screen; clean degradation if the secret is not configured | Owner's product decision (21/08/2026): postponed for now. Confirmed 09/10/2026, after Cap 7: not scheduled. | +| **V13 — delivered** | **Complete runs**: tuning, latest Shapley explanation, exploration and forecast attached to the run record — IndexedDB history (with chips), stored-run page, HTML report and v2 share links (subsampled scatter plots in the URL; v1 links remain decodable) | The V5–V8 artifacts did not survive the run | +| **V14 — delivered** | **Generalized prerendering**: static shells for all six sections (the V9 approach extended — inlined CSS, Latin fonts as data:, per-route preloaded façade, header template), Lighthouse /ml 0.86 → 0.99 and /data 1.0 under real throttling (3-run medians); the root stays the SPA fallback (accepted) | The last Lighthouse gap | --- @@ -624,5 +624,7 @@ before features, and the one that produces wrong data comes first of all. **Cap 7 closed (09/10/2026)**: V47 to V52 delivered. What the lab already did now holds when the user does two things at once (V47), when a link is damaged (V48), when CI runs on a branch nobody checked (V49), when a class is rare or absent (V50); the store fits on a screen (V51), and the three majors were taken one at a time, one of them deferred on a measurement rather than forced (V52). -V12 (consented generative chat) remains pending a product decision. No wave -starts without an explicit launch command. +V12 (consented generative chat) is not scheduled: the owner confirmed on +09/10/2026, once Cap 7 closed, that it stays postponed. The row keeps its +« pending » status because nothing was built or refused; it is a decision not to +start, not a measurement. No wave starts without an explicit launch command. From 1c09d68a05d9675ebe56c00ef22a2c109a0f26c5 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 9 Oct 2026 12:09:08 +0000 Subject: [PATCH 2/2] Close the day: README, limits page and PLAN future directions - README roadmap: seven caps shipped, no wave scheduled, V12 postponed - Limits page (FR/EN): V12 generative chat listed as set aside by choice - PLAN section P: future directions, each with the condition that would start it (TypeScript 7, DuckDB re-measure, coverage floors, zero-warning lint, worker run id, text vocabulary, V12) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01ELAjHYDyxa5zbbdcke1bMA --- PLAN.md | 31 ++++++++++++++++++++++++++++ README.md | 8 +++++--- src/content/docs/en/limits.md | 37 +++++++++++++++++----------------- src/content/docs/fr/limites.md | 37 +++++++++++++++++----------------- 4 files changed, 74 insertions(+), 39 deletions(-) diff --git a/PLAN.md b/PLAN.md index 3876088..87e68fa 100644 --- a/PLAN.md +++ b/PLAN.md @@ -628,3 +628,34 @@ V12 (consented generative chat) is not scheduled: the owner confirmed on 09/10/2026, once Cap 7 closed, that it stays postponed. The row keeps its « pending » status because nothing was built or refused; it is a decision not to start, not a measurement. No wave starts without an explicit launch command. + +## P. Future directions (not scheduled, 09/10/2026) + +Written at the close of Cap 7 so the next session starts from a list rather +than from a fresh audit. None of these is a wave: each has the condition that +would justify starting it, and none starts without an explicit launch command. + +- **Adopt TypeScript 7.** Condition: typescript-eslint supports it (V52.3). The + code already typechecks with 0 errors; the work is a version bump, removing + the Dependabot ignore, and re-measuring the typecheck time in CI. +- **Re-measure DuckDB-Wasm above 1.28.0.** Condition: a release whose eh and + mvp binaries fit under Cloudflare Pages' 25 MiB per-file limit, or a reason + to shard them (V29). The Dependabot ignore keeps the question closed until + someone re-measures; it should be re-opened at least once a year. +- **Raise the coverage floors where they are lowest.** Functions (54 %) and + branches (53 %) trail statements and lines. Condition: none, it is + maintenance; the method is V51's, tests on the modules with the lowest + function coverage, then the floor moves up and never down. +- **A lint with zero warnings.** `badge.tsx` and `button.tsx` export their + variant helpers next to the component, which `react-refresh` flags. Moving + the helpers to their own file and adding `--max-warnings 0` makes the next + warning a failure instead of a line nobody reads. +- **A run id in the ML worker protocol.** Condition: the day two requests can + be in flight at once (for example, an analysis that runs during training). + Until then V47's fence is enough, and the limits page says so. +- **Widen the text vocabulary.** V24 capped it; V25 measured that the memory + guard made the typed-array rewrite unnecessary. Condition: a real dataset + where the cap visibly costs accuracy, measured before and after. +- **V12, consented generative chat.** Postponed by the owner (09/10/2026). + Condition: a product decision, plus a fresh read of the provider's data + policy, since the consent screen would have to quote it. diff --git a/README.md b/README.md index 5637889..562b2a8 100644 --- a/README.md +++ b/README.md @@ -341,12 +341,14 @@ CI builds, tests and deploys on every push: pull requests get a Cloudflare Pages ## Roadmap -Development proceeds in planned "caps" of feature waves; six caps have shipped (MVP -through the lab meeting the real world: real photos, real text, real file sizes). Cap 7 (closed) +Development proceeds in planned "caps" of feature waves; seven caps have shipped (MVP +through the lab meeting the real world: real photos, real text, real file sizes). The last, Cap 7, made what already ships hold up under pressure: worker lifecycle, damaged share links, CI hardening, metric edge cases, a store refactor, and major upgrades taken one at a time (Vitest 5 and vite-plugin-pwa 2 shipped; TypeScript 7 typechecks this code with no error -in 1.5 s instead of about 11, and waits for typescript-eslint to support it). The full plan, delivery log and design decisions live in +in 1.5 s instead of about 11, and waits for typescript-eslint to support it). No wave is scheduled: the consented +generative chat (V12) stays postponed by product decision, and the candidates for a next +cap are listed, each with the condition that would start it. The full plan, delivery log and design decisions live in [PLAN.md](PLAN.md); [CHANGELOG.md](CHANGELOG.md) is extracted from it — one entry per wave, newest first — by `npm run changelog`, and a test fails when the two disagree. diff --git a/src/content/docs/en/limits.md b/src/content/docs/en/limits.md index b1e9cc6..dd5fd73 100644 --- a/src/content/docs/en/limits.md +++ b/src/content/docs/en/limits.md @@ -27,24 +27,25 @@ They are not equivalent, and mixing them would be dishonest: ## Set aside by choice -| Set aside | Why | -| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| An AutoML « we handle everything » mode | The exact opposite of a lab that shows its decisions | -| A tenth model family | Nine is plenty; a tenth improves neither honesty nor understanding | -| Tabular deep learning | High cost, no gain at this scale, and no longer hand-written | -| A spreadsheet-style cell editor | Hand edits break reproducibility — the recipe is the only record | -| Fuzzy deduplication | Guaranteed false positives on names and addresses: silently merging two real people | -| Model-based imputation | Opaque, and it fabricates plausible values — refused twice, in V39 and V40 | -| Caching models across runs | The cache key would be the whole configuration plus the data; a stale hit is a wrong leaderboard with no warning | -| Guessing a file's locale | The browser has no relationship to the file dropped into it | -| Making the absence indicator mandatory | It would add columns to every existing recipe: imposing is not announcing | -| Translating the changelog and prerendering the French docs | The changelog is an engineering log, not editorial content; without per-language routes, hreflang alternates would lie | -| Catching async errors and shipping crash reports | React boundaries cannot see callbacks or event handlers — claiming otherwise would be false; and nothing leaves the browser, telemetry included | -| A daily Dependabot and `npm audit fix --force` | A daily cadence drowns the signal; `--force` moves majors without reading the break. The remaining advisories sit in build tooling, and we say so instead of hiding it | -| Picking multiclass thresholds automatically | The lab shows its decisions instead of making them for you; and abstention is neither uncertainty calibration nor a conformal guarantee | -| A run id in every worker message | The worker answers in the order it is written to, so the training status is enough to recognise a stale answer. The id becomes necessary the day requests can overlap | -| A « rare class » warning in the interface | A one-row class stays in training, and a target where every class has one row is refused by name; a banner would flag a problem the split already handles | -| Splitting the ML Lab store into independent slices | Every action shares one worker: slicing would have moved code without separating anything | +| Set aside | Why | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| An AutoML « we handle everything » mode | The exact opposite of a lab that shows its decisions | +| A tenth model family | Nine is plenty; a tenth improves neither honesty nor understanding | +| Tabular deep learning | High cost, no gain at this scale, and no longer hand-written | +| A spreadsheet-style cell editor | Hand edits break reproducibility — the recipe is the only record | +| Fuzzy deduplication | Guaranteed false positives on names and addresses: silently merging two real people | +| Model-based imputation | Opaque, and it fabricates plausible values — refused twice, in V39 and V40 | +| Caching models across runs | The cache key would be the whole configuration plus the data; a stale hit is a wrong leaderboard with no warning | +| Guessing a file's locale | The browser has no relationship to the file dropped into it | +| Making the absence indicator mandatory | It would add columns to every existing recipe: imposing is not announcing | +| Translating the changelog and prerendering the French docs | The changelog is an engineering log, not editorial content; without per-language routes, hreflang alternates would lie | +| Catching async errors and shipping crash reports | React boundaries cannot see callbacks or event handlers — claiming otherwise would be false; and nothing leaves the browser, telemetry included | +| A daily Dependabot and `npm audit fix --force` | A daily cadence drowns the signal; `--force` moves majors without reading the break. The remaining advisories sit in build tooling, and we say so instead of hiding it | +| Picking multiclass thresholds automatically | The lab shows its decisions instead of making them for you; and abstention is neither uncertainty calibration nor a conformal guarantee | +| A run id in every worker message | The worker answers in the order it is written to, so the training status is enough to recognise a stale answer. The id becomes necessary the day requests can overlap | +| A « rare class » warning in the interface | A one-row class stays in training, and a target where every class has one row is refused by name; a banner would flag a problem the split already handles | +| Splitting the ML Lab store into independent slices | Every action shares one worker: slicing would have moved code without separating anything | +| A generative chat backed by a remote API (V12) | Postponed by product decision (confirmed 09/10/2026). Today's chat runs entirely in the browser; a remote API would send out the question and the column schema, never the data, and would require a consent screen | ## Dropped after measurement diff --git a/src/content/docs/fr/limites.md b/src/content/docs/fr/limites.md index 89ef071..f0ace5f 100644 --- a/src/content/docs/fr/limites.md +++ b/src/content/docs/fr/limites.md @@ -27,24 +27,25 @@ Elles ne se valent pas, et les mélanger serait malhonnête : ## Ce qui a été écarté par choix -| Écarté | Pourquoi | -| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Un mode AutoML « on s'occupe de tout » | L'exact contraire d'un laboratoire qui montre ses décisions | -| Une dixième famille de modèles | Neuf suffisent ; une dixième n'améliore ni l'honnêteté ni la compréhension | -| Le deep learning tabulaire | Coût élevé, aucun gain à cette échelle, et ce ne serait plus écrit à la main | -| Un éditeur de cellules façon tableur | Les retouches à la main cassent la reproductibilité — la recette est le seul enregistrement | -| La déduplication floue | Faux positifs garantis sur des noms et des adresses : fusionner deux personnes réelles en silence | -| L'imputation par modèle | Opaque, et elle fabrique des valeurs plausibles — refusée deux fois, en V39 et en V40 | -| Cacher les modèles entre exécutions | La clé de cache serait la configuration entière plus les données ; un hit périmé, c'est un classement faux sans avertissement | -| Deviner la locale d'un fichier | Le navigateur n'a aucun rapport avec le fichier qu'on y dépose | -| Rendre l'indicateur d'absence obligatoire | Il ajouterait des colonnes à toute recette existante : imposer n'est pas annoncer | -| Traduire le changelog et prérendre la documentation française | Le changelog est un journal d'ingénierie, pas un contenu éditorial ; sans routes par langue, des alternates hreflang mentiraient | -| Capter les erreurs asynchrones et envoyer des rapports de plantage | Les boundaries React ne voient pas les callbacks ni les gestionnaires d'événements — prétendre le contraire serait faux ; et rien ne quitte le navigateur, télémétrie comprise | -| Un Dependabot quotidien et un `npm audit fix --force` | Une cadence quotidienne noie le signal ; `--force` change des majeures sans lire la rupture. Les advisories restantes touchent les outils de build, et on le dit plutôt que de le masquer | -| Choisir les seuils multiclasses automatiquement | Le laboratoire montre ses décisions au lieu de les prendre à votre place ; et l'abstention n'est ni une calibration d'incertitude ni une garantie conforme | -| Un identifiant de run dans chaque message du worker | Le worker répond dans l'ordre où on lui écrit : l'état de l'entraînement suffit à reconnaître une réponse périmée. L'identifiant deviendra nécessaire le jour où des requêtes pourront se chevaucher | -| Un avertissement « classe rare » dans l'interface | Une classe d'une seule ligne reste à l'entraînement, et une cible où chaque classe n'a qu'une ligne est refusée par son nom ; un bandeau signalerait un problème que la découpe règle déjà | -| Découper le store du ML Lab en tranches indépendantes | Toutes ses actions partagent un seul worker : découper aurait déplacé du code sans rien séparer | +| Écarté | Pourquoi | +| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Un mode AutoML « on s'occupe de tout » | L'exact contraire d'un laboratoire qui montre ses décisions | +| Une dixième famille de modèles | Neuf suffisent ; une dixième n'améliore ni l'honnêteté ni la compréhension | +| Le deep learning tabulaire | Coût élevé, aucun gain à cette échelle, et ce ne serait plus écrit à la main | +| Un éditeur de cellules façon tableur | Les retouches à la main cassent la reproductibilité — la recette est le seul enregistrement | +| La déduplication floue | Faux positifs garantis sur des noms et des adresses : fusionner deux personnes réelles en silence | +| L'imputation par modèle | Opaque, et elle fabrique des valeurs plausibles — refusée deux fois, en V39 et en V40 | +| Cacher les modèles entre exécutions | La clé de cache serait la configuration entière plus les données ; un hit périmé, c'est un classement faux sans avertissement | +| Deviner la locale d'un fichier | Le navigateur n'a aucun rapport avec le fichier qu'on y dépose | +| Rendre l'indicateur d'absence obligatoire | Il ajouterait des colonnes à toute recette existante : imposer n'est pas annoncer | +| Traduire le changelog et prérendre la documentation française | Le changelog est un journal d'ingénierie, pas un contenu éditorial ; sans routes par langue, des alternates hreflang mentiraient | +| Capter les erreurs asynchrones et envoyer des rapports de plantage | Les boundaries React ne voient pas les callbacks ni les gestionnaires d'événements — prétendre le contraire serait faux ; et rien ne quitte le navigateur, télémétrie comprise | +| Un Dependabot quotidien et un `npm audit fix --force` | Une cadence quotidienne noie le signal ; `--force` change des majeures sans lire la rupture. Les advisories restantes touchent les outils de build, et on le dit plutôt que de le masquer | +| Choisir les seuils multiclasses automatiquement | Le laboratoire montre ses décisions au lieu de les prendre à votre place ; et l'abstention n'est ni une calibration d'incertitude ni une garantie conforme | +| Un identifiant de run dans chaque message du worker | Le worker répond dans l'ordre où on lui écrit : l'état de l'entraînement suffit à reconnaître une réponse périmée. L'identifiant deviendra nécessaire le jour où des requêtes pourront se chevaucher | +| Un avertissement « classe rare » dans l'interface | Une classe d'une seule ligne reste à l'entraînement, et une cible où chaque classe n'a qu'une ligne est refusée par son nom ; un bandeau signalerait un problème que la découpe règle déjà | +| Découper le store du ML Lab en tranches indépendantes | Toutes ses actions partagent un seul worker : découper aurait déplacé du code sans rien séparer | +| Un chat génératif branché sur une API distante (V12) | Reporté par décision produit (confirmé le 09/10/2026). Le chat actuel tourne entièrement dans le navigateur ; une API distante ferait sortir la question et le schéma des colonnes, jamais les données, et exigerait un écran de consentement | ## Ce qui a été abandonné après mesure