Skip to content

chore(#107): code-health umbrella — all frontend strands (a11y/perf/quality/architecture/validation/keyboard/i18n) - #172

Merged
thomasluizon merged 18 commits into
mainfrom
chore/107-code-health-sweep
Jun 13, 2026
Merged

chore(#107): code-health umbrella — all frontend strands (a11y/perf/quality/architecture/validation/keyboard/i18n)#172
thomasluizon merged 18 commits into
mainfrom
chore/107-code-health-sweep

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

What

Consolidated code-health PR for the #107 umbrella — all frontend strands in one PR (web + mobile + shared), driven by a recursive audit → fix → re-sweep loop until every audit domain reports zero non-deferred findings.

Closes #107

Paired backend PR: thomasluizon/orbit-api#205 — squash-merge it first so the additive errorCode API contract is live before this consumer side.

Highlights

  • Comment-policy lint (Strand 4): packages/shared now enforces local/no-comments=error (284 narration comments autostripped); rule-5 documented in the three workspace CLAUDE.md files; 24 stale CLAUDE.md references fixed.
  • Validation parity (Strand 5): habit create/edit submit-gating and API-key-expiry parsing now identical web↔mobile, sourced from shared schemas/constants; the old titleFilled mobile gate is gone.
  • Function-size (Strand 1): every >100-line function split or registered as a justified orchestration root. Notable splits: useChatComposer (both platforms), ChatPage, CalendarSyncScreen, the profile/ai-settings/preferences/retrospective/login/support/streak/achievements pages.
  • Accessibility: app-wide contrast migration to AA-passing -text/fg-3/fg-on-bad tokens; accessibilityRole added to every mobile interactive element; hit targets ≥44; overlay focus restore; control names; focus rings; reduced-motion gating.
  • Keyboard/back parity: a shared overlay-stack (useOverlayEscape web / useOverlayBack mobile) so ESC and Android-back resolve the top-most layer LIFO across date-picker/emoji/description-viewer/tour/level-up/push-prompt; ErrorBoundary on mobile root + web (chat); dnd KeyboardSensor.
  • DRY: orphaned shared cores (tag-selection-core, dismiss-guard-core) wired into both platforms; highlightText lifted to shared.
  • Error-code localization (client half): getErrorMessage/auth error mapping now resolve the backend errorCode first (paired with the API change).
  • Perf (static): FlatLists for unbounded lists; Today/Calendar swipe → RNGH worklet; transform-only animations; dead deps removed (incl. the radix/shadcn stack), underscore DoS pinned out, @next/env removed.

Validation

npm run lint + npm run type-check + npm test all green (981 shared / 548 mobile / 1523 web). i18n parity 1628=1628.

Deferrals

Each over-the-bar item carries a written justification (function-size orchestration roots/adapters/non-functions; a11y token-ceiling residuals where WCAG 1.4.1 is met and 1.4.3 needs a DESIGN.md token decision; a few pre-existing test-quality nits). Full register summarized on issue #107.

Not run (per request)

Lighthouse / runtime perf were not run (no chrome-devtools). Worth an eyeball in the running app: the Today/Calendar RNGH swipe and the transform-based loading shimmer.

🤖 Generated with Claude Code

…, API-key expiry parity, error states, profile a11y, RNGH swipe
…reakdown parity, status-text tokens, goals/cal a11y
…r codes, dead code, @next/env, offline copy, emoji/checklist keyboard
…atus-text + fg-on-bad tokens, control names, focus rings
…ightText→shared, dead exports, drill error, focus rings, path constants, register roots
…omments, transform shimmer, modal back, split sub-hook tests
…, strict contrast improvement within deferred family)
@vercel

vercel Bot commented Jun 13, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jun 13, 2026 4:11pm

Comment thread apps/web/lib/auth-proxy.ts Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One hard-rule violation to fix before merge.

Finding: apps/web/lib/auth-proxy.ts:50-52logAuthRouteFailure introduces a console.error in production code, violating CLAUDE.md rule 4 ("don't log when no project logger exists"). The old empty-catch blocks silently swallowed errors (a rule 8 violation); the right fix is to remove the log rather than add one. Each catch already returns a structured 500 with the requestId, which is sufficient for client-side observability. Remove logAuthRouteFailure and its four call-sites in the auth route handlers, reverting each catch (error) binding to a bare catch.

Everything else in this 401-file sweep is clean: i18n parity is 1628=1628, web/mobile parity is maintained throughout, types are sound in production code (any in test files is explicitly allowed by the ESLint config), no dead exports, no useless comments introduced, and the new test coverage is substantive.

…ective/preferences/profile) for SonarCloud new-code gate
Comment thread apps/web/lib/auth-proxy.ts Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prior finding still unresolved after the two new commits (b94ff06 web tests, 03a6d5d merge). The logAuthRouteFailure function with console.error in apps/web/lib/auth-proxy.ts remains. Fix: delete that function and its four call-sites in the auth route handlers.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prior finding still unresolved. logAuthRouteFailure (apps/web/lib/auth-proxy.ts:50-52) introduces a console.error in production code, violating CLAUDE.md rule 4. The two new commits (b94ff06 test coverage, b04bece test type fix) are clean. Fix: delete logAuthRouteFailure and its call-sites in the auth route handlers — each catch already returns a structured 500 with the requestId, which is sufficient for observability without a console log.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prior finding still unresolved. logAuthRouteFailure (apps/web/lib/auth-proxy.ts:50-52) introduces a console.error in production code, violating CLAUDE.md rule 4. The two new commits (b94ff06 test coverage, b04bece test type fix) are clean. Fix: delete logAuthRouteFailure and its call-sites in the auth route handlers — each catch already returns a structured 500 with the requestId, which is sufficient for observability without a console log.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prior finding still unresolved: logAuthRouteFailure at apps/web/lib/auth-proxy.ts:50-52 introduces console.error in production code, violating CLAUDE.md rule 4. The two new commits (b94ff06 test coverage, b04bece test type fix) are otherwise clean. Fix: delete logAuthRouteFailure and its four call-sites in the auth route handlers.

