Commit Graph

55 Commits

Author SHA1 Message Date
Sylvain Duchesne aacc2ec3ee feat(data): PdR registration via inbox, notifications, public discovery, protected store
Polyfill-enabled features (T02). All NextGraph I/O goes through
@ng-eventually/client (docs/inbox/storeRegistry); no direct @ng-org.

- Shapes: FpMeetingPoint + FpNotification are now real SHEX shapes with ORM
  bindings (previously app-TS-only, unpersisted).
- Registration (registration.ts, new): joinEvent persists a Participation +
  deposits to the host's inbox + creates a Notification (from = registrant if
  connected, anonymous otherwise). leaveEvent deletes the Participation
  authoritatively via SPARQL DELETE-WHERE (sweep by event+user AND by subject,
  then re-query to confirm) — the désinscription CRDT-resurrection bug is fixed:
  the reactive delete is applied only once the broker confirms 0 remaining.
- Public discovery: useNgData fans out over every account's public docs so a
  user sees others' public events without a connection (dedup union).
- Cap attribution: createEntityDoc declares the ReadCap (open + makePublic/
  grantRead per scope), activating the per-document read filter.
- Protected store (T02.h): the default path now reads/writes shareable domain
  entities in the native protected store (did🆖${protected_store_id}) instead
  of private — verified openable against the broker — matching the per-wallet
  target. Private still anchors the shim/inbox + settings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 15:51:23 +02:00
Sylvain Duchesne 555c670b22 doctrine(nextgraph-platform): shim fully migrated into the lib
Record the completed T01 migration + validation in the two relevant leaves.

- decision_2026-06-17_eventually-library.md: new dated section "Shim migré
  dans la lib — 2026-07-02" — the integration boundary moved from "doc_create
  stays on the real ng / shim still in-app" to "everything in the lib; the app
  touches @ng-org at runtime only via ngSession". TODO "primitive doc_create/
  SPARQL via injected ng" checked done. Namespaces docs/storeRegistry/
  isolation/accounts; isolation<->ReadCap = coexist (distinct axes).
- brief_2026-06-15_shared-wallet-shim.md: Status/summary/Direction "shim
  in-app" -> "shim in the lib".

Validation captured: lib 36/36 + tsc rc=0; app build + harness bundle OK;
full BDD suite 78 passed / 0 failed / 71 skipped (baseline held).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 10:13:29 +02:00
Sylvain Duchesne 3f47ea886f Rewire app onto @ng-eventually/client; drop direct @ng-org runtime imports
Consume the shim mechanics now living in the lib (docs/storeRegistry/
isolation/accounts) and remove the remaining direct @ng-org runtime imports.

- storeRegistry.ts  keeps ONLY the Festipod EntityKind/entityScope mapping,
  injects it via configureStoreRegistry({ getSession, normalizeUser }), and
  re-exports the lib's storeRegistry.* (callers unchanged). Drops
  `import { ng } from '@ng-org/web'`.
- harness-ng.tsx  createSmokeDoc now uses docs.docCreate (real injected ng,
  no DataCloneError) instead of ng.doc_create. Drops the @ng-org import.
- AccountContext.tsx  thin React wrapper over accounts.AccountStore +
  normalizeUsername; historical key `festipod.account.username` pinned →
  zero behavior change. Context/Provider stay in the app.
- isolation.ts  Festipod wrapper over the lib's pure isolation.applyIsolation.

Invariant reached: `grep "from '@ng-org'" src/ | grep -v 'import type'` lists
only ngSession (the configure injection point) + the two documented
test-harness exceptions (auth-setup.tsx, harness.tsx mock). No doc_create
goes through the lib's public proxy. App build + harness-ng bundle OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 10:13:11 +02:00
Sylvain Duchesne a54c119b4d chore: gitignore .tasks/ (local big-task tree)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:35:15 +02:00
Sylvain Duchesne d69fd7a5f9 Revert doc_create to real ng: lib proxy breaks iframe marshaling (validated)
Full-suite validation of the merge surfaced 4 failures, all multistore: routing
doc_create through the lib's `ng` proxy (685f6d3) breaks @ng-org/web's iframe
postMessage marshaling — DataCloneError "function could not be cloned" (a JS
Proxy over the iframe-RPC proxy = double proxy).

Fix: storeRegistry.ts and harness-ng.tsx (createSmokeDoc) call doc_create /
SPARQL on the real @ng-org/web `ng` directly again. useShape / init / login /
ReadCap still route through the lib. After the fix the 3 multistore scenarios
pass; full suite = 77 passed, 0 merge regressions.

Integration boundary documented in decision_2026-06-17: the in-app shim's
low-level NextGraph calls stay on the real SDK until storeRegistry moves INTO
the lib (where it would use the injected real ng, no double proxy). Lib TODO:
expose a doc_create/SPARQL primitive that uses the injected ng.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 13:39:53 +02:00
Sylvain Duchesne 685f6d379d storeRegistry: route ng through @ng-eventually/client (post-merge integration)
Post-merge audit of main's shared-wallet shim: storeRegistry.ts was the only
runtime path still importing `ng` from @ng-org/web directly, bypassing the lib.
Route it through @ng-eventually/client (the ng proxy forwards doc_create /
sparql_update / sparql_query). Now the only @ng-org runtime imports in the app
are the single injection point (ngSession) + documented exceptions (auth-setup,
mock harness) + generated ORM type-only bindings — the decision_2026-06-17
invariant holds again.

Still in-app, to move into the lib later: storeRegistry, AccountContext, the
isolation filter (distinct from the lib's ReadCap filter).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 13:07:28 +02:00
Sylvain Duchesne c52e581e4f Merge main into ng-eventually: shared-wallet shim + multi-browser e2e
Brings 266e335 (staging shared wallet: file-assisted import + multi-browser
e2e) into the ng-eventually branch. Conflicts resolved so both lines of work
coexist and route through the lib where they overlap:

- harness-ng.tsx: combine ReadCap FilterProbe (ours) with main's SmokeProbe/
  FanoutProbe; useShape + ng imported from @ng-eventually/client.
- ngSession.ts (auto): our single-injection-point configure() + main's hidden
  logoutNg, which uses the lib's ng.
- useShapeWithDefaults.ts (auto): lib useShape + main's { graphs } multistore
  scope.
- cucumber.json: single "tags": "not @wip" (both branches added it).
- brief_2026-06-15_shared-wallet-shim: keep main's implemented status; record
  that the read filter now lives in the lib (decision_2026-06-17) while the
  rest of the shim (storeRegistry/accounts/isolation) is still in-app, slated
  to move into the lib.

Build OK; harness-ng bundles. TODO (next): verify all of main's NextGraph
surface routes through @ng-eventually/client (storeRegistry uses ng directly).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 13:05:21 +02:00
Sylvain Duchesne 98c796054e e2e désinscription: mark @wip (real CRDT bug, not a stale test) + exclude @wip from default run
The "Se désinscrire" e2e wasn't obsolete: verified against the broker that
join reflects in the UI but leave does NOT — the button stays "✓ Je participe"
(>10s). DeepSignalSet.delete() does fire reactivity (touchIterable), so the
real cause is downstream: the deletion doesn't propagate / the item resurrects
via broker sync (the documented CRDT limitation).

- cycle-de-vie-evenement.feature: rewrite the désinscription scenario to be
  self-contained (join → leave → "J'y serai" in one session, no cross-scenario
  / persistence dependency), and tag it @wip with an accurate comment.
- cucumber.json: add tags "not @wip" so known-incomplete scenarios document an
  expectation without failing the suite (default run: 146 scenarios).
- docs: caveat_participation-deletion records the e2e finding (leave doesn't
  reflect in the UI; delete fires reactivity but the item resurrects via sync);
  knowledge_cucumber-setup documents @wip = excluded from the default run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 12:19:03 +02:00
Sylvain Duchesne 266e33556d feat(auth): staging wallet partagé — import assisté par fichier + e2e multi-navigateur
Stopgap staging multi-user sur wallet partagé (cf. brief_2026-06-15_shared-wallet-shim).

Distribution / import du wallet :
- AccessGateScreen : barrière d'accès ON PAR DÉFAUT (désactivable via
  globalThis.__FESTIPOD_ACCESS_GATE_DISABLED__ pour tests/dev). Fournit le FICHIER
  .ngw + le mot de passe + un guide en 3 étapes (import assisté sur nextgraph.eu —
  le broker hébergé n'autorise pas l'import inline pendant l'auth web-app).
- sharedWallet.ts + build.ts : fichier copié en /shared-wallet.ngw, mot de passe gravé.
- Ancien LoginScreen (/login) retiré ; atterrissage post-login -> /home.
- NextGraphContext : dé-piégeage de l'état "connecting" au retour (pageshow/bfcache).

Couche multistore stopgap : storeRegistry, isolation, AccountContext, FestipodDataContext.

Tests e2e multi-navigateur :
- browserPool + world.openBrowser : contextes frais isolés, 2 axes orthogonaux
  (nb de navigateurs × modèle de wallet own/shared).
- @humain : parcours humain complet (télécharge -> importe le fichier sur
  nextgraph.eu -> Entrer -> pseudo -> accueil).
- Bypass de la barrière pour @e2e via context.addInitScript.
- Convention @wip exclue via cucumber.json.

Docs (concepts) : nextgraph-platform (knowledge_broker-import-constraint,
decision_2026-06-17_assisted-wallet-import), bdd-testing (knowledge_multibrowser-harness).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 12:04:02 +02:00
Sylvain Duchesne 073150ef61 ReadCap read filter: consume the lib's per-document model + validate against broker
Align Festipod's @data read-filter scenario and harness bridge with
ng-eventually's grant→ReadCap refactor: the access unit is the document
(an item's `@graph`), not the item.

- harness-ng.tsx: governDocument(reader, user)/setUser via getCaps()/resetCaps()
  (replaces setupReadFilter/setGrantOf); FilterProbe exposes a lazy snapshot()
  reflecting the current user without remount.
- read-filter.feature/steps: validate per-document ReadCap on the real
  DeepSignalSet — govern the wallet document, grant the cap to another user
  → current user sees 0; current user gets the cap → sees all (all-or-nothing
  in mono-store, the faithful behavior). 5/5 steps pass against the broker.
- doctrine: knowledge_stores-permissions records the verified store/document/
  repo/ReadCap model (containment by reference, no read-cap inheritance);
  decision_2026-06-17_eventually-library updates the access-rights + filter
  status to the ReadCap model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 11:20:12 +02:00
Sylvain Duchesne aec338441c test(data): validate ng-eventually read filter on the real ORM set
Adds a @data scenario (workshop/read-filter) that enables the lib's read filter on the
real reactive ORM set (via a FilterProbe + setupReadFilter harness helper, granting each
participation to its own user) and asserts useShape returns only the target user's
participations. Validates the trickiest piece — filtering a live DeepSignalSet — against the
broker. @data 9/9. Doc: read filter marked implemented & validated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 10:28:56 +02:00
Sylvain Duchesne e270cc6063 refactor(data): route full NextGraph surface through @ng-eventually/client
The app now takes its NextGraph runtime AND types from @ng-eventually/client; the
only place that imports the real @ng-org SDK is ngSession (the single injection point for
configure()). Lifecycle (init/initNg), data (useShape) and types (ShapeType, DeepSignalSet,
NG…) all go through the lib. Test infra (auth-setup, mock harness) and generated ORM
bindings keep a direct @ng-org import (documented). Validated: build, @ui 4/4, @data 8/8
against the real broker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 14:54:00 +02:00
Sylvain Duchesne 9af128cb22 feat(data): route useShape through @ng-eventually/client (passthrough)
The reactive ORM data-plane now goes through the @ng-eventually/client wrapper
instead of @ng-org/orm directly; ngSession injects the real SDK into the polyfill via
configure(). Currently a transparent passthrough (lib mechanisms still stubbed) →
behavior unchanged. Validated: build, @ui 4/4, @data 8/8 against the real broker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 16:35:58 +02:00
Sylvain Duchesne 3ca2d10c49 docs(concepts): NextGraph multi-user design — ng-eventually polyfill, discovery, apps/services
Captures the design worked out this session:
- decision: ng-eventually generic polyfill library (external repo) encapsulates all
  multi-user compensation; @ng-eventually/client is SDK-identical, app depends only on it.
- decision: discovery via a single global index fed through its inbox (owned doc,
  materialized) — no Group store; index owner = open question (singleton app, deferred).
- knowledge: NextGraph apps/services are mono-user with no global data (corrects the
  earlier 'index service with its own wallet' model).
- reconciled shared-wallet-shim brief (per-entity docs, login flow, polyfill terminology),
  authorization-matrix (no Group store), data-layer stack (ng-eventually indirection).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 16:35:58 +02:00
Sylvain Duchesne 222658a75d docs(concepts): shared-wallet-shim — statut d'implémentation (flags OFF)
Couche compte/login + isolation livrées et vérifiées ; couche multi-document
(storeRegistry) livrée derrière FESTIPOD_MULTISTORE/FESTIPOD_STAGING (OFF par
défaut, mono-store reste le défaut), runtime NG à valider sur broker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:05:55 +02:00
Sylvain Duchesne 0294e3992f docs(concepts): migrate project docs into 7 concepts + code-grounded audit
Migrate .project/{knowledge,decisions,briefs} and the always-loaded
AGENTS.md/CLAUDE.md into the in-repo `concept` system (hook-delivered,
typed leaves). Then audit the actual code to verify the migrated doctrine
and capture knowledge that lived only in the source.

Concepts (53 leaves):
- functional-domain — produit : point de rencontre greffé, acteurs, déduplication
- app-architecture — modules, invariant d'imports, routing, écrans, styling-system,
  screen-pattern, cookbook d'ajout d'écran
- tech-stack — Bun-first, APIs, build pipeline, deployment (Dockerfile), commandes
- data-layer — NextGraph mono-store, shapes, modes, règles + caveats (suppression,
  champs non persistés, internals du contexte)
- bdd-testing — Cucumber multi-couches, contrat de couches, harness, cookbook
- app-security — posture actuelle (mono-store, confiance broker), auth wallet,
  brief matrice d'autorisations cible
- nextgraph-platform — NextGraph système externe + briefs (multi-store, shim, fork)

Audit corrections:
- décision SPARQL-delete annulée (superseded) → caveat (le code utilise ngSet.delete,
  persistance possiblement partielle)
- divergences relevées : routing path-based (pas hash), thème moderne sous components/sketchy,
  ConnectScreen hors registre, build:orm au chemin périmé, champs d'event perdus en connecté

Strip migrated sources; AGENTS.md/CLAUDE.md réduits au cœur (but, invariants,
carte des concepts) + pointeurs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 14:58:44 +02:00
Sylvain Duchesne 445a448031 docs: NextGraph multi-user data model — stores, auth matrix, inbox fork plan
Capture the multi-user design exploration as project knowledge + briefs:
- knowledge: NextGraph store types/permissions (+ inbox at protocol, SDK
  exposure, local repo path); integration model (iframe, where the verifier
  runs, generic JS plumbing, ngd stateful, build-time broker target)
- briefs: multi-store refactor; authorization matrix + query inventory +
  derived store partitions; temporary fork to expose the inbox (3 layers:
  SDK fork, Coolify self-hosting, Festipod integration; libs via build:ng)
- fix stale @ng-org versions (alpha.11 -> alpha.13) and a broken
  decision-record link in data-layer.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:38:51 +02:00
Sylvain Duchesne ffda889f34 docs: rewrite README around point-de-rencontre model + add authorization brief
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 12:03:37 +02:00
Sylvain Duchesne fd6d408de1 deps: install @ng-org packages from npm instead of local tarballs
The @ng-org/* SDK alpha versions are now published on npm. Switch the
package.json dependencies from .ng-tarballs/*.tgz paths to npm
versions, removing the need for a sibling nextgraph-rs build to
install the project. Makes containerized deploys (Coolify) trivial.

- @ng-org/alien-deepsignals: 0.1.2-alpha.11 (unchanged)
- @ng-org/orm: 0.1.2-alpha.15 → 0.1.2-alpha.18
- @ng-org/shex-orm: 0.1.2-alpha.7 → 0.1.2-alpha.8
- @ng-org/web: 0.1.2-alpha.11 → 0.1.2-alpha.13

scripts/build-ng-packages.sh and the .ng-tarballs/ workflow remain
available for local development against an unreleased nextgraph-rs
build (`.gitignore` keeps the directory ignored).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 12:03:36 +02:00
Sylvain Duchesne 5a29938130 Modern UI port, render-based @ui tests, dev seed, layer contracts
- Port modern clean theme (DM Sans, orange accent, app-* CSS classes)
  and screen redesigns from festipod-mockups; replace sketchy Ubuntu
  theme. New shared components: BottomNav, EventCover, EventMeetingPoints,
  Toast, AvatarStack, Tag, RelevanceIcon.

- Restructure from prototyping shell to real mobile web app:
  path-based routing (History API), Gallery/DemoMode/PhoneFrame removed,
  Storybook setup for screen/component browsing.

- ConnectScreen ported from mockup (QR-based user connection); routed
  at /profile/connect, wired from FriendsListScreen.

- Dev-only auto-seed of NG wallet when empty
  (gated on NODE_ENV !== 'production'); bootstrapWallet already
  self-checks for non-empty ngSet so safe even in race conditions.

- Render-based @ui test infrastructure: happy-dom + LocalDataProvider +
  RouterProvider via src/shared/test-harness/renderHelper.tsx, exposed
  on the world as renderedDoc. world.hasText/hasField/hasElement prefer
  the rendered DOM and fall back to source for backward compatibility.

- Migrate 25 brittle @ui assertions from regex-on-source to DOM
  queries; delete implementation-detail tests (showDuplicateWarning,
  importableEvents, importedFrom — anti-patterns per the new contract).
  Update feature files where the UI changed: "Mes amis" → "Mon réseau",
  "Mes événements à venir" → "À venir" on home, Thématique removed
  from create-event wizard, etc.

- Path-based @e2e steps (pushState + popstate dispatch) replacing the
  legacy "#/demo/…" hash routing tied to the deleted Gallery.

- Add .project/knowledge/test-layer-contracts.md defining the role of
  each test layer (@ui = display with seed data + DOM, @data = mutations
  through NG broker, @e2e = critical user journeys) with anti-patterns
  and migration consequences.

Test status: 75 passed / 71 skipped (explicit "non implémenté")
/ 2 failed (pre-existing @wip on ngSet.delete() NG ORM limitation).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 09:49:50 +02:00
Sylvain Duchesne 7099c817db Pure useShape API for mutations, event lifecycle e2e tests
Refactor FestipodDataContext to use only the useShape ORM API:
- Remove ng.sparql_update, sessionPromise, ensureGraphNuri imports
- Use privateNuri (useShape scope) directly as @graph for adds
- Create/join are now synchronous (no async wrapper needed)
- Leave uses ngSet.delete() — known limitation: doesn't persist (@wip)

Add event lifecycle e2e scenarios (cycle-de-vie-evenement.feature):
- Create event via form and verify on home screen
- Created event persists after reconnexion
- Consult event detail from home
- Join an event
- Modify event location and verify
- Leave + persistence tagged @wip (ngSet.delete doesn't persist)

Fix DemoMode external navigation: sync initialScreenId prop changes
to internal state via useEffect (was ignored after first mount).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 13:03:02 +02:00
Sylvain Duchesne 6b95695d34 Fix leaveEvent persistence: use SPARQL DELETE instead of ORM ngSet.delete()
ngSet.delete() updates the local reactive set but does not persist to the
broker. Use ng.sparql_update() with SPARQL DELETE WHERE to remove RDF triples
directly — the broker sends back a GraphOrmUpdate that reactively removes the
item from the ORM set. The two methods must not be combined as they conflict
in the CRDT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 12:28:02 +01:00
Sylvain Duchesne ea8fbcf8b7 Fix NextGraph write persistence: use private_store_id as useShape scope
Writes (doc_create, orm_frontend_update) failed with RepoNotFound because
useShape with did:ng:i scope doesn't open individual repos in the verifier's
cache. Switched to did🆖${session.private_store_id} as both scope and
@graph, matching the expense-tracker-rdf pattern. This opens the private
store repo via orm_start_graph, making it available for subsequent writes.

Also adds wallet login step to ensureAuth so the verifier bootstraps repos
from the remote broker into localStorage on first run.

Key changes:
- useShapeWithDefaults accepts storeNuri param (private store NURI)
- FestipodDataContext.useNgData() passes private store scope
- ensureGraphNuri() simplified: reuse existing @graph or private_store_id
- ngBootstrap uses ensureGraphNuri + flushAndWait between ORM adds
- harness-ng.tsx uses private store scope for test bridge shapes
- hooks.ts: wallet creation logs in to bootstrap verifier repos
- E2e steps for data loading and persistence verification

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 11:51:12 +01:00
Sylvain Duchesne 708cbeead8 E2E testing infrastructure, NextGraph connection fixes, and documentation
- Add @e2e test layer: real app in broker iframe via Playwright
- Fix broker redirect: conditional auto-init only when inside iframe
- Fix seed data flash: empty data during 'connecting' phase
- Fix Gallery button in iframe: explicit navigate instead of history.back
- Add auth e2e feature scenarios and step definitions
- Update docs: bdd-testing, data-layer-testing, data-layer, AGENTS.md
- Add decision record for conditional NG init approach

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 17:51:44 +01: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 c9bc957d2a Suggest on creation + distance in kms 2026-01-26 18:32:16 +01:00
Sylvain Duchesne b7f86b139f Warning if similar event exists 2026-01-26 18:12:34 +01:00
Sylvain Duchesne 2415409374 Update event 2026-01-26 18:05:10 +01:00
Sylvain Duchesne 22164b8bb0 E-mail notifs in prefs 2026-01-26 17:43:59 +01:00
Sylvain Duchesne 9181cf46a0 Add welcome page and helpers texts 2026-01-26 17:37:50 +01:00
Sylvain Duchesne 561a0df3fe User profile page with past and future events 2026-01-26 17:29:10 +01:00
Sylvain Duchesne 3fb60388fb Update meeting points 2026-01-26 17:20:33 +01:00
Sylvain Duchesne 21f33faf4a Unkown users 2026-01-26 15:58:42 +01:00
Sylvain Duchesne 9836a2c5fe Events on several days and public only 2026-01-26 15:49:02 +01:00
Sylvain Duchesne 5258b46c8d Icon sharing button 2026-01-26 15:48:28 +01:00
Sylvain Duchesne 8e673a5690 Replace font 2026-01-26 15:46:07 +01:00
Sylvain Duchesne 0179f74407 Replace Organisateur with Relayé par
- EventDetailScreen: person who shared the event is now "Relayé par"
- ProfileScreen/UserProfileScreen: remove role badges from event lists
- FriendsListScreen: Organisateur/Organisatrice → Relayeur/Relayeuse
- Update event data to transition-themed examples

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 15:27:26 +01:00
Sylvain Duchesne 82b04c0258 Add location to events + improve examples 2026-01-26 15:15:36 +01:00
Sylvain Duchesne 157e04b859 Rephrase home title 2026-01-26 14:54:46 +01:00
Sylvain Duchesne cbbd53850b Remove contact exchange section from meeting points
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 14:42:38 +01:00
Sylvain Duchesne 92a835e553 Replace multiple share buttons with single Share + Copy Link
- ShareProfileScreen: Remove 3 individual share options (SMS, Email, Copy)
  and replace with single "Partager" primary button
- MeetingPointsScreen: Add "Copier le lien" button alongside "Partager"

Task: 0NGEZ8E5

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:04:02 +01:00
Sylvain Duchesne a3e89e65c9 Complete feature file audit and fix scenarios
- Fix US-6: Rename to "M'inscrire/me désinscrire à un atelier" and remove
  non-atelier scenarios
- Fix US-9: Add missing scenario for "Ajouter une photo personnelle"
- Fix US-13: Add scenarios for "Modifier" and "Supprimer" événement,
  plus "Retirer une organisation"
- Fix US-14: Mark all scenarios as non-implemented (no atelier screen)
- Fix US-15: Distinguish événement vs atelier scenarios, remove unclear ones
- Fix US-16: Implement 4 scenarios for MeetingPointsScreen
- Fix US-22: Implement 5 scenarios for ShareProfileScreen (parrainage)
- Fix US-23: Implement 3 scenarios for profile sharing

Add missing scenarios from user story descriptions:
- US-1: Programme détaillé, zone partage collective
- US-2: Programme détaillé des ateliers
- US-4: Icône ajouter commentaire
- US-5: Interactions Date/Heure/Lieu
- US-7: Recherche Mobilizon
- US-8: 4 scenarios for macro-événement
- US-12: Vue carte des événements
- US-20: Profils publiques

Add new step definitions:
- l'écran contient un bouton {string}
- l'écran contient un champ {string}
- l'écran contient un texte {string}
- l'écran contient un avatar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 12:49:41 +01:00
Sylvain Duchesne 7827479e9c Simplify skipped scenario format with placeholder step
Replace @skip tag + placeholder step with just placeholder step.
Skipped scenarios now only need:
  Scénario: Name
    * Scénario non implémenté

- Remove @skip tags from all 26 feature files
- Add step definition returning 'skipped' for placeholder
- Update GherkinHighlighter to hide placeholder and make
  skipped scenarios non-expandable (no chevron, no click)
- Update documentation with new format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:31:42 +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 fd5fab5bd2 Merge User Stories page into Specs page
- SpecsPage: Add screen filter, scroll-to-story, selection highlight
- FeatureFilter: Add screen filter chips for both mobile and desktop
- Router: Redirect /stories/* routes to /specs/* for backward compatibility
- App: Remove UserStoriesPage routing, simplify navigation
- Gallery: Remove User Stories button, keep only Specs BDD
- Button: Add cursor-pointer to base styles

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 20:02:39 +01:00
Sylvain Duchesne 4ae96b0e94 Display user story description as multiline in specs pages
- GherkinHighlighter: Render user story lines (En tant que, Je peux,
  Afin de) in a violet card at the top of feature details
- FeatureView: Remove duplicate description display (now in GherkinHighlighter)
- SpecsPage: Display feature cards in single column layout with
  multiline user story formatting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 19:43:34 +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 9620461b36 Rewrite step definitions with inline detection logic
- Replace abstraction functions with inline regex patterns in step definitions
- Add clear test outcomes: Pass/Fail for testable features, Pending with
  specific prefixes (NOT IMPLEMENTED, CANNOT TEST, WRONG STEP, NOT ON THIS
  SCREEN) for non-testable features
- Fix GherkinHighlighter to use step.text instead of step.originalLine
  for step definition matching
- Update documentation with Test Outcomes section
- Extend test:cucumber script to run all parsing steps

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 19:20:04 +01:00