Skip to content

chore(frontend): ESLint 9 upgrade + debug cleanup#325

Open
namastex888 wants to merge 3 commits intodevfrom
fix/publish-version-check
Open

chore(frontend): ESLint 9 upgrade + debug cleanup#325
namastex888 wants to merge 3 commits intodevfrom
fix/publish-version-check

Conversation

@namastex888
Copy link
Contributor

Summary

  • Upgrade ESLint 8→9 with flat config migration, eliminating 14 deprecated subdependencies
  • Remove debug console.logs and add performance optimizations (memo, stable deps)
  • Fix useConversationHistory to properly clear loading state when process completes

Changes

ESLint 9 Migration

  • New flat config: eslint.config.js replaces .eslintrc.cjs
  • Dependency upgrades: eslint 8.57→9.39, @typescript-eslint/* 7.18→8.50
  • react-spring→@react-spring/web: Eliminates 9 deprecated deps from react-native chain
  • Lint fixes: 4 issues caught by stricter v9 rules (unreachable code, expression statements)

Deprecation Warnings Eliminated

Before: 16 deprecated subdependencies on pnpm install
After: 2 (unfixable - from click-to-react-component and forge-inspector)

Performance & Cleanup

  • TaskCard: Wrapped in memo() to prevent re-renders during kanban drag
  • TaskKanbanBoard, TaskFollowUpSection: Removed debug console.log statements
  • useTaskCompletionNotification: Simplified from Map to Set, clearer completion logic
  • useConversationHistory: Fix loading indicator not clearing when process completes
  • TaskFollowUpSection: Extract primitive hasMergedPR for stable useMemo dependencies

Test Plan

  • pnpm install shows only 2 deprecated warnings
  • pnpm run lint passes (0 errors, 7 warnings within limit)
  • pnpm run build compiles successfully
  • Manual: Verify kanban drag/drop still works
  • Manual: Verify task completion notification sounds

ESLint 9 flat config migration:
- Migrate from .eslintrc.cjs to eslint.config.js flat config format
- Upgrade eslint 8.57→9.39, @typescript-eslint/* 7.18→8.50
- Replace react-spring with @react-spring/web (eliminates 9 deprecated deps)
- Fix 4 lint errors caught by stricter v9 rules

Dependency improvements:
- Eliminates 14 deprecated subdependencies from pnpm install warnings
- Only 2 remain (from click-to-react-component and forge-inspector)

Performance and cleanup:
- Wrap TaskCard in memo() to prevent unnecessary re-renders
- Remove debug console.logs from TaskKanbanBoard, TaskFollowUpSection
- Simplify useTaskCompletionNotification (Set vs Map, clearer logic)
- Fix useConversationHistory to emit entries when process completes
- Extract primitive from branchStatus for stable useMemo deps
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @namastex888, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the frontend development experience and application performance by upgrading the ESLint configuration to version 9, which includes a migration to flat config and a substantial cleanup of deprecated dependencies. Alongside these foundational improvements, several performance optimizations have been introduced, such as memoization for key components and more stable useMemo dependencies. Debugging artifacts have been removed, and a critical bug affecting the conversation history loading state has been resolved, ensuring a smoother user experience.

Highlights

  • ESLint 9 Upgrade: Migrated the frontend to ESLint 9 with a flat configuration, updating related dependencies and resolving stricter linting rules, which caught 4 new issues.
  • Dependency Cleanup: Replaced react-spring with @react-spring/web and eliminated 14 deprecated subdependencies, reducing pnpm install warnings from 16 to 2.
  • Performance Optimizations: Implemented memo for TaskCard to prevent unnecessary re-renders during kanban drag operations and extracted primitive values for stable useMemo dependencies in TaskFollowUpSection.
  • Debug Cleanup: Removed several console.log statements from TaskKanbanBoard and TaskFollowUpSection components.
  • Loading State Fix: Corrected an issue in useConversationHistory where the loading indicator would not clear properly upon process completion.
  • Notification Logic Refinement: Simplified the useTaskCompletionNotification hook by switching from a Map to a Set for tracking notified processes, improving clarity and preventing duplicate notifications.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 is a great cleanup and upgrade effort. The migration to ESLint 9 and the flat config is well-executed, and the dependency cleanup is a significant improvement. The performance optimizations, such as wrapping TaskCard in memo and ensuring stable dependencies for hooks, are excellent additions. I've found a couple of areas for improvement. One is a minor suggestion to restore a documentation link in the new ESLint config for better developer guidance. The other is a more significant point regarding a potential regression in the useTaskCompletionNotification hook, where the refactoring seems to have changed the core logic for detecting task completions. Overall, this is a very solid contribution to the project's health and maintainability.

Comment on lines 12 to 42
export function useTaskCompletionNotification(
executionProcesses: ExecutionProcess[]
) {
const { config } = useUserSystem();
const previousProcessesRef = useRef<Map<string, string>>(new Map());
// Track which process IDs have already played notification sound
// This prevents duplicates from re-renders, React Strict Mode, or array re-creation
const notifiedProcessIdsRef = useRef<Set<string>>(new Set());

useEffect(() => {
if (!config?.notifications.sound_enabled) {
return;
}

const currentProcesses = new Map<string, string>();

// Build current state and detect completions
executionProcesses.forEach((process) => {
const prevStatus = previousProcessesRef.current.get(process.id);
const currentStatus = process.status;

currentProcesses.set(process.id, currentStatus);

// Check if process just completed (status changed from running to completed/failed/killed)
const wasRunning = prevStatus === 'running';
const isCompleted =
currentStatus === 'completed' ||
currentStatus === 'failed' ||
currentStatus === 'killed';

if (wasRunning && isCompleted && process.run_reason === 'codingagent') {
// Task execution completed, play notification sound
// Use full volume - users can adjust system/browser volume
process.status === 'completed' ||
process.status === 'failed' ||
process.status === 'killed';

// Only notify once per process ID when it reaches a completed state
if (
isCompleted &&
process.run_reason === 'codingagent' &&
!notifiedProcessIdsRef.current.has(process.id)
) {
notifiedProcessIdsRef.current.add(process.id);
playNotificationSound(config.notifications.sound_file, 1.0);
}
});

// Update ref for next comparison
previousProcessesRef.current = currentProcesses;
}, [executionProcesses, config]);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The refactoring of this hook from using a Map to a Set has introduced a behavioral change that could be a regression. The previous logic correctly triggered a notification only when a process transitions from a running state to a completed state. The new logic triggers a notification if a process is in a completed state and hasn't been notified before within the component's lifecycle.

This can lead to unwanted notifications. For example, if the user loads a page where a task is already complete, a notification sound will play, which is likely not the intended behavior. The notification should ideally only occur for completions that happen while the user is actively viewing the page.

I recommend reverting to the previous implementation which correctly checked for the state transition, as it was more accurate in capturing the "completion" event.

export function useTaskCompletionNotification(
  executionProcesses: ExecutionProcess[]
) {
  const { config } = useUserSystem();
  const previousProcessesRef = useRef<Map<string, string>>(new Map());

  useEffect(() => {
    if (!config?.notifications.sound_enabled) {
      return;
    }

    const currentProcesses = new Map<string, string>();

    // Build current state and detect completions
    executionProcesses.forEach((process) => {
      const prevStatus = previousProcessesRef.current.get(process.id);
      const currentStatus = process.status;

      currentProcesses.set(process.id, currentStatus);

      // Check if process just completed (status changed from running to completed/failed/killed)
      const wasRunning = prevStatus === 'running';
      const isCompleted =
        currentStatus === 'completed' ||
        currentStatus === 'failed' ||
        currentStatus === 'killed';

      if (wasRunning && isCompleted && process.run_reason === 'codingagent') {
        // Task execution completed, play notification sound
        // Use full volume - users can adjust system/browser volume
        playNotificationSound(config.notifications.sound_file, 1.0);
      }
    });

    // Update ref for next comparison
    previousProcessesRef.current = currentProcesses;
  }, [executionProcesses, config]);
}

Comment on lines +65 to +68
'no-restricted-syntax': ['warn', {
selector: 'Property[key.name="refetchInterval"][value.type="Literal"][value.value<15000]',
message: 'Polling intervals under 15s are discouraged. Use WebSocket streams or event-driven invalidation instead.',
}],
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The warning message for the no-restricted-syntax rule regarding refetchInterval has been shortened. The previous version included a reference to docs/DATA_FETCHING.md, which is valuable for developers to understand the context and reasoning behind this rule. It would be beneficial to add this reference back to the message.

Suggested change
'no-restricted-syntax': ['warn', {
selector: 'Property[key.name="refetchInterval"][value.type="Literal"][value.value<15000]',
message: 'Polling intervals under 15s are discouraged. Use WebSocket streams or event-driven invalidation instead.',
}],
'no-restricted-syntax': ['warn', {
selector: 'Property[key.name="refetchInterval"][value.type="Literal"][value.value<15000]',
message: 'Polling intervals under 15s are discouraged. Use WebSocket streams or event-driven invalidation instead. See docs/DATA_FETCHING.md',
}],

chatgpt-codex-connector[bot]

This comment was marked as resolved.

The P0 performance optimization (42s -> <1s HTTP response) introduced
silent failures: start_attempt() runs in tokio::spawn() with errors
only logged, returning is_attempt_running=true before knowing if the
attempt actually started.

This fix:
- Add `Initializing` status to ExecutionProcessStatus enum
- Create ExecutionProcess with Initializing status BEFORE spawning
- Transition to Running on success, Failed on error
- SSE automatically pushes status changes to clients

Also fixes logging:
- main.rs: Log success/failure of PATH cache warming (not just "warmed")
- shell.rs: Restore debug/warn logging for shell failures/timeouts

forge-core files changed:
- crates/db/src/models/execution_process.rs: New status + helper methods
- crates/server/src/routes/tasks.rs: Create EP early
- crates/server/src/routes/task_attempts.rs: Same pattern
- crates/services/src/services/container.rs: New start_attempt_with_process()
- crates/server/src/main.rs: Better PATH warming logs
- crates/utils/src/shell.rs: Restore shell error logging
@namastex888 namastex888 force-pushed the fix/publish-version-check branch from b70b530 to e490d2b Compare December 19, 2025 00:31
Adds migration to include 'initializing' in the execution_processes
status CHECK constraint. Required for the early ExecutionProcess
creation pattern that surfaces startup failures to clients.

Council review: git_ops_safety test failures are environmental
(pre-commit hook context), not code quality issues.
chatgpt-codex-connector[bot]

This comment was marked as resolved.

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