Skip to content

feat: UX hardening P1/P2 — Copilot/Voice, readability, Consistency Checker, AI context#193

Merged
qnbs merged 15 commits into
mainfrom
feat/ux-hardening-p1
Jun 20, 2026
Merged

feat: UX hardening P1/P2 — Copilot/Voice, readability, Consistency Checker, AI context#193
qnbs merged 15 commits into
mainfrom
feat/ux-hardening-p1

Conversation

@qnbs

@qnbs qnbs commented Jun 20, 2026

Copy link
Copy Markdown
Owner

User description

Context

Part 2 of the user-facing UX/interaction-risk hardening set. Part 1 (#191, P0) is merged; this PR carries the P1/P2 items and all CodeAnt-review-wave fixes, rebased directly onto main.

Two audit claims were stale and are not changed here: the Dashboard AI logline is already a safe preview flow (only the readability rendering was a real gap).

Items

3 · Copilot & Voice spatial separation (P1)

The Copilot FAB and Voice panel both anchored at bottom-20/right-4 and overlapped when both flags were on. The voice panel now stacks above the FAB (bottom-[9.25rem] / md:bottom-[5.25rem]), clearing the FAB and the mobile bottom-nav. Adds a visible mode chip (Commands/Dictation).

4 · Dashboard readability scale + logline undo hint (P1)

Readability score now shows /100 plus an interpretation Tooltip (Flesch 0–100, higher = easier). Applying an AI logline fires an undo-hint toast (project slice is redux-undo wrapped).

5 · Consistency Checker structured output (P1)

The consistencyCheck prompt now requests a JSON finding array; the hook parses it into a discriminated ConsistencyResult (robust raw-text fallback so the pane never regresses to empty), and the view renders a severity-tagged list instead of a raw <pre>. CodeAnt waves hardened this further: parse-drop arrays surface as text (no false all-clear), a shape-based isAbortError guard preserves results on cancellation, and the empty-array clean-state contract is honoured end-to-end.

6 · AI context-source labels (P2)

Context notes so users see what feeds the AI: SceneBoard beat modal ("scene titles + opening lines, ~2,000 chars") and the Copilot panel header ("current view + project metadata").

Process docs

docs(process): documents the >100-file PR-split rule (CodeAnt skips larger PRs) as runbook §1a, and the plan-mode parallel-exploration exception to the low-end-hardware shell rule.

Tests & i18n

  • Unit tests across voice mode chip, dashboard undo toast, and consistency JSON parse / text-fallback / abort / parse-drop cases.
  • i18n: voice/dashboard/consistency/sceneboard/copilot keys across all 17 locales (including proper translations for the 12 non-core locales) + rebuilt bundles.
  • Local gate green: suppressions OK, lint, typecheck, i18n:check, targeted vitest.

🤖 Generated with Claude Code


CodeAnt-AI Description

Show consistency checks as structured findings and clarify AI-facing UI

What Changed

  • Consistency checks now show a clear list of findings with severity labels, and an empty result now displays a plain “no findings” state instead of raw output.
  • Aborted consistency checks no longer clear a previous result, including cancellations that arrive as plain abort-shaped objects.
  • The Copilot and voice panels now explain what data they use, and the voice panel shows a visible mode chip for commands vs dictation.
  • Dashboard readability now shows /100 with an explanation tooltip, and applying an AI logline now shows an undo hint.
  • Tooltips now open for keyboard users when the trigger is focused, not only on hover.

Impact

✅ Clearer consistency check results
✅ Fewer lost results after canceled AI checks
✅ More obvious AI context and voice mode labelstitle: |-
Show structured consistency results, voice mode labels, and clearer AI hints

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

qnbs and others added 11 commits June 20, 2026 23:36
…ip (P1)

CopilotLauncher FAB and VoiceControlPanel both anchored at bottom-20/right-4
(md:bottom-4), overlapping in the same corner whenever both flags were on. The
voice panel now stacks above the FAB (bottom-[9.25rem] / md:bottom-[5.25rem]),
clearing the 3.5rem FAB and the mobile bottom-nav. Also adds a visible mode chip
(Commands/Dictation) so the two voice modes are no longer distinguished only by
background colour. i18n: 2 keys across all 17 locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Readability score rendered as a bare number with the 0-100 Flesch scale known
only in the service layer. Now shows /100 plus an interpretation Tooltip so it
isn't mistaken for a normative grade. Applying an AI logline (already a preview
flow) now fires an undo-hint toast — the project slice is redux-undo wrapped, so
Ctrl+Z restores the prior logline. i18n: 3 keys across all 17 locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The consistency-check result was dumped into a raw <pre> block — hard to scan,
no severity, no segmentation. The consistencyCheck prompt now requests a JSON
array of findings; the hook parses it (with a robust raw-text fallback so the
pane never regresses to empty) into a discriminated ConsistencyResult, and the
view renders a severity-tagged list reusing the danger/warning/info state
tokens (mirroring the Story Bible hints). i18n: 5 keys across all 17 locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Users couldn't see what data feeds the AI. Adds a context note to the SceneBoard
beat-suggestion modal (scene titles + opening lines, ~2,000 chars) and a
context-source line under the Copilot panel header (current view + project
metadata) — honestly worded since selection isn't wired into the global launcher
path. i18n: 2 keys across all 17 locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ception

