Skip to content

fix(ux): close 3 parcours bugs (Step 7 art. 25 flip, prohibition short-circuit, copy)#8

Closed
abk1969 wants to merge 1 commit into
test/component-smokefrom
fix/parcours-ux-bugs
Closed

fix(ux): close 3 parcours bugs (Step 7 art. 25 flip, prohibition short-circuit, copy)#8
abk1969 wants to merge 1 commit into
test/component-smokefrom
fix/parcours-ux-bugs

Conversation

@abk1969
Copy link
Copy Markdown
Owner

@abk1969 abk1969 commented May 15, 2026

Summary

Closes 3 bugs identified by the UX/parcours audit on the 7-step flow. Stacks on PR #7.

Bug #1 (CRITICAL) — Step 7 unreachable for art. 25 flip path

Symptom: An integrator who declares `nature='systeme_sur_gpai'` + `substantialModification='oui'` is reclassified as a GPAI provider by the classifier (PR #3, Item D), but Step 7 only showed the systemic-risk question when `nature==='gpai'`. Their `gpaiSystemic` stayed `null` → `isGPAI_RS` evaluated to `false` → they were classified as plain GPAI even at ≥ 10²⁵ FLOPs.

Fix: Step 7's visibility predicate now matches both paths:

```js
const gpaiQuestionApplicable =
answers.nature === 'gpai' ||
(answers.nature === 'systeme_sur_gpai' && answers.substantialModification === 'oui');
```

`canNext` updated symmetrically. The classifier already supported `GPAI_RS` for the flip path (PR #3 D1 tests pass) — this UI fix unblocks that codepath.

Bug #2 (IMPORTANT) — Prohibition short-circuit ignored carve-out claims

Symptom: `goToResultIfProhibited` jumped straight to verdict on any prohibition selection. A user who picks prohibition (h) AND claims the art. 5(2)–(3) carve-out (PR #3, Item A) would skip Annex I/III/50/GPAI entirely and land on RISQUE_MINIMAL with just the carve-out trace — even if they should have ticked Annex III §1 biometrics.

Fix: short-circuit only fires if at least one selected prohibition has no claimed-and-matched carve-out:

```js
const hasUnCarvedOutProhibition = prohibitions.some(id => {
const carveOutClaimed = !!carveOuts[id];
const carveOutExists = ART5_CARVEOUTS.some(c => c.appliesTo === id);
return !(carveOutClaimed && carveOutExists);
});
```

Bug #3 (MINOR — copy) — q7Sub / q7NotApplicable contradicted flipped integrators

Symptom: The "not applicable" message read "you are not a GPAI" — false for someone who declared substantial modification (PR #3 Item D made them a GPAI provider for the modified model).

Fix: Updated EN+FR copy on `UI.q7Sub` and `UI.q7NotApplicable` to acknowledge the art. 25 flip path. With Bug #1 fixed, this message is now reserved for users who are neither native GPAI providers nor substantially-modifying integrators.

UX note — Cumulativity rappel on Step 5

Added a one-line reminder to `q5Sub` (EN+FR) that art. 5 prohibitions, Annex III, and art. 50 transparency are cumulative — same underlying tech (biometric ID, emotion recognition) may need ticking in multiple steps because each tests a distinct legal regime. Reduces user confusion / risk of underdeclaring.

Tests + build

  • 113 tests pass (unchanged count — no logic changes in classify.js; UI-only fixes)
  • Build green: 279.21 kB JS / 84.52 kB gzip (+1 kB from new copy)
  • Component smoke tests still pass (App still renders, Step 1 still navigates)

Test plan

  • Integrator path: nature='systeme_sur_gpai' + substantialModification='oui' + Step 7 'oui' → verdict primary === 'GPAI_RS' (was 'GPAI')
  • Carve-out path: prohibition (h) ticked + art. 5(2)-(3) carve-out claimed → user continues to Step 4, not jumped to verdict
  • Non-flipped integrator (substantialModification='non') reaches Step 7 and sees the "not applicable" message with the new wording
  • French UI: q7Sub mentions "art. 25" and "modèle GPAI tiers"
  • Step 5 sub-question copy reminds user that regimes are cumulative

🤖 Generated with Claude Code

Bug #1 (critical) — Step 7 systemic-risk question was hidden for art. 25 flip
  Integrators flipping to provider via substantialModification='oui' could
  never reach GPAI_RS classification because Step 7's gpaiQuestionApplicable
  check only matched nature==='gpai'. Now also matches the flip path:
  nature==='systeme_sur_gpai' && substantialModification==='oui'. canNext
  updated symmetrically. The classifier already supported GPAI_RS for the
  flip path (PR #3 D1) — this UI fix makes that path reachable.

Bug #2 (important) — Prohibition short-circuit ignored carve-out claims
  goToResultIfProhibited jumped to verdict on ANY prohibition selection,
  bypassing Annex I/III/50/GPAI steps. A user with prohibition (h) +
  art. 5(2)-(3) carve-out claim would land on RISQUE_MINIMAL without
  ever being asked about Annex III §1 biometrics. Now short-circuits only
  if at least one selected prohibition has no claimed-and-matched carve-out.

Bug #3 (copy) — q7Sub / q7NotApplicable mentioned only GPAI providers
  Updated EN+FR to acknowledge the art. 25 flip path so the "not applicable"
  message no longer contradicts a flipped integrator's status.

UX note — added a cumulativity rappel to q5Sub
  Reminds the user that art. 5 prohibitions (step 3), Annex III §1 (step 5),
  and art. 50 transparency (step 6) are cumulative — same underlying tech
  may need ticking in multiple steps because each tests a distinct legal
  regime.

Tests + build green at 113/113.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ai_act_compass Ready Ready Preview, Comment May 15, 2026 3:30pm

abk1969 added a commit that referenced this pull request May 16, 2026
Closes the last TDD audit recommendation: end-to-end coverage of the 7-step
parcours in a real browser. Catches the class of bug where the React tree
renders successfully and unit/component tests pass, but the user flow lands
on the wrong screen — exactly what happened pre-PR #8 with the art. 25 flip
unreachable Step 7 and the prohibition short-circuit ignoring carve-outs.

Infrastructure:
- devDep: @playwright/test
- playwright.config.js — auto-spawns `npm run dev` on :5173, single Chromium
  project, retain trace + screenshot on failure
- .gitignore — exclude test-results/ + playwright-report/

Tests (e2e/parcours.spec.js):
1. happy path — provider with no triggers → RISQUE_MINIMAL
2. high-risk deployer Annex III §3 → HAUT_RISQUE_ANNEXE_III + FRIA visible
3. art. 25 flip — integrator + substantialModification + systemic risk →
   GPAI_RS (regression guard for Bug #1 from the parcours audit)
4. art. 5 carve-out claim does NOT short-circuit — user advances to Step 4
   instead of jumping to verdict (regression guard for Bug #2)

Selectors anchor on the OptionCard aria-label, which composes
`<title> — <sub> — <desc>`. Matching unique sub fragments (e.g. "art. 3(3)",
"art. 5(1)(h)", "art. 5(2)-(3)") keeps selectors stable across copy edits.

Run: `npx playwright test` — 4 tests pass in ~25 s. Not wired into
`npm test` (Vitest scope); future CI could add a separate e2e job.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@abk1969 abk1969 deleted the branch test/component-smoke May 16, 2026 12:44
@abk1969 abk1969 closed this May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant