fix(front): Option A — fixtures only on network failure, 404 degrades to empty (WO-11) - #119
Merged
Merged
Conversation
…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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Jul 28, 2026
This was referenced Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
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_ratioandfirst_person_ratiowere documented as "fraction of sentences" when neither is, which had skewed three fixture values by a factor of ~45. Corrected separately, already onmain.Checklist
make test)make lint)docs/.env.exampledocs/api_contract.yamlREADME.mdupdated