Skip to content

Add ESLint baseline: no-floating-promises enforced, recommended rules as warnings#201

Merged
willwashburn merged 2 commits into
mainfrom
audit/eslint-baseline
Jun 10, 2026
Merged

Add ESLint baseline: no-floating-promises enforced, recommended rules as warnings#201
willwashburn merged 2 commits into
mainfrom
audit/eslint-baseline

Conversation

@willwashburn

Copy link
Copy Markdown
Member

What this does

Adds ESLint 9 flat config (eslint.config.mjs) with typescript-eslint. This is the first linter in the repo — designed as a low-noise, genuinely useful baseline that passes in CI without becoming a style crusade.

Config philosophy

  • Scope: src/**/*.{ts,tsx} and scripts/**/*.mjs; ignores out/, build/, dist/, node_modules/
  • @typescript-eslint/no-floating-promises → ERROR (type-aware): un-awaited promises are a real bug category. 18 violations fixed (see below).
  • All other recommended rules → WARN: they surface real issues as informational without blocking CI.
  • No formatting/style rules: prefer-const, naming-convention, consistent-type-imports etc. are all off or warn-only. No Prettier in this PR.
  • Test files (.test.ts, __tests__/**, .dom.test.ts) are excluded from type-aware analysis — they're excluded from all tsconfigs so projectService can't resolve them.

Violation counts

Total: 54 warnings, 0 errors (after fixes)

Warning breakdown by rule:

  • @typescript-eslint/no-unused-vars: 35 warnings (underscore-prefixed params, dead exports)
  • prefer-const: 4 warnings
  • @typescript-eslint/prefer-as-const: 1 warning
  • no-console (unused disable directives): 4 warnings
  • Other: 10 warnings

54 warnings is intentionally non-zero — they're real signals for future cleanup, just not blocking.

no-floating-promises fixes (18 violations across 7 files)

All fixes follow the convention from PR #195 (error-visibility): either void expr with a justifying comment, or a proper .catch() handler.

File Lines Fix
src/main/index.ts 141 void shell.openExternal(url) — OS-level fire-and-forget
src/main/index.ts 155, 157 void mainWindow.loadURL/File() — load errors surface in devtools
src/main/index.ts 308 Added .catch((err) => console.error('[main] app initialization failed:', err))
src/renderer/src/App.tsx 56 void load() inside useEffect
src/renderer/src/components/diff/DiffViewer.tsx 460 void Promise.all(...).then(...) inside useEffect with ignore-flag pattern
src/renderer/src/components/sidebar/ProjectSidebar.tsx 189 void pear.auth.status().then(setAuth)
src/renderer/src/components/terminal/TerminalPane.tsx 328 void pear.broker.releaseAgent(...) inside onClick
src/renderer/src/hooks/use-broker-events.ts 112 void pear.broker.releaseAgent(...) inside menu event handler
src/renderer/src/stores/git-store.ts 364, 377–395 void get().fetchStatus/Summary/Diff/ProjectStatus(...) — zustand store polling, results update state directly

CI change

One line added to .github/workflows/ci.yml immediately after verify:mcp-resources-drift:

- run: npm run lint

New dependencies (devDependencies only)

  • eslint@^9.39.4
  • typescript-eslint@^8.61.0 (meta-package: plugin + parser)

Follow-ups (not in this PR)

  • Fix the 54 warnings (especially the 35 unused-var warnings — many are already underscore-prefixed placeholders that could be removed)
  • Flip no-floating-promises catch-all void usages to proper error handlers where warranted
  • Enable @typescript-eslint/no-unused-vars as ERROR once the warnings are cleaned up
  • Add lint to the packaged-mcp-smoke job if desired

…es as warnings

Installs ESLint 9 + typescript-eslint. Uses a flat config (eslint.config.mjs)
scoped to src/**/*.{ts,tsx} and scripts/**/*.mjs with build artifacts ignored.

no-floating-promises is ERROR (type-aware); 18 violations fixed across 7 files
using void + comment or .catch() per the PR #195 error-visibility conventions.
All other recommended rules are WARN so they inform without blocking CI.

Adds "lint" npm script and a CI gate immediately after verify:mcp-resources-drift.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@willwashburn, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 27 minutes and 5 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1b1ca013-23ff-408b-989e-e6204f9ac66d

📥 Commits

Reviewing files that changed from the base of the PR and between 831a56b and c9d9cea.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • .github/workflows/ci.yml
  • eslint.config.mjs
  • package.json
  • src/main/index.ts
  • src/renderer/src/App.tsx
  • src/renderer/src/components/diff/DiffViewer.tsx
  • src/renderer/src/components/sidebar/ProjectSidebar.tsx
  • src/renderer/src/components/terminal/TerminalPane.tsx
  • src/renderer/src/hooks/use-broker-events.ts
  • src/renderer/src/stores/git-store.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch audit/eslint-baseline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request integrates ESLint and TypeScript-ESLint into the project, adding a linting script and a configuration file that enforces type-aware rules, specifically targeting un-awaited promises. Consequently, numerous floating promises across the codebase have been prefixed with void to satisfy the new rules. Feedback on these changes highlights a critical issue in eslint.config.mjs where the extends property is incorrectly used inside a configuration object, which is unsupported in ESLint 9 flat config and will cause a runtime error. Additionally, for the promise chain in ProjectSidebar.tsx, it is recommended to append a .catch() block to properly handle potential rejections rather than solely silencing the linter with void.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread eslint.config.mjs
Comment on lines +15 to +21
// Apply to all TS/TSX source and mjs scripts — no type-aware rules here
{
files: ['src/**/*.{ts,tsx}', 'scripts/**/*.mjs'],
extends: [
...tseslint.configs.recommended,
],
rules: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

In ESLint 9 flat config, the extends property is not supported inside a configuration object. Using it will cause ESLint to throw a TypeError and fail to run.

To fix this, you should spread tseslint.configs.recommended directly into the tseslint.config() call, and then define your custom rules in a separate configuration object.

  ...tseslint.configs.recommended,
  // Apply to all TS/TSX source and mjs scripts — no type-aware rules here
  {
    files: ['src/**/*.{ts,tsx}', 'scripts/**/*.mjs'],
    rules: {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

False positive: extends is not supported in raw flat-config objects, but this file wraps everything in tseslint.config(), whose documented signature feature is exactly per-object extends (https://typescript-eslint.io/packages/typescript-eslint#config). Verified empirically: npx eslint . runs on this branch — 0 errors, 54 warnings, no TypeError.


useEffect(() => {
pear.auth.status().then(setAuth)
void pear.auth.status().then(setAuth)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using void on a promise chain without a .catch() block silences the linter but leaves potential promise rejections unhandled. If pear.auth.status() fails, it will result in an unhandled promise rejection at runtime.

Since the comment indicates this is a best-effort probe where failures can be safely ignored, explicitly catch the error to prevent unhandled rejections.

Suggested change
void pear.auth.status().then(setAuth)
void pear.auth.status().then(setAuth).catch(() => {})

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Applied in c9d9cea — explicit .catch(() => {}) on the best-effort probe.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0bffaaf5ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/index.ts
Comment on lines +344 to +345
}).catch((err) => {
console.error('[main] app initialization failed:', err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't swallow startup initialization failures

If any startup step inside the app.whenReady().then(...) callback throws before the window is created or IPC is registered, this new catch only logs the error and lets the Electron process keep running in a partially initialized/no-window state. Previously the unhandled rejection would fail fast under the Node/Electron default; please rethrow/quit after logging, or handle recovery explicitly, so startup failures don't leave a hung app.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed — fixed in c9d9cea: the init catch now logs, sets process.exitCode = 1, and calls app.quit() so a partially-initialized app fails fast instead of lingering windowless (preserving the pre-lint exit-non-zero behavior).

- ProjectSidebar auth.status() best-effort probe now catches rejections
  explicitly instead of leaving an unhandled rejection path.
- app initialization catch now sets exitCode and quits instead of
  leaving a partially-initialized, windowless app running.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@willwashburn willwashburn merged commit 0521b80 into main Jun 10, 2026
5 checks passed
@willwashburn willwashburn deleted the audit/eslint-baseline branch June 10, 2026 13:44
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