Skip to content

fix(front): Option A — fixtures only on network failure, 404 degrades to empty (WO-11) - #119

Merged
sergi-torres merged 3 commits into
mainfrom
fix/wo-11-fixture-honesty
Jul 28, 2026
Merged

fix(front): Option A — fixtures only on network failure, 404 degrades to empty (WO-11)#119
sergi-torres merged 3 commits into
mainfrom
fix/wo-11-fixture-honesty

Conversation

@sergi-torres

@sergi-torres sergi-torres commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Base is fix/wo-12-distinctive-vocab, not main. Stacked PR, and a sibling of #118 — both descend from #117 and collide with each other in style-dna.ts, page.tsx and GenerateStudio.tsx.

What

Implements Option A, decided on 2026-07-27: fixtures are used only on network failure or a 5xx. A legitimate 404 degrades to an empty state instead of being silently replaced by an invented StyleProfile.

Until now the Style DNA screen displayed fabricated data with nothing distinguishing it from real data — a user (or a juror) had no way to tell whether what they saw came from the pipeline or from an example file.

Why

Closes #92

How IBM Bob helped

  • Custom Mode used: none
  • Bob session export: n/a

Claude Code agents. The underlying decision (Option A versus continuing to substitute) was not made by an agent: it was escalated and recorded in docs/decision_log.md.

Screenshots / output

Known and accepted consequence: with an unseeded database, the Style DNA screen renders empty. That is correct, not a regression — it is exactly what Option A asks for. What fills it is the seed (#86), which in turn depends on #112.

Related finding: cross-checking the fixtures against the contract revealed that dialogue_ratio and first_person_ratio were documented as "fraction of sentences" when neither is, which had skewed three fixture values by a factor of ~45. Corrected separately, already on main.

Checklist

  • Tests pass locally (make test)
  • Lint passes (make lint)
  • If schema changed (StyleProfile / Passport) → bumped version + updated docs/
  • If new env var → added to .env.example
  • If new/changed endpoint → updated docs/api_contract.yaml
  • Documentation in the relevant README.md updated
  • At least one teammate reviewed

Expected conflict in docs/decision_log.md when this retargets to main: it is append-only with four writers. Keep all rows, never delete someone else's.

This is the widest branch in the batch (11 files). It goes last in the frontend chain on purpose. Also merge #115 before this one — both touch frontend/src/lib/api.ts.

sergi-torres and others added 2 commits July 28, 2026 00:27
…ble (#92)

WO-11, option A (decision_log 2026-07-27). Both load points substituted a
hand-written fixture on ANY error, including a legitimate 404 from an
unseeded DB, and presented it exactly like measured data:

  - components/StyleDnaPanel.tsx::fetchProfileWithFallback
  - app/author/[id]/page.tsx::loadDistinctiveTerms (bare .catch)

Now a fixture stands in only when the backend gave no answer — a rejected
fetch (NetworkError) or a 5xx (ServerError). A real 404 degrades to the
neutral empty state: EmptyState in the panel, [] for the highlight terms
(no marks, no legend, no throw). Any other 4xx surfaces as an error.

lib/api.ts gains typed NetworkError / ServerError plus the single predicate
isFixtureEligibleError; both load points and the scatter's author-list
fallback route through it, so no bare catch remains. No response shape and
no docs/api_contract.yaml change.

Fixture honesty: the file header now describes the behaviour the code
implements instead of the guarantee it had stopped honouring, and the values
are re-based inside docs/style_features.md §7 (17 of 30 tracked metrics were
out of range; all three first_person_ratio values were [0,1] fractions
instead of the per-1k-token unit §3.4 defines).

Tests: components/StyleDnaPanel.test.ts (the 404-vs-network decision) and
lib/fixtures/style-profiles.test.ts (substitution rule + §7 range guard).

Accepted consequence: on an unseeded DB the Style DNA panel renders empty.
That is the correct empty state; seeding (#86) is what fills it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The seeded fallback list returned by getAuthorCards() when GET /api/authors
fails hardcodes has_style_profile: true. With the backend down the home screen
therefore shows three cards asserting a computed profile exists, and sends the
user to a Style DNA panel that — correctly, after option A — renders empty.

Names, slugs and bios are static editorial metadata and stay: serving them
offline claims nothing new, and the selector must not render empty. But
has_style_profile asserts measured state this constant cannot know, so it is
now false. The honesty rule of design-system.md 8.6 covers any claim about
what was computed, not just the numbers.

Both the WO-11 executor and its independent verifier flagged this path as the
last remaining way the UI can assert something it has not measured. Committed
separately from e732ad1 so the verified scope stays legible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
author-ai Error Error Jul 28, 2026 4:52pm

@sergi-torres
sergi-torres merged commit 3f4e39e into main Jul 28, 2026
6 of 8 checks passed
@sergi-torres
sergi-torres deleted the fix/wo-11-fixture-honesty branch July 28, 2026 16:52
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.

[frontend] WO-11 — REQUIERE DECISIÓN — Resolver la sustitución silenciosa de StyleProfiles por fixtures inventados

1 participant