logAuthRouteFailure wrapped a console.error, which rule 4 prohibits
(no console in production code; no project logger exists). Each auth
route catch already returns a structured 500 with requestId, so the
log carried nothing the response doesn't. Remove the helper, its four
call-sites, and the three console.error spy assertions (which tested
an implementation detail, not behavior).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid code-health umbrella. Zero rule violations across all 410 files reviewed. Highlights: the auth store logout now goes through apiClient (dropping the old direct fetch with a hardcoded base-URL fallback — two rule-5 violations fixed in one); all empty catch blocks properly surface errors to state rather than swallowing them; any usage is confined to test helpers; no console statements in production code; i18n parity held at 1628 keys each locale. The function splits, accessibility token migration, overlay-back stack, and cross-platform validation parity are all clean and complete. Ready to merge.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid code-health umbrella. Zero rule violations across all 410 files reviewed. Highlights: the auth store logout now goes through apiClient (dropping the old direct fetch with a hardcoded base-URL fallback); all empty catch blocks properly surface errors to state rather than swallowing them; any usage is confined to test helpers; no console statements in production code; i18n parity held at 1628 keys each locale. The function splits, accessibility token migration, overlay-back stack, and cross-platform validation parity are all clean and complete. Ready to merge.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid code-health umbrella. Zero rule violations across 410 files. The auth store logout now uses apiClient (dropping a direct fetch with hardcoded base-URL fallback). All catch blocks surface errors to state. No any in production, no console statements, i18n parity held at 1628 keys per locale. Function splits, a11y token migration, overlay-back stack, and cross-platform validation parity all clean. Ready to merge.

@thomasluizon
thomasluizon merged commit 1c6d2da into main Jun 13, 2026
8 checks passed
@thomasluizon
thomasluizon deleted the chore/107-code-health-sweep branch June 13, 2026 16:31
thomasluizon added a commit that referenced this pull request Jun 14, 2026
…#174)

* fix(mobile): lazy Supabase client to stop grey-screen crash on launch

#172 removed the public Supabase URL/key fallbacks in lib/supabase.ts and
added a top-level `throw new Error('Supabase config missing')`. The build
sets no EXPO_PUBLIC_SUPABASE_* vars, so the module threw at import-time;
expo-router then failed to load the route importing it (via lib/google-auth.ts)
and crashed with "Cannot read property 'ErrorBoundary' of undefined" — a grey
crash-loop on every launch, regardless of auth state.

Mirror apps/web/lib/supabase.ts: create the client lazily via
getSupabaseClient() so a missing/optional config can never crash the app
shell at module-eval. Restore the public project URL + sb_publishable key as
in-code fallbacks (a publishable key + EXPO_PUBLIC_ vars ship in the client
bundle anyway — not secrets). Google OAuth call sites in google-auth.ts use
the getter.

Verified on device: login screen renders, no Supabase/ErrorBoundary errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(mobile): update google-auth mock for getSupabaseClient