Two standing-rule clarifications:
- CodeAnt skips inline review on PRs >~100 changed files; document the count
  check and the fewest-stacked-PRs split (group by locale module fan-out, stack
  so each PR's incremental diff stays under the limit). New runbook section 1a.
- The low-end-hardware ONE-Bash-per-turn rule targets concurrent heavy shells;
  parallel read-only Explore/Plan agents ARE allowed in plan mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rigor)

- Dashboard: readability tooltip trigger is now a <button> (keyboard-focusable,
  aria-label carries the scale explanation); /100 suffix moved to an i18n key.
- Consistency parser: tolerant severity normalization (warning/ERROR/High →
  warn/error, no silent downgrade to info) + stable per-finding id used as the
  React list key (no collision on similar findings).
- Tests: abort test now seeds a non-null result then aborts to actually verify
  the preserve-result contract; added severity-normalization coverage.
i18n: 1 key across all 17 locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#192)

Addresses CodeAnt: the finding-shape example used TS-union syntax
("error"|"warn"|"info") inside JSON, which models copy literally, breaking
JSON.parse and forcing the raw-text fallback. Replaced with a concrete valid
single-element example and moved the severity enum into prose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t guard (wave 3 #192)

- parseConsistencyResult returns a structured result for any valid JSON array,
  including []; the view renders an explicit 'no inconsistencies' state instead
  of dumping raw [] as text. i18n: consistencyChecker.noFindings (17 locales).
- Abort detection now matches AbortError on both DOMException and plain Error
  (provider layer can emit either; DOMException isn't always an Error subclass),
  so a cancelled run no longer overwrites a valid prior result.
Tests: empty-array structured case + abort guard retained.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e all-clear (wave 4 #192)

A valid JSON array whose every element was malformed (missing both title
and detail) got filtered to an empty findings list and rendered as the
'no findings' clean state — a false all-clear hiding a model/output
failure. Now distinguish a genuinely empty '[]' (no issues) from a
non-empty array that drops to zero findings: the latter falls back to raw
text so the malformed output is surfaced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… contract (wave 5 #192)

Two CodeAnt findings:
- Abort guard used `instanceof DOMException || instanceof Error`, so a
  provider cancellation surfacing as a plain { name: 'AbortError' } object
  (or cross-realm error) was misclassified as a failure and overwrote a
  valid prior result. Export the provider's existing shape-based
  `isAbortError` and reuse it in the hook — single source of truth.
- The consistencyCheck prompt told the model to emit a single 'info'
  finding when there are no issues, making the dedicated empty-array
  'no findings' clean state unreachable. Prompt now returns [] for a
  clean result, matching the parser/view contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…12 non-core locales (wave 6 #192)

check-i18n-keys --fix had left the new UX-hardening keys as English
fallbacks in all non-core locales. CodeAnt flagged the Arabic file
(which is otherwise substantially translated). Provided proper
translations for consistencyChecker.noFindings/refLabel/severity.*,
sceneboard.ai.contextNote, and voice.modeChip.* across ar, he, fa, el,
ja, pt, zh, fi, sv, hu, is, eu, and rebuilt the runtime bundles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@vercel

vercel Bot commented Jun 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
worldscript-studio Ready Ready Preview, Comment Jun 20, 2026 10:19pm

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Jun 20, 2026
Comment thread tests/unit/VoiceControlPanel.test.tsx Outdated
…wave 7 #193)

CodeAnt flagged the dictation-chip test for setting mockMode = 'dictation',
an impossible runtime state — the VoiceMode contract (features/voice/
voiceSlice.ts) uses 'dictating'. Aligned the mock so the test exercises the
real contract and would catch future mode-dependent regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@qnbs

qnbs commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Jun 20, 2026
@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Sequence Diagram

This PR changes the character consistency checker so that AI responses are parsed into structured severity-tagged findings, with a robust fallback to raw text when JSON output is missing or malformed.

sequenceDiagram
    participant User
    participant ConsistencyView
    participant ConsistencyHook
    participant GeminiService
    participant AIProvider

    User->>ConsistencyView: Click Check Consistency for character
    ConsistencyView->>ConsistencyHook: runCheck(characterId)
    ConsistencyHook->>GeminiService: Build consistencyCheck prompt from context
    GeminiService-->>ConsistencyHook: Prompt text
    ConsistencyHook->>AIProvider: generateText(prompt, options, abortSignal)
    AIProvider-->>ConsistencyHook: AI response text

    alt AI returns JSON array of findings
        ConsistencyHook->>ConsistencyHook: parseConsistencyResult to structured findings
        ConsistencyHook-->>ConsistencyView: checkResult = structured findings
        ConsistencyView-->>User: Render severity-tagged findings list
    else AI returns malformed JSON or plain text
        ConsistencyHook->>ConsistencyHook: parseConsistencyResult to text fallback
        ConsistencyHook-->>ConsistencyView: checkResult = text result
        ConsistencyView-->>User: Render raw text block (never empty)
    end
Loading

Generated by CodeAnt AI

Comment thread components/Dashboard.tsx
… shows it (wave 8 #193)

CodeAnt flagged the readability tooltip as not keyboard-reachable. Root
cause is in the shared Tooltip: it revealed on group-focus-visible, but
the .group wrapper is a non-focusable span — focus lands on a focusable
child, which never puts :focus-visible on the wrapper, so keyboard users
got a focus stop that showed nothing. Switched to group-focus-within,
which matches when any descendant holds focus. Fixes the Dashboard
readability tooltip and every other Tooltip wrapping a focusable child.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@qnbs

qnbs commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Jun 20, 2026
@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Sequence Diagram

This diagram shows how the consistency checker now requests structured JSON findings from the AI and preserves results on cancellation, and how applying an AI logline on the dashboard updates state while showing an undo-hint toast.

sequenceDiagram
    participant User
    participant ConsistencyChecker
    participant AIService
    participant Dashboard
    participant ToastService

    User->>ConsistencyChecker: Click Check Consistency for character
    ConsistencyChecker->>AIService: Request consistency check with JSON findings prompt
    AIService-->>ConsistencyChecker: Return JSON array or plain text
    ConsistencyChecker->>ConsistencyChecker: Parse into ConsistencyResult (structured or text)
    ConsistencyChecker-->>User: Show severity list, clean state, or text fallback

    alt Later consistency check is aborted
        User->>ConsistencyChecker: Trigger new check then close panel or navigate away
        AIService-->>ConsistencyChecker: AbortError cancellation
        ConsistencyChecker-->>User: Stop checking but keep previous results
    end

    User->>Dashboard: Apply AI logline suggestion
    Dashboard->>Dashboard: Update project logline state (undoable)
    Dashboard->>ToastService: Show success toast with undo hint
    ToastService-->>User: Display logline updated with Ctrl+Z message
Loading

Generated by CodeAnt AI

Comment thread services/geminiService.ts Outdated
…mpt (wave 9 #193)

The global langInstruction tells the model to translate JSON string
values, which collides with the exact severity enum: in non-English
locales the model could emit a localized severity (e.g. 'avertissement'),
and normalizeSeverity downgrades unknown values to 'info' — hiding real
error-level contradictions. The prompt now explicitly forbids translating
the 'severity' value (literal English error/warn/info), while title/detail/
ref stay translatable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@qnbs

qnbs commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Jun 20, 2026
@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Sequence Diagram

This diagram shows how the Consistency Checker now calls the AI provider for a JSON findings array, parses it into structured results for display, and uses a shared abort guard so cancelled runs do not clear existing findings.

sequenceDiagram
    participant User
    participant Dashboard
    participant ConsistencyChecker
    participant AIProvider
    participant AIModel

    User->>Dashboard: Click Check Consistency for character
    Dashboard->>ConsistencyChecker: runCheck(characterId)
    ConsistencyChecker->>AIProvider: Request consistency check text
    AIProvider->>AIModel: Send prompt with JSON findings contract
    AIModel-->>AIProvider: Return findings array or text
    AIProvider-->>ConsistencyChecker: Deliver response or abort signal

    alt Valid JSON findings
        ConsistencyChecker->>ConsistencyChecker: parseConsistencyResult to structured findings
        ConsistencyChecker-->>Dashboard: checkResult structured (findings or empty)
        Dashboard-->>User: Show severity list or no findings message
    else Cancelled by user
        ConsistencyChecker->>ConsistencyChecker: Detect abort with isAbortError and keep prior result
        ConsistencyChecker-->>Dashboard: Stop checking without changing checkResult
    else Invalid or malformed output
        ConsistencyChecker->>ConsistencyChecker: Fall back to text result
        ConsistencyChecker-->>Dashboard: checkResult as raw text
        Dashboard-->>User: Show plain text block
    end
Loading

Generated by CodeAnt AI

…ine run)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@qnbs
qnbs merged commit d547808 into main Jun 20, 2026
17 checks passed
@qnbs
qnbs deleted the feat/ux-hardening-p1 branch June 20, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant