Commit Graph

16 Commits

Author SHA1 Message Date
Sylvain Duchesne c7cda38235 Name the script for what it does, now that it serves two providers
`link-polyfill.ts` handled one provider. It now handles two through a registry,
one of which is not a polyfill, so both the filename and the `link:` verb said
something false — and a name that is short but wrong misleads more than an opaque
one would.

It becomes `overlay-local-checkout.ts`, which is the operation: it copy-overlays a
local package checkout into node_modules for development. "link" also implied a
symlink, which is precisely what the script exists NOT to do — its own header
spends a paragraph on why.

No behaviour changed: same registry, same copy, same `--once`, same watch loop,
same assertion. Both providers exercised afterwards, each reporting the singletons
it must preserve — one package for the data layer, two for the indexing package,
whose own checkout carries `file:` links and would otherwise smuggle in a second
verifier.

Seven references repaired by rewriting the sentence that carried them rather than
swapping a path, across the script, `package.json`, `.env.example` and four
doctrine leaves. No compatibility alias left behind: an old name kept "just in
case" would restore exactly the ambiguity being removed.
2026-08-17 12:35:28 +02:00
Sylvain Duchesne 7124750874 The indexing package installs, and there is still one verifier
`1.0.1` moves the data layer from `dependencies` to `peerDependencies`, satisfied
by the application's own copy. The path that broke `1.0.0` survives only in
devDependencies, which pnpm never installs for a git dependency -- verified at the
tag's commit rather than taken on trust.

One verifier, proven: the data layer and `@ng-org/web` each resolve to the same
realpath from the application and from inside the new package, and exactly one
`@ng-org/web` exists in the whole store. No overrides, no resolutions, no hoisting
flag, no `.npmrc` -- the peer dependency did it alone, which is the point: the
singleton becomes structural instead of something checked afterwards.

The runtime surface matches the engagement exactly -- five values exported, every
other published name type-only and erased. Nothing undeclared, nothing missing.

Local wiring stays ONE script rather than a sibling: a provider registry drives
the same copy-overlay, the same `--once`, the same watch loop, only the paths
differ. Its single-instance assertion became a loop over every package a provider
shares with the application, which matters here because that provider's own
checkout carries `file:` links -- the very symlink hazard the script exists for.

Its header no longer promises what the old one did: a running dev server never
picks up a refreshed node_modules package, not even across a real rebuild.
2026-08-17 12:30:25 +02:00
Sylvain Duchesne ac55dc96a4 A refreshed data-layer package never reaches a running dev server
`link:polyfill` overlays the package into node_modules and keeps it current.
That is all it does. A `bun run dev` already running goes on serving what it
loaded at startup, however many times the overlay is rewritten underneath it:
node_modules is excluded by file watchers, so the change lands in the one place
nothing is looking.

The script promised the opposite -- that `bun --hot` would reload the copied
file live. That promise is now removed, and replaced by the instruction to
restart.

It cost about an hour. A defect had been fixed upstream, the overlay refreshed,
and a probe on a freshly launched server confirmed the fix 3 runs out of 3. The
same sequence by hand reproduced the defect at once. The two observations looked
irreconcilable and the hunt went to the wallet, to prior state, to timing.

The dev server had been up for six days. It predated the package rename and the
whole migration; the browser was running a different application from the one
under test. Nothing warned: a stale server looks exactly like a current one, and
the script's own header ruled out the true cause for anyone who trusted it.

The reflex is written down with the leaf: when a fix seems not to take, or when
a hand-run and an automated run disagree, check how long the server has been up
before anything else. One command, cheapest hypothesis first.
2026-08-16 22:06:52 +02:00
Sylvain Duchesne 53c0e095cf Code against the polyfill's published contract, and nothing else
The data layer is now reached through one pulled, version-pinned engagement
(`.project/concepts/data-layer/contract_polyfill-surface.md`, @1ecf511e9d).
That copy is the only reference: the provider's sources are never opened, and
what the contract does not answer is a gap raised with it, never worked around
here.

Surface
- `@ng-eventually/sdk` -> `@ng-eventually/polyfill`, one entry point.
- `configure` loses `getSession`, `normalizeId`, `currentUser`; the session
  belongs to the package and its own `init` captures it.
- Placement is named by scope alone -- a session is one user, so the app no
  longer passes an identity it had no way to obtain. This removes a constant
  that made every user collide on one owner's document.
- `init(...)` then `await ensureIdentity()`, in that order, as one sequence:
  React runs child effects first, so the two calls sat in the wrong order and
  the contract now makes that throw.
- `sessionId` relayed as `string | number`, `materialize` -> `read`.