The lazy-client refactor renamed the supabase export; the google-auth test
mock still returned `supabase`, so the suite failed with "No getSupabaseClient
export is defined on the @/lib/supabase mock". Mock getSupabaseClient() instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
thomasluizon added a commit that referenced this pull request Jun 15, 2026
…bmit gate (#175)

* fix(ui): UX/QA batch across web + mobile (26 items) + create-habit submit gate

Cross-platform UX/QA pass plus shared error localization. Highlights:
- Chat: voice-recording race fix; language picker moved to the chat header
- Calendar: tappable centered month nav, day-detail modal, centered muted
  legend, removed the "x/30 dias" summary
- Errors: backend errors render localized via ERROR_CODE_TO_KEY; login surfaces
  errors through a toast only (no reference code / inline yellow text)
- Retrospective: stats-dashboard + narrative UI with an empty-period state
- Upgrade: exact hero copy + Free/Pro two-column comparison
- Frequency: swipe carousel; streak-freeze celebration auto-dismisses;
  bad = red / overdue = yellow log dots on both platforms
- Preferences option legends relocated into the picker modal; AI-facts paginator
  inline with an icon select
- Support: removed name/email fields; advanced devs: deduped MCP tab
- Widget: fallback drawables + first-add render fix
- pt-BR naturalization across the locale (parity preserved at 1665/1665)
- fix(mobile): restore the title-presence submit gate on the create/edit habit
  modals. #172 reverted #145: with a buffered title input, setValue without
  shouldValidate re-broadcasts the cached onSubmit-mode isValid, so the button
  stayed disabled with a title filled. Gate on useWatch('title') instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(i18n): remove dead orbitMcp.claudeDesktop key

The desktop MCP tab was dropped (MCP_CONFIG_TABS no longer includes 'desktop'),
so this key has no remaining callers. Flagged by the PR review bot. Removed from
both locales; en/pt-BR parity preserved at 1664/1664.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
thomasluizon added a commit that referenced this pull request Jul 17, 2026
* chore(harness): three memory-derived guardrail gates

Convert three operational memories into deterministic dual-target gates
(pure _lib rule -> Claude Code hook + .opencode plugin + test-hooks), so the
knowledge is enforced structurally instead of living only in recallable memory.

- mobile supabase-lazy (checkMobileSupabaseLazy, rules-source.mjs): blocks a
  module-scope throw or top-level createClient() in apps/mobile/**/supabase.ts;
  eager module-eval crashes to a grey screen at launch (#172/#174).
- EF-migration IF-NOT-EXISTS (checkEfMigrationRawIndex, rules-source.mjs): blocks
  a raw migrationBuilder.Sql CREATE INDEX / DROP INDEX lacking IF [NOT] EXISTS in
  orbit-api Migrations; EF runs migrations at startup on Render and a duplicate
  raw index throws Postgres 42P07, failing the deploy. Leaves CreateIndex() alone.
- worktree junction guard (checkGitWorktreeRemove, rules-git.mjs): blocks the
  forced form of git worktree remove; on Windows it follows a junction and deletes
  the link TARGET. Strips heredoc bodies so a message naming the flag is not a
  false positive. Wired into the existing git-guardrails PreToolUse.

Gate: node .claude/hooks/test-hooks.mjs is green (existing + new assertions).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(harness): close false-negative gaps in the three guardrail gates

Addresses the #556 review — each finding was a verified false negative in a
gate whose purpose is preventing a specific prior incident from recurring.

- supabase-lazy (High): the `throw` check anchored to column 0, missing an
  indented / `if (!x) throw` guard-clause form; the createClient regex rejected
  a typed const `export const supabase: SupabaseClient = createClient(...)` —
  the exact style the real apps/mobile/lib/supabase.ts already uses. Now a
  string/comment-aware bracket-depth scan flags any module-scope throw, and the
  regex allows an optional type annotation. The lazy `() => createClient` arrow
  still passes (a new test pins that no false positive was introduced).
- ef-migration-idempotency (High): IF [NOT] EXISTS was tested once against the
  whole Sql() blob, so one idempotent statement masked a sibling raw index in a
  batched call. Now each `;`-separated statement is checked independently.
- worktree-junction (Medium x2): force detection is now segment-scoped like
  checkGitCommand, so `git worktree remove path && npm test -- --force` no longer
  false-blocks; and the block message inlines the SAFE cleanup order instead of
  pointing at a CLAUDE.md section that does not exist.

Gate: node .claude/hooks/test-hooks.mjs green (existing + 6 new regression assertions).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

chore: code-health umbrella — function-size splits + cross-repo agent sweep (a11y/security/perf/quality/architecture/UX)

1 participant