Skip to content

chore(lint): enforce ESLint in CI + type-aware rules (#414, #415) - #426

Merged
thomasluizon merged 1 commit into
mainfrom
issue-414
Jul 8, 2026
Merged

chore(lint): enforce ESLint in CI + type-aware rules (#414, #415)#426
thomasluizon merged 1 commit into
mainfrom
issue-414

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

Bundles #414 + #415 (correlated lint hardening).

#414 — ESLint as a blocking CI job

Adds a Lint job to .github/workflows/test.yml running npx turbo run lint across web/mobile/shared (previously lint ran in no workflow, so error-level rules were unenforced). Includes a .turbo cache step. Register Lint as a required check after merge (documented in #420).

#415 — type-aware rules + cognitive-complexity cap

Enables typescript-eslint recommendedTypeChecked + explicit no-unnecessary-condition + sonarjs/cognitive-complexity (15) across web, shared, and mobile, wired via parserOptions.projectService. 777 raw findings → 0 errors, fixed behavior-preservingly:

  • promises (floating → await/void; misused → house () => void fn() idiom / sync-wrap)
  • no-unsafe-* → honest boundary typing at res.json()/JSON seams (no as any)
  • redundant type-assertions, require-await, unbound-method, misc
  • 3 clean cognitive-complexity extractions

Two rules graduated to warn (unsafe to batch-fix; tracked follow-ups): no-unnecessary-condition#424 (guard-deletion risk at untyped boundaries), cognitive-complexity#425 (large core-screen refactors need visual verification). 229 warnings remain, all from these two graduated rules.

Validated: turbo run type-check 3/3, turbo run lint 3/3 (0 errors), turbo run test 3/3 (web 2150, shared 1411, mobile green). Parity maintained across web↔mobile fixes.

🤖 Generated with Claude Code

#414 — add a blocking Lint job to test.yml (`npx turbo run lint` across
web/mobile/shared) so error-level rules actually gate PRs, plus a .turbo cache step.

#415 — enable typescript-eslint recommendedTypeChecked + sonarjs across web, shared,
and mobile (projectService/tsconfigRootDir; disableTypeChecked for loose JS). Fix
~471 violations behavior-preservingly: floating/misused promises (await/void + the
house `() => void fn()` handler idiom), no-unsafe-* boundary typing, redundant type
assertions, require-await, and 3 cognitive-complexity extractions. Graduate the two
rules that are unsafe to batch-fix to `warn` with tracked follow-ups:
no-unnecessary-condition (#424) and cognitive-complexity (#425).

Closes #414
Closes #415

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

vercel Bot commented Jul 8, 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 Jul 8, 2026 7:17pm

Request Review

@sonarqubecloud

sonarqubecloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
70.8% Coverage on New Code (required ≥ 80%)
5.1% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@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.

/pr-review — PR #426

Scope: Bundles #414 (ESLint as a required CI job) + #415 (type-aware ESLint rules + cognitive-complexity cap), with ~190 files of behavior-preserving lint fixes across apps/web, apps/mobile, packages/shared.

Dimensions checked

Dimension Result
Correctness (behavior-preservation of the fixes) ✅ Spot-checked all non-trivial hunks (see below) — no behavior drift found
Cross-platform parity PAIRED — parity-checker subagent confirmed mirrored web/mobile files received equivalent fixes; eslint.config changes landed in all three workspaces (web/mobile/shared)
Design (DESIGN.md token/AI-slop/scene-sentence) PASS — design-reviewer subagent confirmed the 4 flagged extraction sites use only semantic tokens, no new hex literals/radii, no logic drift
Security ✅ N/A — no auth, input-validation, or trust-boundary code touched; changes are typing/promise-handling only
Contract-aligner / backward-compat guard ⚠️ Not verifiable in CI (orbit-api sibling repo not checked out) — moot anyway: diff touches no files under packages/shared/src/types/* or packages/shared/src/api/endpoints.ts, so no contract surface changed
i18n sync ✅ N/A — no user-facing strings added/changed
CI/config changes (test.yml, eslint.config.*, package.json) ✅ New Lint job mirrors the existing type-check job's checkout/setup/cache pattern; no-unsafe-*/unbound-method are disabled only in test-file overrides (__tests__/**, *.test.*, *.spec.*), not in production code — reasonable scoping, not a gate violation

Manual verification performed

Reviewed the diff directly (git diff origin/main...HEAD, 192 files / 852+/505−) and hand-checked the largest/riskiest hunks for behavior drift:

  • apps/mobile/app/streak-sections.tsxresolveNumeralColor/buildRunBandStyle extractions preserve identical branching and token usage.
  • apps/mobile/components/habits/habit-row-trailing.tsx — extracted runParentProgressAction/resolveParentRingColor/resolveParentRingTrackColor preserve the exact same precedence and color logic.
  • apps/mobile/components/onboarding/onboarding-actions-context.tsxasync→sync + explicit Promise.resolve() conversions (require-await fix) are behavior-equivalent.
  • apps/web/.../friend-row.tsx + mobile mirror — void (async () => {...})() IIFE wraps preserve the original await/setState sequencing.
  • apps/mobile/components/goals/goal-detail-drawer.tsx — confirmed refetchDetail: () => void refetchDetail() matches useGoalStatusActions's actual () => void parameter type (not fire-and-forgetting a value the callee awaits).
  • packages/shared/src/{stores/ui-store,utils/error-utils,utils/drill-navigation}.ts — redundant as X casts removed after narrowing already guarantees the type; packages/shared/src/validation/habit-form.ts's validateTimes extraction preserves the original short-circuit order.

No Critical or High findings. No Medium findings that are concretely actionable beyond what's already tracked (the two rules graduated to warn#424, #425 — are called out and tracked by the PR author already, not new debt this review needs to add).

Note (informational, not gating)

SonarCloud's automated PR comment shows the Quality Gate failing on New Code Coverage (70.8% < 80%) and Duplication (5.1% > 3%) — expected for a mechanical fix-up PR with no test additions and repeated void-wrap/extraction patterns across many files. This is a separate required check per this review's CI adaptations, not part of this rubric's pass/fail — flagging for visibility only.

Recommendation: APPROVE

Clean, well-scoped, behavior-preserving lint-hardening PR. Both automated dimension checks (parity, design) passed, and manual spot-checks of every non-trivial hunk found no drift.

@thomasluizon
thomasluizon merged commit 7688e46 into main Jul 8, 2026
15 of 16 checks passed
@thomasluizon
thomasluizon deleted the issue-414 branch July 8, 2026 20:18
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