A rejection means "unknown", never "absent"
Four places treated a caught error as an empty result. The worst wrote a
duplicate participation: an unknown count read as zero defeated the idempotence
guard of `joinEvent`. Also fixed: a per-document count, a silently dropped
notification shown optimistically anyway, and a failed listing that left the
owned-event set empty and disabled the materializer for the whole session.

Shared identity is not a Festipod notion
A browser context is one user. The per-scenario identity plant is deleted at
its source and its five sites; what stays is the deployment's wallet file,
which the contract requires an application to serve.

Documentation
The doctrine no longer describes how the data layer works underneath: five
leaves whose subject was internals are gone, a dozen more are re-founded on the
contract's own words, and two frozen arbitrations about a deleted screen were
removed rather than left to mislead a future session.

Test harness
It can sign in at last: cucumber runs under node, which does not load `.env`,
so the harness never received the wallet material and every scenario silently
fell back to an empty local mode. A failed sign-in is now loud on both sides.
The suite also releases what it opens and exits on its own -- runs were still
resident hours after reporting, holding a browser and two servers.

Known red: `@data` cannot be measured. The served wallet accumulates and
nothing resets it; moving the browser profile aside does not, since the data
lives in the wallet file, not the profile.
2026-08-16 12:33:14 +02:00
Sylvain Duchesne f6fc3c262e chore: install via pnpm + polyfill depuis Gitea (git-https) + lien local réactif
Passe l'installation de bun à pnpm (runtime/build/test restent bun).
Dépendance prod @ng-eventually/client résolue depuis le Gitea public en
git+https (committée, reproductible via pnpm-lock.yaml). Script
link:polyfill (S2 copie-overlay + watcher) pour un lien local réactif
préservant l'instance @ng-org unique. bun (peer de bun-plugin-tailwind)
approuvé au build (pnpm.onlyBuiltDependencies) pour que
node_modules/.bin/bun soit un vrai binaire. Dockerfile: install pnpm
avec git + node dans l'image, runtime bun inchangé. Doctrine tech-stack
(deployment, stack-and-commands) mise à jour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg
2026-07-14 12:52:30 +02:00
Sylvain Duchesne 7302936502 test(e2e): smoke @smoke garde la classe "page blanche une fois connecté"
Boote le VRAI App via le broker (hook Before @e2e existant), navigue vers
l'accueil connecté et asserte deux choses fortes : HomeScreen a réellement
monté (.app-navbar + bouton "Relayer", absents d'un spinner/bandeau broker)
ET aucune erreur runtime (pageerror/console.error) n'a été émise pendant le
boot connecté. Le World collecte désormais les pageErrors (réinitialisés par
scénario, logging existant préservé). Câblé dans `bun run validate` (run par
défaut) via @smoke and not @wip, avec nettoyage Chromium.

Preuve: un throw dans HomeScreen fait virer le smoke au rouge; sans lui, vert.
Comble le trou qui laissait passer la régression page-blanche (aucune suite
n'exécutait @e2e et aucune assertion ne gardait le rendu connecté).

Doctrine: bdd-testing/knowledge_e2e-layer documente le smoke @smoke + pageErrors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 19:03:21 +02:00
Sylvain Duchesne 0fc8479e22 tooling(validate): nettoyage SingletonLock + @multibrowser réactif @wip (limite wallet-partagé)
- validate.ts : `cleanSingletons()` retire SingletonLock/Cookie/Socket avant
  polyfill:e2e (et à la rotation) → fiabilise polyfill:e2e (fini le faux rouge
  ProcessSingleton). @multibrowser lancé en `@multibrowser and not @wip`.
- e2e-multibrowser : le scénario réactif « Un participant apparaît réactivement »
  passe @wip, commentaire d'en-tête expliquant la LIMITE : en wallet-partagé A et B
  partagent UNE identité NG → B voit l'événement de A comme possédé → son
  owner-materializer écrit le doc de A → StorageError. PAS un bug produit (prod =
  wallets distincts). Vrai fix = isolation distinct-wallets (chantier T02.d/g).
  Réserve : ce scénario était vert (517045c) ; à re-vérifier lors de l'isolation
  distinct-wallets (peut masquer une interaction phase-B).

Baseline validate visé : vert sauf ce @multibrowser documenté.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 17:17:18 +02:00
Sylvain Duchesne 7dab6e44e2 tooling(validate): sous-ensemble @data clé rapide par défaut + flag --full + budgets
`bun run validate` finissait en timeout (@data complet >14min). Désormais : par
défaut un SOUS-ENSEMBLE CLÉ de 8 scénarios @data (les couvertures des bugs terrain :
inscription, désinscription, isolation, reconnexion, créateur, compteur, auth×2) en
une invocation → finit en ~8m30. Flag `--full` pour toute la suite @data (budget
élargi 35min). Rotation profil avant @data/@multibrowser, matrice + exit non-zéro.

Baseline actuel : 8/8 @data clé VERTS (les fixes watchShape/optimiste/reconnexion/
anti-fork tiennent) ; polyfill:unit 123 ; rouges = SingletonLock (infra) + un
@multibrowser (limite wallet-partagé A/B).

Note : gate pre-push rapide (tsc+build+polyfill unit) ajouté dans .git/hooks/pre-push
(local, non versionné — pour partage : script tracké + install, suivi).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 17:06:40 +02:00
Sylvain Duchesne 9e62bdea53 tooling: commande bun run validate — validation complète 2 niveaux
Fondation « l'agent valide tout d'un coup » (audit couverture, levier C1). Enchaîne
et agrège : polyfill unit + polyfill e2e réel + Festipod @data + @multibrowser
(profils frais/rotation), matrice finale + exit non-zéro si rouge, passe @wip
informative.

Baseline établi (premier run réel) : polyfill unit 120 , polyfill e2e 42/42 
(broker réel), @multibrowser 1 rouge (limite wallet-partagé A/B), @data 4 rouges
dont 2 régressions phase B confirmées. → a trouvé les problèmes tout seul.

À TUNER (suivi) : le budget @data (~14min) est trop court → la suite complète est
tuée par timeout ; augmenter le budget OU exécuter un sous-ensemble clé rapide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 01:04:57 +02:00
Sylvain Duchesne 6f9b3ece34 Data-layer BDD testing infrastructure and steps/frontend → steps/ui rename
- Rename steps/frontend/ to steps/ui/ across all modules and shared
- Add data-layer test harness (mock + real broker modes) with Playwright
- Add inscription data-layer steps (@data scenarios)
- Add test auth setup script and browser debug script
- Update docs (architecture, BDD testing, data-layer testing)
- Add ADR for headless wallet creation decision

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:01:46 +01:00
Sylvain Duchesne 901fd659df NextGraph integration (WIP), broker banner, and feature-based architecture
- Add NextGraph data layer with @ng-org/orm, SHEX shapes (Event, UserProfile,
  Participation), session management, and FestipodDataContext with dual-mode
  operation (connected via NextGraph or local seed data)
- Add BrokerBanner and NgStatus components showing connection status
- Refactor to feature-based architecture: organize code by business domain
  (event, user, home, auth, workshop, meeting, notification) instead of
  technical layer. Modules only import from shared/, never from each other
- Collocate BDD features and step definitions with their modules: event-specific
  steps in event/steps/, user steps in user/steps/, shared generic steps remain
  in shared/steps/
- Set up multi-layer BDD structure (frontend/backend/e2e steps per module)
- Add project documentation (AGENTS.md, .project/knowledge/)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:19:45 +01:00
Sylvain Duchesne ed61c7081f Extract screenIds from feature files automatically
- Add screenIds extraction to parse-features.ts based on step patterns
- Update ParsedFeature type to include screenIds field
- Remove manual screenIds from user story definitions in index.ts
- Compute screenIds by looking up parsed features at runtime

Feature files are now the single source of truth for screen-to-story
linking. Run `bun run features:parse` to update after modifying features.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:00:42 +01:00
Sylvain Duchesne 9cc916e8bc Fix TypeScript strict null check errors
Add optional chaining and null checks in build scripts to handle
potentially undefined array elements. Add style prop to Card, Badge,
and Placeholder components, and onClick prop to Text component to
support inline styling in screen components.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 21:16:21 +01:00
Sylvain Duchesne 9843936212 Use grammatically correct French Gherkin keyword "Étant donné que"
Update all 26 feature files to use proper French grammar with the
subordinating conjunction "que" after "Étant donné". Also update the
parser to recognize both "Étant donné que " and "Étant donné qu'"
(elision before vowels), while maintaining backwards compatibility
with the original form.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 19:39:12 +01:00
Sylvain Duchesne a19bda44e1 Fix step definition popup for mobile and escaped quotes
- Replace hover-based Tooltip with click-based popover for mobile support
- Fix pattern extraction regex to handle escaped apostrophes (e.g., l'écran)
- Add dashed underline (1.3px) to indicate clickable steps with definitions
- Enable definitions mode by default
- Regenerate stepDefinitions.ts with correct patterns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 18:25:02 +01:00
Sylvain Duchesne f04f15d926 first commit 2026-01-18 11:53:42 +01:00