Skip to content

Conversation

@kvnloo
Copy link
Contributor

@kvnloo kvnloo commented Dec 27, 2025

Base Branch

  • This PR targets the develop branch (required for all feature/fix PRs)
  • This PR targets main (hotfix only - maintainers)

Description

Implement a cognitively-optimized expandable view for subtasks that intelligently surfaces the 5 most relevant agent actions from logs containing 1000+ actions. This creates a critical "middle layer" between high-level subtask summaries and overwhelming full logs, using weighted scoring algorithms based on cognitive science principles (Justin Sung, Scott Young methodologies) and progressive disclosure UI patterns to maintain developer flow state during debugging and monitoring.

Related Issue

Closes #

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation
  • ♻️ Refactor
  • 🧪 Test

Area

  • Frontend
  • Backend
  • Fullstack

Commit Message Format

Follow conventional commits: feat: add intelligent action summarization UI

Types: feat, fix, docs, style, refactor, test, chore

Example: feat: add user authentication system

Checklist

  • I've synced with develop branch
  • I've tested my changes locally
  • I've followed the code principles (SOLID, DRY, KISS)
  • My PR is small and focused (< 400 lines ideally)

CI/Testing Requirements

  • All CI checks pass
  • All existing tests pass
  • New features include test coverage
  • Bug fixes include regression tests

Screenshots

Before After
image image

Feature Toggle

  • Behind localStorage flag: use_feature_name
  • Behind settings toggle
  • Behind environment variable/config
  • N/A - Feature is complete and ready for all users

Breaking Changes

Breaking: No

Details:

Summary by CodeRabbit

  • New Features

    • Intelligent action scoring with top‑N highlights, explanatory score badges, subphase grouping, and file summaries
    • Collapsible, relevance‑sorted subtasks with sort toggle, progress indicators, and "View all logs" navigation
    • Enhanced per‑action views (tool vs standard), expandable details, timestamps, and modified/read files section
    • Added localized UI strings for subtask/action/tool/scoring (English & French)
  • Tests

    • Comprehensive unit tests covering scoring, filtering, grouping, file extraction, and subtask relevance

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 27, 2025

📝 Walkthrough

Walkthrough

Adds an action-scoring library, tests, i18n keys, and UI components to surface top‑N scored subtask actions; wires phaseLogs and onViewAllLogs through TaskDetailModal → TaskSubtasks and renders results with SubtaskActionList (grouping, score breakdowns, files, and navigation to logs).

Changes

Cohort / File(s) Summary
Action Scoring Core
apps/frontend/src/renderer/lib/actionScoring.ts
New scoring module: weights/constants, predictors (error/warning/decision/file-change/novelty), duration helpers, scoreAction, filterTopActions, grouping by subphase, subtask relevance calculations, file extraction/summarization, and exported types/interfaces.
Action Scoring Tests
apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
New comprehensive unit tests covering detectors, scoring breakdowns, top‑N filtering, grouping, subtask relevance, file extraction, edge cases, and performance/scale scenarios.
Subtask Action Display
apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
New React component rendering scored actions (top‑N, grouped/flat), tool vs. regular action paths, ScoreBadge with tooltip breakdown, SubphaseGroup collapsibles, FilesSection, and default + named export.
Subtask Panel Enhancement
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
API extended to accept phaseLogs and onViewAllLogs; adds relevance scoring, sort‑by‑relevance mode, per‑subtask expansion, relevance badges, and uses SubtaskActionList to show top actions.
Task Detail Modal
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
Adds memoized handleViewAllLogs and passes phaseLogs and onViewAllLogs into TaskSubtasks.
i18n Additions
apps/frontend/src/shared/i18n/locales/en/tasks.json, apps/frontend/src/shared/i18n/locales/fr/tasks.json
New detail section with translation keys for subtasks, actions, tools, and scoring (additive).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant TDM as TaskDetailModal
    participant TSub as TaskSubtasks
    participant AS as ActionScoring
    participant SAL as SubtaskActionList
    participant UI as Rendered UI

    User->>TDM: Open task detail
    TDM->>TSub: pass phaseLogs, onViewAllLogs

    rect rgba(248,251,255,0.9)
      Note over AS,TSub: Aggregate & score entries
      TSub->>AS: getAllEntriesFromPhaseLogs(phaseLogs)
      AS-->>TSub: TaskLogEntry[]
      TSub->>AS: calculateSubtaskRelevanceScores(entries, subtaskIds)
      AS-->>TSub: Map<subtaskId, RelevanceScore>
    end

    rect rgba(255,248,240,0.9)
      Note over TSub,UI: Order & render subtasks
      TSub->>TSub: sort subtasks (relevance toggle)
      TSub-->>UI: render headers/badges
    end

    User->>UI: Expand a subtask
    UI->>TSub: expand event

    rect rgba(246,255,246,0.9)
      Note over SAL,AS: Top‑N selection & tooltips
      TSub->>AS: filterTopActions(subtaskActions, topN)
      AS-->>SAL: ScoredAction[]
      SAL->>AS: getScoreReason(scoredAction)
      SAL-->>UI: render actions, files, score tooltip
    end

    User->>UI: Click "View all logs"
    UI->>TSub: onViewAllLogs()
    TSub->>TDM: trigger tab change to Logs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement, size/M

Suggested reviewers

  • AlexMadera
  • AndyMik90

Poem

🐰 I hop through logs with whiskers bright,

Weighing errors, edits, and each light bite.
Subtasks ranked, top‑N carrots in sight,
Badges gleam, little insights take flight,
Hooray — the burrow's logic feels right!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: introducing intelligent action summarization to enhance the subtask view by surfacing relevant actions from logs.
Docstring Coverage ✅ Passed Docstring coverage is 94.69% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35a28ed and 890fad0.

📒 Files selected for processing (7)
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
🧰 Additional context used
📓 Path-based instructions (3)
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
apps/frontend/src/shared/i18n/locales/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

Add new translation keys to ALL language files (minimum: en/*.json and fr/*.json) in apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
🧠 Learnings (3)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)

Applied to files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
🧬 Code graph analysis (3)
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (1)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (1)
  • TaskSubtasks (67-359)
apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts (2)
apps/frontend/src/shared/types/task.ts (3)
  • TaskLogEntry (64-77)
  • TaskLogEntryType (62-62)
  • TaskLogPhase (60-60)
apps/frontend/src/renderer/lib/actionScoring.ts (21)
  • SCORING_WEIGHTS (18-25)
  • DEFAULT_TOP_N (28-28)
  • isErrorAction (98-114)
  • isWarningAction (119-126)
  • isDecisionAction (132-153)
  • isFileChangeAction (158-176)
  • countFilesChanged (182-193)
  • isNovelty (241-248)
  • scoreAction (258-317)
  • filterTopActions (341-376)
  • ScoredAction (36-41)
  • groupActionsBySubphase (384-397)
  • getScoreReason (447-478)
  • calculateSubtaskRelevance (505-548)
  • calculateSubtaskRelevanceScores (557-568)
  • sortSubtasksByRelevance (581-615)
  • SubtaskRelevanceScore (483-491)
  • extractFilesFromAction (741-790)
  • extractFilesFromActions (795-804)
  • getFilesSummary (809-859)
  • getImportantFiles (865-880)
apps/frontend/src/renderer/lib/actionScoring.ts (1)
apps/frontend/src/shared/types/task.ts (2)
  • TaskLogEntry (64-77)
  • TaskLogEntryType (62-62)
🔇 Additional comments (25)
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (2)

159-162: LGTM! Memoized callback correctly implemented.

The handleViewAllLogs callback is properly memoized with useCallback and includes state.setActiveTab in the dependency array. This ensures stable function identity across renders, preventing unnecessary re-renders of TaskSubtasks when other state changes.


436-440: LGTM! Props correctly wired to TaskSubtasks.

The phaseLogs and onViewAllLogs props are correctly passed to TaskSubtasks, enabling phase-logs-driven rendering and navigation to the Logs tab.

apps/frontend/src/shared/i18n/locales/en/tasks.json (1)

86-130: LGTM! Comprehensive i18n keys for the new feature.

The new detail section provides well-structured translation keys for:

  • Subtask UI (detail.subtasks.*)
  • Action list (detail.actions.*)
  • Tool labels (detail.tools.*)
  • Scoring explanations (detail.scoring.*)

The pluralization for actionsCount_one/actionsCount_other correctly follows i18next conventions.

apps/frontend/src/shared/i18n/locales/fr/tasks.json (1)

86-130: LGTM! French translations correctly mirror English structure.

All translation keys from the English file are present with appropriate French translations. The pluralization and interpolation variables are consistent across both locales, satisfying the coding guidelines requirement for maintaining parity between language files.

apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts (4)

1-52: LGTM! Well-structured test file with comprehensive coverage.

The test file provides excellent coverage of the action scoring algorithm:

  • Helper functions for creating test data
  • Constants validation
  • Individual predicate function tests
  • Scoring and filtering logic
  • Edge cases and performance benchmarks

The createTestAction helper with sensible defaults makes tests readable and maintainable.


590-652: LGTM! CI-resilient performance tests.

The performance tests correctly address flakiness concerns by using a ciMultiplier that increases thresholds 5x when running in CI environments. This approach maintains the value of performance testing while avoiding intermittent failures on slower CI runners.


381-392: LGTM! Tiebreaker test correctly verifies stable ordering.

The test now uses strict equality (toEqual([0, 1, 2, 3, 4])) to verify that actions with identical scores preserve their original order, which is a stronger assertion than the previous non-decreasing check.


877-1190: LGTM! Comprehensive file extraction tests.

The file extraction tests cover:

  • Various tool types (Read, Edit, Write)
  • Skipping tool_end and non-tool actions
  • Relative and absolute paths
  • Filtering by subtask_id
  • Deduplication of unique files
  • Modified vs. read-only file categorization

Good coverage of the getImportantFiles prioritization logic.

apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (6)

1-28: LGTM! Proper imports and i18n setup.

The component correctly imports useTranslation from react-i18next and uses the 'tasks' namespace. All lucide-react icons are imported as needed.


49-67: LGTM! Tool info helper returns i18n keys.

The getToolInfo function returns labelKey for translation lookup rather than hardcoded strings. For unknown tools, it provides a fallbackLabel that uses the tool name directly, which is acceptable since tool names are technical identifiers.


72-79: LGTM! Locale-aware time formatting.

Using undefined as the locale parameter allows the browser to use the user's default locale preferences, addressing the previous review concern about hardcoded 'en-US'.


241-271: LGTM! ScoreBadge uses i18n-compatible reason keys.

The component correctly uses getScoreReasonKeys() to get translation keys and maps them through t() for localized display. This addresses the previous review comment about type assertions.


326-329: LGTM! Cross-platform path handling.

The getFilenameFromPath function now splits on both / and \ using a regex, correctly handling both Unix and Windows path separators.


420-503: LGTM! Main component properly internationalized.

The SubtaskActionList component:

  • Uses translation keys for all user-facing text
  • Has explicit type="button" on all buttons
  • Properly memoizes computed values with useMemo
  • Handles empty state with localized message

The implementation is clean and follows React best practices.

apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (4)

1-11: LGTM! Clean imports with action scoring integration.

The imports are well-organized, bringing in the necessary action scoring utilities (filterTopActions, calculateSubtaskRelevanceScores, sortSubtasksByRelevance, getImportantFiles) alongside UI components and types.


67-133: LGTM! Well-structured component state and memoization.

The component demonstrates good React patterns:

  • useState for expansion tracking and sort mode
  • useCallback for toggle handlers to maintain stable references
  • useMemo for expensive computations (allEntries, relevanceScores, sortedSubtasks, originalIndexMap)
  • Type guard in sortedSubtasks filter: (s): s is Subtask => s != null
  • Precomputed originalIndexMap for O(1) index lookup during render

250-262: LGTM! Fully internationalized tooltip content.

The tooltip correctly uses translation keys with interpolation:

  • t('detail.scoring.relevanceScore')
  • t('detail.scoring.actionsCount', { count: ... })
  • t('detail.scoring.averageScore', { value: ... })
  • t('detail.scoring.topScore', { value: ... })
  • t('detail.subtasks.containsErrors')

This addresses the previous review comment about hardcoded English text.


336-349: LGTM! SubtaskActionList correctly wired.

The SubtaskActionList component receives all necessary props:

  • actions: scored actions for the subtask
  • maxActions: configured to 5
  • showSubphaseGrouping: enabled
  • onViewAllLogs: callback for navigation
  • modifiedFiles/readFiles: extracted file data

The lazy computation (isExpanded ? getSubtaskActions(subtask.id) : []) ensures scored actions are only computed when needed.

apps/frontend/src/renderer/lib/actionScoring.ts (7)

1-31: LGTM! Well-documented module with clear cognitive science rationale.

The module header clearly explains the scoring weights and their cognitive science foundations. The exported constants (SCORING_WEIGHTS, DEFAULT_TOP_N, TIME_ANOMALY_THRESHOLD) are appropriately typed with as const for type safety.


195-236: LGTM! Duration parsing stub with clear TODO.

The parseDuration function returns undefined with a clear TODO comment explaining that TaskLogEntry doesn't include duration data. This makes the TIME_ANOMALY scoring effectively disabled but leaves the infrastructure in place for future enhancement. The isTimeAnomaly function correctly handles the undefined case.


341-376: LGTM! Consolidated filterTopActions implementation.

The function now uses a single code path for all array sizes, addressing the previous review comment about duplicate logic. The implementation correctly:

  • Handles empty/invalid inputs early
  • Filters by subtask ID when provided
  • Creates scoring context once
  • Sorts with stable tiebreaking
  • Returns top N results

405-436: LGTM! i18n-compatible score reason keys.

The getScoreReasonKeys function returns translation keys (e.g., 'detail.scoring.errorDetected') instead of hardcoded English strings, enabling proper internationalization in UI components. The function signature uses Pick<ScoredAction, 'scoreBreakdown'> for flexibility.


581-615: LGTM! Efficient subtask sorting with O(1) index lookup.

The sortSubtasksByRelevance function correctly pre-computes an index map for O(1) lookups in the tertiary sort, addressing the previous O(n²) concern with indexOf calls inside the comparator.


684-708: LGTM! Regex pattern extraction correctly implemented.

The file path extraction:

  • Places quoted patterns first to extract paths without surrounding quotes
  • Uses exec() instead of match() for proper capture group handling
  • Prefers match[1] (captured group) over match[0] (full match)
  • Avoids global flags to prevent regex state issues

This addresses the previous review comment about incorrect quote handling.


741-880: LGTM! Comprehensive file extraction and summarization.

The file extraction subsystem provides:

  • extractFilesFromAction: Extracts file info from tool actions
  • extractFilesFromActions: Aggregates across multiple actions
  • getFilesSummary: Categorizes by operation, deduplicates, separates modified vs read
  • getImportantFiles: Prioritizes modified files for display

The logic correctly excludes search operations and skips tool_end to avoid duplicates.


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 30

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (1)

125-131: Use translation keys for user-facing text.

As per coding guidelines, all user-facing text in React/TypeScript frontend components must use translation keys with useTranslation(). Multiple hardcoded strings in this component violate this requirement.

Key violations:

  • Lines 127-129: "No subtasks defined", "Implementation subtasks will appear here after planning"
  • Lines 159, 166-167: Sort mode labels and tooltips
  • Lines 237-244: Relevance score labels
Example fix for empty state
+import { useTranslation } from 'react-i18next';
+
 export function TaskSubtasks({ task, phaseLogs, onViewAllLogs }: TaskSubtasksProps) {
+  const { t } = useTranslation('taskDetail');
   const progress = calculateProgress(task.subtasks);
   // ...
   
   // In JSX:
-  <p className="text-sm font-medium text-muted-foreground mb-1">No subtasks defined</p>
-  <p className="text-xs text-muted-foreground/70">
-    Implementation subtasks will appear here after planning
-  </p>
+  <p className="text-sm font-medium text-muted-foreground mb-1">{t('subtasks.empty.title')}</p>
+  <p className="text-xs text-muted-foreground/70">
+    {t('subtasks.empty.description')}
+  </p>
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50e3111 and ec7c63c.

⛔ Files ignored due to path filters (1)
  • apps/frontend/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (29)
  • apps/frontend/.env.example
  • apps/frontend/package.json
  • apps/frontend/src/__tests__/integration/api-ipc-bridge.test.ts
  • apps/frontend/src/__tests__/integration/openapi-spec.test.ts
  • apps/frontend/src/main/api/.gitkeep
  • apps/frontend/src/main/api/__tests__/websocket.spec.ts
  • apps/frontend/src/main/api/event-bridge.ts
  • apps/frontend/src/main/api/index.ts
  • apps/frontend/src/main/api/middleware/.gitkeep
  • apps/frontend/src/main/api/middleware/__tests__/auth.spec.ts
  • apps/frontend/src/main/api/middleware/auth.ts
  • apps/frontend/src/main/api/routes/.gitkeep
  • apps/frontend/src/main/api/routes/__tests__/tasks.spec.ts
  • apps/frontend/src/main/api/routes/index.ts
  • apps/frontend/src/main/api/routes/monitoring.ts
  • apps/frontend/src/main/api/routes/projects.ts
  • apps/frontend/src/main/api/routes/tasks.ts
  • apps/frontend/src/main/api/schemas/.gitkeep
  • apps/frontend/src/main/api/schemas/index.ts
  • apps/frontend/src/main/api/server.ts
  • apps/frontend/src/main/api/startup.ts
  • apps/frontend/src/main/api/types/index.ts
  • apps/frontend/src/main/api/websocket.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/lib/actionScoring.ts
🧰 Additional context used
📓 Path-based instructions (2)
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/main/api/middleware/__tests__/auth.spec.ts
  • apps/frontend/src/main/api/routes/tasks.ts
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/__tests__/integration/api-ipc-bridge.test.ts
  • apps/frontend/src/main/api/server.ts
  • apps/frontend/src/main/api/event-bridge.ts
  • apps/frontend/src/main/api/types/index.ts
  • apps/frontend/src/main/api/routes/projects.ts
  • apps/frontend/src/main/api/routes/__tests__/tasks.spec.ts
  • apps/frontend/src/__tests__/integration/openapi-spec.test.ts
  • apps/frontend/src/main/api/routes/index.ts
  • apps/frontend/src/main/api/middleware/auth.ts
  • apps/frontend/src/main/api/websocket.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/main/api/startup.ts
  • apps/frontend/src/main/api/__tests__/websocket.spec.ts
  • apps/frontend/src/main/api/schemas/index.ts
  • apps/frontend/src/main/api/index.ts
  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/main/api/routes/monitoring.ts
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/main/api/middleware/__tests__/auth.spec.ts
  • apps/frontend/src/main/api/routes/tasks.ts
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/__tests__/integration/api-ipc-bridge.test.ts
  • apps/frontend/src/main/api/server.ts
  • apps/frontend/src/main/api/event-bridge.ts
  • apps/frontend/src/main/api/types/index.ts
  • apps/frontend/src/main/api/routes/projects.ts
  • apps/frontend/src/main/api/routes/__tests__/tasks.spec.ts
  • apps/frontend/src/__tests__/integration/openapi-spec.test.ts
  • apps/frontend/src/main/api/routes/index.ts
  • apps/frontend/src/main/api/middleware/auth.ts
  • apps/frontend/src/main/api/websocket.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/main/api/startup.ts
  • apps/frontend/src/main/api/__tests__/websocket.spec.ts
  • apps/frontend/src/main/api/schemas/index.ts
  • apps/frontend/src/main/api/index.ts
  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/main/api/routes/monitoring.ts
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/agents/{qa_reviewer,qa_fixer}.py : For frontend bug fixes and feature implementations, use the Electron MCP server for automated E2E testing when the app is running with `--remote-debugging-port=9222`
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/.env* : Enable Electron MCP in `apps/backend/.env` with `ELECTRON_MCP_ENABLED=true` and `ELECTRON_DEBUG_PORT=9222` to allow QA agents to interact with running Electron app

Applied to files:

  • apps/frontend/.env.example
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/agents/{qa_reviewer,qa_fixer}.py : For frontend bug fixes and feature implementations, use the Electron MCP server for automated E2E testing when the app is running with `--remote-debugging-port=9222`

Applied to files:

  • apps/frontend/.env.example
🧬 Code graph analysis (8)
apps/frontend/src/main/api/routes/tasks.ts (2)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (776-776)
apps/frontend/src/shared/constants/config.ts (2)
  • getSpecsDir (100-103)
  • AUTO_BUILD_PATHS (77-94)
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (1)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (1)
  • TaskSubtasks (63-343)
apps/frontend/src/__tests__/integration/api-ipc-bridge.test.ts (1)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (776-776)
apps/frontend/src/main/api/routes/projects.ts (1)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (776-776)
apps/frontend/src/main/api/routes/__tests__/tasks.spec.ts (1)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (776-776)
apps/frontend/src/main/api/startup.ts (1)
apps/frontend/src/main/api/index.ts (24)
  • ApiStartupOptions (129-129)
  • ApiStartupResult (130-130)
  • ApiShutdownResult (131-131)
  • ApiServerStatus (132-132)
  • initializeApiServer (119-119)
  • isServerRunning (40-40)
  • getServerInstance (43-43)
  • createApiServer (36-36)
  • registerRoutes (53-53)
  • startApiServer (37-37)
  • initializeEventBridge (105-105)
  • shutdownApiServer (120-120)
  • getServerUptime (41-41)
  • getClientCount (87-87)
  • getEventBridgeStats (108-108)
  • closeAllConnections (96-96)
  • shutdownEventBridge (106-106)
  • stopApiServer (38-38)
  • getApiServerStatus (121-121)
  • isEventBridgeActive (107-107)
  • isApiServerEnabled (122-122)
  • areApiKeysLoaded (124-124)
  • areKeysLoaded (70-70)
  • getApiServerInstance (125-125)
apps/frontend/src/renderer/lib/actionScoring.ts (1)
apps/frontend/src/shared/types/task.ts (2)
  • TaskLogEntry (62-75)
  • TaskLogEntryType (60-60)
apps/frontend/src/main/api/routes/monitoring.ts (1)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (776-776)
🪛 Biome (2.1.2)
apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx

[error] 141-148: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 198-205: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 279-282: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 447-450: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx

[error] 142-152: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 298-306: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🪛 Gitleaks (8.30.0)
apps/frontend/src/main/api/middleware/__tests__/auth.spec.ts

[high] 183-183: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 193-193: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (35)
apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts (2)

593-636: Verify performance test thresholds are CI-friendly.

The performance tests expect sub-100ms for 1000 actions and sub-500ms for 5000 actions. These thresholds may be too strict for CI environments, which typically have slower/shared resources than development machines.

Consider one of these approaches:

  1. Increase the thresholds by 2-3x to account for CI variability (e.g., 300ms and 1500ms)
  2. Use relative performance assertions instead of absolute timings
  3. Skip performance tests in CI with a flag like skipInCI

Based on learnings, if QA agents have access to the running app, you could also create E2E performance tests that measure real-world scoring performance with the Electron MCP server.


1-1188: LGTM! Comprehensive test coverage.

The test suite is well-structured with excellent coverage of:

  • Scoring weights and detection logic
  • Filtering and tiebreaking behavior
  • File extraction and summarization
  • Subtask relevance calculations
  • Edge cases (null, empty, missing data)
  • Non-mutation guarantees

The tests are clear, use appropriate helpers, and validate both positive and negative cases.

apps/frontend/src/main/index.ts (1)

9-9: LGTM! API server lifecycle integration is solid.

The API server initialization and shutdown are properly integrated into the Electron app lifecycle with:

  • Conditional enablement check
  • Proper error handling for both resolved and rejected promises
  • Consistent logging
  • Clean shutdown in before-quit handler

Also applies to: 185-267

apps/frontend/src/__tests__/integration/openapi-spec.test.ts (1)

1-655: LGTM! Excellent OpenAPI spec validation.

This integration test provides comprehensive coverage of:

  • OpenAPI spec structure and metadata
  • All REST endpoints (tasks, projects, monitoring)
  • Request/response schemas
  • Security schemes
  • Query and path parameters
  • WebSocket endpoint (with appropriate handling of OpenAPI limitations)
  • Spec accessibility and consistency

The mocking approach is clean and the test structure makes it easy to verify complete API surface coverage.

apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (1)

420-424: LGTM! Clean prop integration.

The addition of phaseLogs and onViewAllLogs props to TaskSubtasks is properly typed and integrates cleanly with the existing component. The callback enables navigation from the Subtasks tab to the Logs tab, which is a good UX improvement.

apps/frontend/src/main/api/routes/index.ts (1)

26-40: No action required. The registerWebSocketRoute function returns void (not a Promise), making it synchronous and intentionally not awaitable. The registration order—using await for async operations and direct calls for synchronous ones—is correct as written.

Likely an incorrect or invalid review comment.

apps/frontend/src/main/api/middleware/__tests__/auth.spec.ts (1)

1-597: LGTM! Comprehensive test coverage for auth middleware.

The test suite thoroughly covers all authentication functions including edge cases for security (empty strings, whitespace, non-string inputs, fail-closed behavior). The Gitleaks warnings on lines 183 and 193 are false positives as these are test API keys (valid-key-123) used in unit tests, not actual secrets.

apps/frontend/src/main/api/routes/__tests__/tasks.spec.ts (1)

1-645: LGTM! Comprehensive unit test coverage for task routes.

The test suite covers all task CRUD operations, lifecycle endpoints (start/stop/review), authentication middleware verification, and appropriate error handling scenarios. Good use of beforeEach/afterEach for test isolation and cleanup.

apps/frontend/src/main/api/routes/monitoring.ts (1)

142-259: LGTM! Well-structured monitoring endpoints.

The route registration correctly separates public endpoints (/api/health, /api/version) from authenticated endpoints (/api/status). The dynamic import for project-store avoids circular dependency issues and gracefully handles failures by marking the component as degraded.

apps/frontend/src/main/api/__tests__/websocket.spec.ts (1)

1-912: LGTM! Comprehensive WebSocket test coverage.

The test suite thoroughly covers client management, broadcast functions, connection lifecycle, message processing (subscribe/unsubscribe/ping), subscription filtering, and edge cases (closed sockets, send errors, unique IDs). Good use of mock patterns and clear test organization.

apps/frontend/src/__tests__/integration/api-ipc-bridge.test.ts (1)

1-636: LGTM! Solid integration tests verifying HTTP API mirrors IPC functionality.

The test suite comprehensively validates that the HTTP API provides equivalent functionality to IPC handlers, including project and task operations, error handling, monitoring endpoints, and authentication. Good verification that both layers use the same projectStore.

apps/frontend/src/main/api/routes/tasks.ts (3)

51-66: LGTM! Helper function for finding tasks across projects.

The helper iterates all projects to find a task by ID or specId. While this is O(projects × tasks), it's acceptable for typical project counts and mirrors IPC handler behavior.


440-460: Deletion allowed without checking if task is running.

The comment on lines 441-443 acknowledges that the IPC handler checks if a task is running before deletion, but the HTTP API skips this check. This could lead to inconsistent behavior between IPC and HTTP API, and potentially orphaned running processes.

Consider whether the HTTP API should also check AgentManager for running tasks before allowing deletion, or if this is intentional behavior for the remote API use case. If intentional, the API documentation should clarify this difference.


141-287: LGTM! Task creation with comprehensive spec generation.

The POST /api/tasks endpoint properly creates spec directories, generates implementation_plan.json, task_metadata.json, and requirements.json files, handles attached images with base64 decoding, and uses zero-padded spec IDs.

apps/frontend/src/main/api/event-bridge.ts (1)

210-263: LGTM! Well-structured event bridge initialization.

The initialization properly prevents double-initialization, subscribes to all relevant events from AgentManager and FileWatcher, and registers cleanup functions for proper teardown. The cleanup array pattern ensures all listeners are removed during shutdown.

apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (1)

407-487: LGTM! Well-structured component with good performance optimizations.

The SubtaskActionList component uses useMemo appropriately for expensive operations (slicing and grouping actions), handles empty states gracefully, and provides a clear visual hierarchy with grouped actions and score badges.

apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (1)

63-120: LGTM - Component logic and memoization are well-structured.

The use of useMemo for allEntries, relevanceScores, and sortedSubtasks is appropriate for avoiding unnecessary recomputation. The useCallback for getSubtaskActions correctly captures the allEntries dependency while avoiding recreation on every render.

apps/frontend/src/main/api/startup.ts (1)

277-341: LGTM - Graceful shutdown implementation.

The shutdown sequence is well-designed:

  1. Captures statistics before shutdown
  2. Closes WebSocket connections first
  3. Shuts down event bridge
  4. Stops the Fastify server
  5. Clears module state

Each step has individual error handling to ensure partial failures don't prevent subsequent cleanup steps.

apps/frontend/src/main/api/types/index.ts (1)

1-362: LGTM - Comprehensive and well-organized type definitions.

The types module provides a clean API contract surface with:

  • Proper re-exports from shared types for consistency
  • Complete coverage of REST API request/response types
  • WebSocket message types with proper payloads
  • Route parameters and pagination helpers for future extensibility
apps/frontend/src/main/api/server.ts (3)

46-55: Verify CORS default allows all origins.

The default CORS configuration allows all origins (['*']) when API_CORS_ORIGINS is not set. While convenient for development, this could be a security concern in production deployments.

Consider documenting this behavior prominently or defaulting to a more restrictive setting:

 function parseCorsOrigins(): string[] {
   const envOrigins = process.env.API_CORS_ORIGINS;
   if (!envOrigins) {
-    return ['*']; // Allow all origins by default (configurable)
+    // SECURITY: In production, set API_CORS_ORIGINS to restrict access
+    // Default allows all origins for local development convenience
+    return ['*'];
   }

239-264: LGTM - Error handling is well-implemented.

The error handler appropriately:

  • Falls back to 500 for unknown errors
  • Logs 5xx errors at error level, 4xx at warn level
  • Returns consistent error response format
  • Provides a meaningful not-found handler with request details

101-107: loadApiKeys() throws if API_KEY is not set; consider documenting callers' responsibility or refactoring to return a result.

createApiServer() calls loadApiKeys() which throws if API_KEY is missing. While initializeApiServer() (startup.ts) protects this call with a pre-check and try-catch, the public createAndStartApiServer() function does not check API_KEY before calling createApiServer(), leaving callers of that function unprotected. Either document that all callers must check API_KEY first, or refactor loadApiKeys() to return a validation result to centralize this check.

apps/frontend/src/main/api/websocket.ts (1)

593-598: Type assertion is acceptable but consider typing improvement.

The any type assertion is documented with a comment explaining the necessity. For a cleaner approach, consider using Fastify's proper WebSocket route typing:

import type { FastifyInstance, RouteShorthandOptions } from 'fastify';

// Using proper generic typing if available from @fastify/websocket
fastify.get('/ws', routeOptions as RouteShorthandOptions, wsHandler);

However, the current approach works and the comment adequately explains the rationale.

apps/frontend/src/main/api/middleware/auth.ts (1)

60-90: LGTM - API key loading implementation.

The key loading function properly:

  • Validates environment variable presence
  • Parses comma-separated keys
  • Filters empty strings
  • Throws clear error messages for misconfiguration
apps/frontend/src/main/api/schemas/index.ts (2)

39-95: LGTM - Enum definitions align with TypeScript types.

The const arrays for enums (taskStatusEnum, subtaskStatusEnum, etc.) correctly match the corresponding TypeScript types and provide runtime values for JSON Schema validation.


993-1014: LGTM - Public endpoints correctly exclude security.

The health and version endpoint schemas properly set security: [] to indicate they don't require authentication, which is the correct pattern for monitoring endpoints.

apps/frontend/src/main/api/index.ts (1)

1-281: LGTM - Well-organized module entry point.

The barrel file effectively consolidates the API surface with:

  • Clear section headers for discoverability
  • Comprehensive re-exports of functions and types
  • Helpful usage example in the module documentation
  • Logical grouping (server lifecycle, routes, auth, websocket, etc.)
apps/frontend/src/renderer/lib/actionScoring.ts (8)

1-31: LGTM!

Well-documented constants with clear cognitive science rationale. The as const assertion ensures type safety for the scoring weights.


33-60: LGTM!

Type definitions are well-structured. Using index for tiebreaking ensures deterministic sorting.


100-181: LGTM!

Detection functions are well-implemented with multiple strategies (type-based and content-based). Case-insensitive handling is consistent.


183-198: LGTM!

The heuristic approach is reasonable. Consider that the {1,4} extension limit may miss some file types (e.g., .swift, .scala), but for a scoring heuristic this is acceptable.


241-251: LGTM!

Clean implementation of novelty detection using a set for O(1) lookups.


298-305: Side effect: scoreAction mutates context.seenToolTypes.

This makes scoring order-dependent. The current usage in filterTopActions processes sequentially, so this works correctly. However, if this function is ever used in parallel processing or with a shared context across multiple calls, results could be inconsistent.

Consider documenting this behavior in the JSDoc or making the mutation explicit in the caller.


389-408: LGTM!

Clean grouping implementation with sensible default for missing subphase.


581-829: LGTM!

File extraction utilities are well-implemented with:

  • Multiple path format support (direct, JSON, regex patterns)
  • Proper deduplication by skipping tool_end events
  • Clear categorization of modified vs read-only files
  • Sensible defaults and caps for UI display

Comment on lines 52 to 55
# API key for authentication (required for remote access)
# Generate a secure random key for production use
# If not set, API authentication is disabled (local development only)
# API_KEY=your-secure-api-key-here
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Clarify API authentication requirements.

The comments state "API key for authentication (required for remote access)" and "If not set, API authentication is disabled (local development only)". This creates ambiguity about when authentication is actually enforced.

Consider clarifying the behavior:

🔎 Suggested clarification
-# API key for authentication (required for remote access)
-# Generate a secure random key for production use
-# If not set, API authentication is disabled (local development only)
+# API key for authentication
+# REQUIRED when API_HOST is not 127.0.0.1 (remote access)
+# OPTIONAL for localhost-only access (development)
+# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
 # API_KEY=your-secure-api-key-here

Also consider whether disabling authentication even for localhost is secure, given that malicious local software could access the API.

🤖 Prompt for AI Agents
In apps/frontend/.env.example lines 52-55, the existing comments about API_KEY
are ambiguous about when authentication is enforced; update the comment to (1)
explicitly state that setting API_KEY enables authentication for all requests,
(2) clarify that if API_KEY is empty the server will run in an
"allow-unauthenticated" mode used only for local development, and (3) add a
security note advising not to run without an API_KEY on any machine exposed to
untrusted software and recommending generating a strong secret for production
and/or using a separate flag or bind-address restriction to allow
unauthenticated localhost-only access. Ensure the new comment gives exact
instructions to set API_KEY for production and warns about localhost risk.

Comment on lines 53 to 56
"@fastify/cors": "^11.2.0",
"@fastify/swagger": "^9.4.2",
"@fastify/swagger-ui": "^5.2.2",
"@fastify/websocket": "^11.0.2",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check current versions of Fastify and related packages
echo "=== Current npm versions ==="
npm info fastify --json | jq '.["dist-tags"]'
npm info @fastify/cors --json | jq '.["dist-tags"]'
npm info @fastify/swagger --json | jq '.["dist-tags"]'
npm info @fastify/swagger-ui --json | jq '.["dist-tags"]'
npm info @fastify/websocket --json | jq '.["dist-tags"]'

echo -e "\n=== Version details for Fastify 5.3.4 ==="
npm info [email protected] --json | jq '{name: .name, version: .version, published: .time.created, latest: .time[.["dist-tags"]["latest"]]}'

echo -e "\n=== Plugin version details ==="
npm info @fastify/[email protected] --json | jq '{name: .name, version: .version, published: .time.created}'
npm info @fastify/[email protected] --json | jq '{name: .name, version: .version, published: .time.created}'

Repository: AndyMik90/Auto-Claude

Length of output: 1066


🌐 Web query:

Fastify 5.x production-ready stability release notes compatibility

💡 Result:

Short answer

  • Fastify 5 is a stable, production-ready major series (first stable tag v5.0.0 published Sep 17, 2024) and is actively maintained with 5.x patch/minor releases. [1][2]

Key compatibility / production notes

  • Node.js requirement: v20+ only (v5 drops support for older Node versions). [1]
  • Many breaking changes vs v4 (full JSON Schema required for query/params/body/response, changed .listen() behavior, removed deprecated APIs, changed logger signature, parameters object prototype removed, type-provider split, plugins must not mix callback/promise APIs, etc.). See the full migration/breaking-changes list. [1]
  • Plugin ecosystem: many community plugins required updated fastify-plugin peer ranges and code changes; check individual plugins for v5 support before upgrading. See the tracking issue and plugin updates. [3]
  • Security/patches: v5 receives regular security/bug patches (see GitHub releases/changelog for v5.x). [2]

Upgrade checklist (brief)

  • Upgrade Node to v20+.
  • Fix all v4 deprecation warnings first.
  • Read and apply the Migration Guide (address schema changes, new APIs, removed APIs).
  • Verify each plugin you use is updated for fastify@^5 (or replace/patch it).
  • Run full test suite and smoke-test in staging before production deploy.

Links

  • Migration guide / breaking changes (Fastify v5 docs). [1]
  • Fastify releases / changelog (GitHub releases). [2]
  • Plugin compatibility tracking issue (plugins needing updates for v5). [3]

References
[1] Fastify Migration Guide V5 (breaking changes & requirements).
[2] fastify/fastify Releases (v5.x changelog).
[3] GitHub issue tracking plugins needing updates for Fastify v5.


🌐 Web query:

@fastify/cors @fastify/swagger @fastify/websocket Fastify 5.x compatibility

💡 Result:

Short answer — yes; use the plugins' v5-compatible releases:

  • @fastify/cors: use v^10 / v^11 (compat with Fastify ^5.x). [1]
  • @fastify/swagger: use v9.x (>=9.x compatible with Fastify ^5.x). [2]
  • @fastify/swagger-ui: use v^5.x (compatible with Fastify ^5.x; pairs with @fastify/swagger v9). [3]
  • @fastify/websocket: use the @fastify/websocket package (v5.x series for Fastify 5). [4]

References:
[1] @fastify/cors compatibility table.
[2] @fastify/swagger compatibility table / README.
[3] @fastify/swagger-ui README (version → Fastify mapping).
[4] @fastify/websocket README / repo (maintained @fastify/websocket package).


🌐 Web query:

Fastify security vulnerabilities CVE 2024 2025

💡 Result:

Here are notable Fastify-related CVEs from 2024–2025 (summary + patched versions and dates):

  1. CVE-2024-35220 — @fastify/session: cookie expiration/maxAge bug that could keep sessions alive. Patched in @fastify/session 10.8.0 (disclosed 2024). [1]

  2. CVE-2024-31999 — @fastify/secure-session: deleted/encrypted session cookies could remain reusable. Patched in @fastify/secure-session 7.3.0 (disclosed Apr 10, 2024). [2]

  3. CVE-2024-22207 — @fastify/swagger-ui: default config could expose module files when baseDir not set. Affected @fastify/swagger-ui 2.0.0–2.1.0; patched (disclosed Jan 15, 2024). [3]

  4. CVE-2025-24033 — @fastify/multipart: temporary uploaded files not deleted when requests are cancelled (resource exhaustion/cleanup). Patched in 8.3.1 and 9.0.3 (disclosed Jan 23, 2025). [4]

  5. CVE-2025-32442 — fastify core: content-type validation bypass for slightly altered content-types (affects fastify >=5.0.0 <5.3.2 and specific 4.x). Patched in fastify 5.3.2 and 4.9.1 (published Apr 18, 2025). [5]

  6. CVE-2025-66415 — fastify-reply-from: crafted URLs could access routes not intended to be proxied. Patched in fastify-reply-from 12.5.0 (2025). [6]

Recommended actions (brief):

  • Upgrade the listed packages to the patched versions above (or latest). [1][2][3][4][5][6]
  • Audit your dependency tree (npm audit / SCA) and rebuild images/containers after upgrades.
  • If you cannot immediately upgrade, apply vendor workarounds noted in advisories (see linked advisories for each CVE).

Sources:
[1] NVD / @fastify/session advisory (CVE-2024-35220). (nvd.nist.gov)
[2] Wiz / GitHub advisory summary (CVE-2024-31999). (wiz.io)
[3] Wiz / GitHub advisory (CVE-2024-22207). (wiz.io)
[4] Wiz vulnerability DB (CVE-2025-24033). (wiz.io)
[5] cve.circl / GitHub advisory (CVE-2025-32442). (cve.circl.lu)
[6] NVD record for CVE-2025-66415 (fastify-reply-from). (nvd.nist.gov)

If you’d like, I can fetch the exact advisory/commit links and suggested mitigations for any specific CVE above.

Citations:


[email protected] does not exist in npm registry—this must be corrected.

The version [email protected] returns a 404 error. The latest stable 5.x release is 5.6.2. Update the dependency to a valid version (e.g., ^5.6.2). Note that fastify 5 requires Node.js v20+ and includes breaking changes from v4; ensure the codebase accommodates the migration (full JSON Schema, .listen() behavior, logger signature changes, etc.).

All plugin versions (@fastify/cors ^11.2.0, @fastify/swagger ^9.4.2, @fastify/swagger-ui ^5.2.2, @fastify/websocket ^11.0.2) are compatible with Fastify 5.x. No known security vulnerabilities exist in these plugin versions.

🤖 Prompt for AI Agents
In apps/frontend/package.json around lines 53 to 56, the fastify dependency is
pinned to a non-existent version (5.3.4); update the fastify entry to a valid
release such as "^5.6.2", run npm/yarn install to update lockfile, and run the
test suite; additionally ensure the project uses Node.js v20+ and audit/adjust
code for Fastify v5 breaking changes (full JSON Schema usage, .listen() async
signature and return handling, and any logger signature differences) so runtime
errors do not occur after the upgrade.

Comment on lines 104 to 135
function handleAgentExit(taskId: string, code: number | null, processType: ProcessType): void {
state.eventCount++;

// Determine new status based on process type and exit code
// This mirrors the logic in agent-events-handlers.ts
let newStatus: TaskStatus;

if (processType === 'spec-creation') {
// Spec creation doesn't trigger a status change via WebSocket
// The status is updated through other means
if (debugMode) {
process.stdout.write(`[EventBridge] exit (spec-creation): ${taskId} code=${code}\n`);
}
return;
}

if (processType === 'task-execution' || processType === 'qa-process') {
// Task execution or QA process completed -> Human Review
newStatus = 'human_review';
} else {
// Unknown process type -> Human Review
newStatus = 'human_review';
}

if (debugMode) {
process.stdout.write(
`[EventBridge] exit: ${taskId} code=${code} type=${processType} -> ${newStatus}\n`
);
}

broadcastTaskStatusChange(taskId, newStatus);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Redundant else branch in handleAgentExit.

Lines 120-126 have a redundant else branch - both the if and else conditions return 'human_review'. This appears to be placeholder code or incomplete logic.

🔎 Proposed simplification
   if (processType === 'task-execution' || processType === 'qa-process') {
     // Task execution or QA process completed -> Human Review
     newStatus = 'human_review';
-  } else {
-    // Unknown process type -> Human Review
-    newStatus = 'human_review';
   }
+  // Default: Human Review (for unknown process types)
+  newStatus = 'human_review';

Or if different status mappings are intended for future process types, consider using a switch statement with explicit cases.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function handleAgentExit(taskId: string, code: number | null, processType: ProcessType): void {
state.eventCount++;
// Determine new status based on process type and exit code
// This mirrors the logic in agent-events-handlers.ts
let newStatus: TaskStatus;
if (processType === 'spec-creation') {
// Spec creation doesn't trigger a status change via WebSocket
// The status is updated through other means
if (debugMode) {
process.stdout.write(`[EventBridge] exit (spec-creation): ${taskId} code=${code}\n`);
}
return;
}
if (processType === 'task-execution' || processType === 'qa-process') {
// Task execution or QA process completed -> Human Review
newStatus = 'human_review';
} else {
// Unknown process type -> Human Review
newStatus = 'human_review';
}
if (debugMode) {
process.stdout.write(
`[EventBridge] exit: ${taskId} code=${code} type=${processType} -> ${newStatus}\n`
);
}
broadcastTaskStatusChange(taskId, newStatus);
}
function handleAgentExit(taskId: string, code: number | null, processType: ProcessType): void {
state.eventCount++;
// Determine new status based on process type and exit code
// This mirrors the logic in agent-events-handlers.ts
let newStatus: TaskStatus;
if (processType === 'spec-creation') {
// Spec creation doesn't trigger a status change via WebSocket
// The status is updated through other means
if (debugMode) {
process.stdout.write(`[EventBridge] exit (spec-creation): ${taskId} code=${code}\n`);
}
return;
}
if (processType === 'task-execution' || processType === 'qa-process') {
// Task execution or QA process completed -> Human Review
newStatus = 'human_review';
}
// Default: Human Review (for unknown process types)
newStatus = 'human_review';
if (debugMode) {
process.stdout.write(
`[EventBridge] exit: ${taskId} code=${code} type=${processType} -> ${newStatus}\n`
);
}
broadcastTaskStatusChange(taskId, newStatus);
}
🤖 Prompt for AI Agents
In apps/frontend/src/main/api/event-bridge.ts around lines 104 to 135, the
if/else that sets newStatus is redundant because both branches assign
'human_review'; simplify by removing the unnecessary else branch and directly
assigning newStatus = 'human_review' for the known process types (or replace the
whole conditional with a switch or a mapping object if you plan to support
additional processType values), ensure debug logging and
broadcastTaskStatusChange(taskId, newStatus) remain unchanged.

Comment on lines 113 to 129
export function validateApiKey(apiKey: string | undefined | null): ApiKeyValidation {
if (!apiKey || typeof apiKey !== 'string') {
return { valid: false };
}

if (!keysLoaded) {
// Keys not loaded - fail closed (reject)
return { valid: false };
}

const isValid = authConfig.validKeys.has(apiKey);

return {
valid: isValid,
// Note: We don't include keyId to avoid leaking information
};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential timing attack vulnerability in key validation.

Using Set.has() for key comparison may be vulnerable to timing attacks, as Set lookups can have variable timing based on the key's hash bucket location.

For API key validation, consider using a constant-time comparison:

Suggested improvement
import { timingSafeEqual } from 'crypto';

export function validateApiKey(apiKey: string | undefined | null): ApiKeyValidation {
  if (!apiKey || typeof apiKey !== 'string' || !keysLoaded) {
    return { valid: false };
  }

  // Constant-time comparison against all valid keys
  const apiKeyBuffer = Buffer.from(apiKey);
  let isValid = false;
  
  for (const validKey of authConfig.validKeys) {
    const validKeyBuffer = Buffer.from(validKey);
    if (apiKeyBuffer.length === validKeyBuffer.length &&
        timingSafeEqual(apiKeyBuffer, validKeyBuffer)) {
      isValid = true;
      // Don't break early to maintain constant time
    }
  }
  
  return { valid: isValid };
}
🤖 Prompt for AI Agents
In apps/frontend/src/main/api/middleware/auth.ts around lines 113 to 129, the
current Set.has() lookup can leak timing information; replace it with a
constant-time comparison: import crypto.timingSafeEqual, convert the incoming
apiKey and each stored key to Buffers, iterate over all stored keys comparing
lengths and using timingSafeEqual (do not break early) and accumulate a boolean
match flag, and ensure the early checks (apiKey type and keysLoaded) remain but
return only the accumulated result to avoid timing differences.

Comment on lines 257 to 276
export function resetAuthState(): void {
authConfig = { ...defaultAuthConfig };
keysLoaded = false;
}

/**
* Configure auth with custom keys (for testing purposes only)
*
* This function allows setting API keys programmatically for tests.
* In production, always use loadApiKeys() to load from environment.
*
* @param keys - Array of valid API keys
*/
export function setApiKeysForTesting(keys: string[]): void {
authConfig = {
...defaultAuthConfig,
validKeys: new Set(keys),
};
keysLoaded = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Testing utilities are exported from production code.

resetAuthState() and setApiKeysForTesting() are exported and could be accidentally used in production code. Consider:

  1. Moving these to a separate test utilities file
  2. Adding runtime checks to prevent production usage:
 export function setApiKeysForTesting(keys: string[]): void {
+  if (process.env.NODE_ENV === 'production') {
+    throw new Error('setApiKeysForTesting cannot be used in production');
+  }
   authConfig = {
     ...defaultAuthConfig,
     validKeys: new Set(keys),
   };
   keysLoaded = true;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function resetAuthState(): void {
authConfig = { ...defaultAuthConfig };
keysLoaded = false;
}
/**
* Configure auth with custom keys (for testing purposes only)
*
* This function allows setting API keys programmatically for tests.
* In production, always use loadApiKeys() to load from environment.
*
* @param keys - Array of valid API keys
*/
export function setApiKeysForTesting(keys: string[]): void {
authConfig = {
...defaultAuthConfig,
validKeys: new Set(keys),
};
keysLoaded = true;
}
export function resetAuthState(): void {
authConfig = { ...defaultAuthConfig };
keysLoaded = false;
}
/**
* Configure auth with custom keys (for testing purposes only)
*
* This function allows setting API keys programmatically for tests.
* In production, always use loadApiKeys() to load from environment.
*
* @param keys - Array of valid API keys
*/
export function setApiKeysForTesting(keys: string[]): void {
if (process.env.NODE_ENV === 'production') {
throw new Error('setApiKeysForTesting cannot be used in production');
}
authConfig = {
...defaultAuthConfig,
validKeys: new Set(keys),
};
keysLoaded = true;
}

@MikeeBuilds MikeeBuilds added feature New feature or request area/frontend This is frontend only labels Dec 27, 2025
@AndyMik90 AndyMik90 self-assigned this Dec 27, 2025
@kvnloo kvnloo force-pushed the feat/enhanceSubtaskView branch from ec7c63c to ed006cd Compare December 27, 2025 18:57
@kvnloo
Copy link
Contributor Author

kvnloo commented Dec 27, 2025

@AndyMik90 sorry about that, I didn't realize the REST API commits got included here. I just fixed it with a git cherry-pick, it should be good now!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (13)
apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (5)

141-161: Add explicit type="button" to prevent unintended form submissions.

This button lacks an explicit type attribute. If used inside a form, it would default to submit and could trigger unintended form submissions.

🔎 Proposed fix
           <button
+            type="button"
             onClick={() => setIsExpanded(!isExpanded)}
             className={cn(

198-208: Add explicit type="button" to this button as well.

Same issue - missing explicit type attribute.

🔎 Proposed fix
           <button
+            type="button"
             onClick={() => setIsExpanded(!isExpanded)}

279-295: Add explicit type="button" to the CollapsibleTrigger button.

🔎 Proposed fix
         <button
+          type="button"
           className={cn(
             'w-full flex items-center justify-between px-2 py-1.5 rounded-md transition-colors',

447-453: Add explicit type="button" to the "View all logs" button.

🔎 Proposed fix
           <button
+            type="button"
             onClick={onViewAllLogs}

426-453: Hardcoded user-facing strings should use translation keys.

Per coding guidelines, all user-facing text in React components should use useTranslation() with translation keys. The following strings need internationalization:

  • Line 430: "No actions recorded"
  • Line 444: "Top {n} of {m} actions"
  • Line 451: "View all logs"
  • Line 482: "Showing top {n} most relevant from {m} total actions"

Additionally, strings in FilesSection (lines 339, 347, 374) and getToolInfo labels should be internationalized.

As per coding guidelines, consider using the useTranslation hook:

import { useTranslation } from 'react-i18next';

// In component:
const { t } = useTranslation('taskDetail');

// Usage:
<p>{t('subtaskActions.noActionsRecorded')}</p>
<span>{t('subtaskActions.topActions', { displayed: displayActions.length, total: actions.length })}</span>
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (3)

2-2: Remove unused import ArrowUpDown.

The ArrowUpDown icon is imported but never used in this file.

-import { CheckCircle2, Clock, XCircle, AlertCircle, ListChecks, FileCode, ChevronDown, ChevronRight, Sparkles, ArrowUpDown, ArrowDownWideNarrow, ListOrdered } from 'lucide-react';
+import { CheckCircle2, Clock, XCircle, AlertCircle, ListChecks, FileCode, ChevronDown, ChevronRight, Sparkles, ArrowDownWideNarrow, ListOrdered } from 'lucide-react';

142-161: Add explicit type="button" to prevent unintended form submission.

Per static analysis, buttons without an explicit type default to submit.

 <button
+  type="button"
   onClick={toggleSortMode}
   className={cn(

298-314: Add explicit type="button" to the CollapsibleTrigger button.

 <button
+  type="button"
   className={cn(
apps/frontend/src/renderer/lib/actionScoring.ts (5)

95-98: Remove unused constant SUCCESS_TYPES.

This constant is defined but never referenced anywhere in the file.

🔎 Proposed fix
-/**
- * Entry types that indicate success (lower priority than errors)
- */
-const SUCCESS_TYPES: TaskLogEntryType[] = ['success'];

200-239: Time anomaly scoring is effectively disabled.

parseDuration always returns undefined, which means:

  • calculateAverageDuration always returns undefined
  • isTimeAnomaly always returns false
  • The TIME_ANOMALY weight (10 points) is never applied

Consider adding a TODO comment to clarify intent, or removing the dead code path until duration tracking is implemented:

// TODO: Implement duration-based scoring when TaskLogEntry includes duration data

576-578: indexOf in sort comparator is O(n) per comparison.

Using subtaskIds.indexOf(a) inside the sort comparator performs a linear search for each comparison, leading to O(n² log n) complexity for large arrays.

🔎 Proposed fix using index map
 export function sortSubtasksByRelevance(
   subtaskIds: string[],
   relevanceScores: Map<string, SubtaskRelevanceScore>
 ): string[] {
+  // Pre-compute index map for O(1) lookups
+  const indexMap = new Map(subtaskIds.map((id, idx) => [id, idx]));
+
   return [...subtaskIds].sort((a, b) => {
     // ... existing logic ...
     
     // Tertiary: stable sort by original index
-    return subtaskIds.indexOf(a) - subtaskIds.indexOf(b);
+    return (indexMap.get(a) ?? 0) - (indexMap.get(b) ?? 0);
   });
 }

344-387: Consider consolidating duplicate scoring logic.

The two branches (lines 360-369 for small arrays, lines 371-386 for larger) contain nearly identical code. The early return for small arrays doesn't provide meaningful optimization.

🔎 Proposed simplification
 export function filterTopActions(
   actions: TaskLogEntry[],
   n: number = DEFAULT_TOP_N,
   subtaskId?: string
 ): ScoredAction[] {
-  if (!actions || actions.length === 0) {
+  if (!actions || actions.length === 0 || n <= 0) {
     return [];
   }

   let filteredActions = subtaskId
     ? actions.filter((a) => a.subtask_id === subtaskId)
     : actions;

-  if (filteredActions.length <= n) {
-    const context: ScoringContext = { ... };
-    return filteredActions
-      .map((action, index) => scoreAction(action, index, context))
-      .sort(compareScoredActions);
-  }
-
   const context: ScoringContext = {
     averageDuration: calculateAverageDuration(filteredActions),
     seenToolTypes: new Set<string>(),
   };

   const scoredActions = filteredActions.map((action, index) =>
     scoreAction(action, index, context)
   );

   scoredActions.sort(compareScoredActions);
-  return scoredActions.slice(0, n);
+  return scoredActions.slice(0, Math.min(n, scoredActions.length));
 }

416-445: Hardcoded user-facing strings should use translation keys.

Per coding guidelines, getScoreReason returns hardcoded English strings that appear to be displayed in the UI (via ScoreBadge component). These should be internationalized.

Consider returning translation keys instead of hardcoded strings:

export const SCORE_REASON_KEYS = {
  ERROR: 'actionScoring:reasons.errorDetected',
  WARNING: 'actionScoring:reasons.warningDetected',
  DECISION: 'actionScoring:reasons.keyDecision',
  // ...
} as const;

Then have UI components translate the keys using useTranslation(). As per coding guidelines, user-facing text must use translation keys.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec7c63c and ed006cd.

📒 Files selected for processing (5)
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/lib/actionScoring.ts
🧰 Additional context used
📓 Path-based instructions (2)
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
🧠 Learnings (3)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)

Applied to files:

  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
🧬 Code graph analysis (3)
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (1)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (1)
  • TaskSubtasks (63-343)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (3)
apps/frontend/src/shared/types/task.ts (3)
  • Task (235-255)
  • TaskLogs (87-96)
  • TaskLogEntry (64-77)
apps/frontend/src/renderer/lib/actionScoring.ts (4)
  • filterTopActions (344-387)
  • calculateSubtaskRelevanceScores (524-535)
  • sortSubtasksByRelevance (548-579)
  • getImportantFiles (814-829)
apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (1)
  • SubtaskActionList (407-487)
apps/frontend/src/renderer/lib/actionScoring.ts (1)
apps/frontend/src/shared/types/task.ts (2)
  • TaskLogEntry (64-77)
  • TaskLogEntryType (62-62)
🪛 Biome (2.1.2)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx

[error] 142-152: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 298-306: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx

[error] 141-148: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 198-205: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 279-282: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 447-450: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🔇 Additional comments (8)
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (1)

426-430: LGTM!

The integration cleanly passes phaseLogs from the modal's state and provides an onViewAllLogs callback to navigate to the logs tab. This properly connects the new action summarization UI to the existing modal architecture.

apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts (2)

1-52: Well-structured test file with comprehensive coverage.

The test helpers createTestAction and createScoringContext are cleanly factored, and the file header clearly documents the test scope. The coverage spans constants, predicates, scoring logic, filtering, grouping, relevance scoring, and file extraction.


858-870: Good defensive test for immutability.

The test verifying sortSubtasksByRelevance doesn't mutate the original array is a valuable safeguard against accidental side effects.

apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (1)

48-65: LGTM - Tool info helper is well-structured.

The getToolInfo function provides consistent styling and icon mapping for different tool types, mirroring the pattern from TaskLogs.tsx as noted in the comment.

apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (2)

36-61: LGTM - Helper functions are cleanly factored.

getAllEntriesFromPhaseLogs and getSubtaskActionCount are well-structured utilities that centralize phase log traversal logic. The iteration over all three phases ensures comprehensive entry collection.


90-100: Good memoization strategy for scored actions.

Using useCallback with allEntries dependency for getSubtaskActions ensures scored actions are only recomputed when the underlying entries change, not on every render. The lazy computation pattern (only when expanded) is a good performance optimization.

apps/frontend/src/renderer/lib/actionScoring.ts (2)

1-28: Well-documented module with clear cognitive science rationale.

The module header effectively explains the scoring weights with references to relevant research (Csikszentmihalyi, Kahneman, Bjork). The exported constants and types provide a clean public API for the scoring system.


472-515: LGTM - Subtask relevance scoring is well-designed.

The calculateSubtaskRelevance function correctly aggregates individual action scores into a composite subtask relevance score. The flags for hasErrors and hasDecisions enable effective prioritization in the UI.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed006cd and ef4d811.

📒 Files selected for processing (1)
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
🧰 Additional context used
📓 Path-based instructions (2)
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
🧬 Code graph analysis (1)
apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (1)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (1)
  • TaskSubtasks (63-343)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef4d811 and 35a28ed.

📒 Files selected for processing (7)
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/lib/actionScoring.ts
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
🧰 Additional context used
📓 Path-based instructions (3)
apps/frontend/src/shared/i18n/locales/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

Add new translation keys to ALL language files (minimum: en/*.json and fr/*.json) in apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
  • apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
🧠 Learnings (3)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)

Applied to files:

  • apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx
  • apps/frontend/src/renderer/lib/actionScoring.ts
🧬 Code graph analysis (3)
apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (4)
apps/frontend/src/renderer/lib/actionScoring.ts (3)
  • ScoredAction (36-41)
  • getScoreReasonKeys (405-436)
  • groupActionsBySubphase (384-397)
.design-system/src/lib/utils.ts (1)
  • cn (4-6)
.design-system/src/components/Badge.tsx (1)
  • Badge (9-27)
apps/frontend/scripts/download-python.cjs (1)
  • key (106-106)
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (2)
apps/frontend/src/shared/types/task.ts (3)
  • Subtask (32-43)
  • Task (235-255)
  • TaskLogEntry (64-77)
apps/frontend/src/renderer/lib/actionScoring.ts (4)
  • filterTopActions (341-376)
  • calculateSubtaskRelevanceScores (557-568)
  • sortSubtasksByRelevance (581-615)
  • getImportantFiles (864-879)
apps/frontend/src/renderer/lib/actionScoring.ts (1)
apps/frontend/src/shared/types/task.ts (2)
  • TaskLogEntry (64-77)
  • TaskLogEntryType (62-62)
🔇 Additional comments (22)
apps/frontend/src/shared/i18n/locales/en/tasks.json (1)

86-126: LGTM! Well-structured i18n keys for the new subtask action summarization feature.

The new detail namespace with nested sections (subtasks, actions, tools, scoring) follows a logical structure that aligns with the UI components. The interpolation patterns (e.g., {{completed}}, {{displayed}}) are correctly formatted for i18next.

apps/frontend/src/shared/i18n/locales/fr/tasks.json (1)

86-126: LGTM! French translations are complete and maintain parity with the English file.

All translation keys added in the English file are properly mirrored here with French translations. The interpolation placeholders ({{completed}}, {{total}}, {{displayed}}) are correctly preserved. Based on learnings, this satisfies the requirement to add new translation keys to ALL language files.

apps/frontend/src/renderer/lib/__tests__/actionScoring.test.ts (1)

1-39: LGTM! Comprehensive test suite with excellent coverage.

The test file thoroughly covers:

  • All exported constants and interfaces
  • Predicate functions (isErrorAction, isWarningAction, isDecisionAction, isFileChangeAction, isNovelty)
  • Core scoring logic with score breakdown validation
  • Edge cases (null/undefined, empty, single action, N=0, negative N)
  • Performance benchmarks with CI-aware thresholds
  • Integration scenarios with realistic action mixes
  • Subtask relevance scoring and sorting
  • File extraction and summarization

The helper functions createTestAction and createScoringContext provide clean test setup.

apps/frontend/src/renderer/lib/actionScoring.ts (5)

1-52: LGTM! Well-documented module with clear cognitive science rationale.

The module header clearly documents the scoring weights and their research-backed justifications. The exported interfaces (ScoredAction, ScoreBreakdown, ScoringContext) provide good type safety for consumers.


195-205: Good documentation of the unimplemented feature.

The TODO clearly explains why parseDuration returns undefined and what's needed to enable TIME_ANOMALY scoring. This prevents confusion about the dead code path.


282-288: Potential unbounded score from file change multiplier.

The fileChange score is multiplied by Math.max(1, filesChanged), but filesChanged is capped at 3 by countFilesChanged. However, the comment says "cap at 3x base weight" which is correct behavior. This is fine as-is.


405-436: Clean i18n-ready implementation.

getScoreReasonKeys correctly returns translation keys that match the keys defined in tasks.json. The deprecated getScoreReason is preserved for backwards compatibility with appropriate @deprecated JSDoc.


581-615: Efficient sorting with pre-computed index map.

Good use of the index map for O(1) lookups in the tertiary sort, addressing the previous O(n²) concern. The composite score formula clearly prioritizes errors (1000 bonus) over other factors.

apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx (3)

1-1: LGTM! Appropriate import addition.

The useCallback import is correctly added to support the memoized callback.


159-162: LGTM! Well-memoized callback.

The handleViewAllLogs callback is correctly memoized with useCallback and the appropriate dependency (state.setActiveTab). This prevents unnecessary re-renders of TaskSubtasks when other state changes.


436-440: LGTM! Proper prop wiring to TaskSubtasks.

The phaseLogs and onViewAllLogs props are correctly passed, enabling the subtasks component to access phase log data and navigate to the logs tab.

apps/frontend/src/renderer/components/task-detail/SubtaskActionList.tsx (6)

1-43: LGTM! Clean imports and well-typed interface.

The component imports are appropriate, and SubtaskActionListProps is well-documented with JSDoc comments explaining each prop's purpose.


49-67: Good i18n pattern with fallback for unknown tools.

The getToolInfo function correctly returns translation keys for known tools and provides a fallback label for unknown tools. The pattern of returning labelKey: null with a fallbackLabel is handled properly in the consumer.


105-177: LGTM! Well-structured tool action rendering.

The ScoredActionItem component correctly handles both tool actions and typed entries with proper i18n usage. The type="button" attributes are present on interactive elements.


241-271: LGTM! Clean ScoreBadge implementation.

The component correctly uses getScoreReasonKeys with the Pick type (no unsafe assertion needed since getScoreReasonKeys accepts Pick<ScoredAction, 'scoreBreakdown'>). Translation keys are properly resolved via t().


282-321: LGTM! SubphaseGroup with proper accessibility.

The collapsible group uses type="button" on the trigger and provides clear visual feedback for expansion state.


420-503: LGTM! Main component with proper memoization and i18n.

The SubtaskActionList component:

  • Uses useMemo appropriately for displayActions and groupedActions
  • All user-facing strings use translation keys
  • Handles empty state gracefully
  • Uses type="button" on the "View all logs" button
apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx (5)

1-11: LGTM! Clean imports with no unused dependencies.

The imports are appropriate for the component's functionality. The ArrowUpDown icon was correctly removed as noted in past reviews.


40-65: LGTM! Helper functions with clear responsibilities.

getAllEntriesFromPhaseLogs efficiently flattens phase log entries, and getSubtaskActionCount provides a simple count API. Both handle null/undefined inputs gracefully.


95-126: LGTM! Well-structured memoization strategy.

  • allEntries is memoized based on phaseLogs
  • getSubtaskActions is a useCallback that captures allEntries
  • relevanceScores recalculates when entries or subtasks change
  • sortedSubtasks uses a proper type guard: .filter((s): s is Subtask => s != null)

This addresses the previous concern about non-null assertions.


102-105: getSubtaskActions recreates on every allEntries change but is called conditionally.

The useCallback for getSubtaskActions is recreated whenever allEntries changes. Since it's only called when isExpanded is true, this is fine. However, consider if this could cause issues if many subtasks are expanded simultaneously.

This is informational - the current implementation is correct. Each expanded subtask will call filterTopActions which scores and sorts, potentially multiple times if allEntries changes frequently. For the expected use case (5-10 subtasks, few expanded at once), this should be acceptable.


328-342: LGTM! Clean integration with SubtaskActionList.

The SubtaskActionList is rendered with appropriate props, including the memoized scoredActions and file information. The conditional rendering based on hasActions ensures the component only appears when relevant.

@kvnloo kvnloo changed the title Intelligent Subtask Action Summarization UI feat(subtask): enhance subtask view to intelligently surface the most relevant actions from the logs Dec 27, 2025
kvnloo and others added 11 commits December 27, 2025 16:28
Implement cognitively-optimized expandable view for subtasks that intelligently surfaces the 5 most relevant agent actions from logs containing 1000+ actions. Add comprehensive action scoring algorithm with tests to create a middle layer between raw logs and user interface for better information clarity.

Signed-off-by: kevin rajan <[email protected]>
Fixes AndyMik90#235

The Edit Task modal's close button (X) was unresponsive because both the parent
modal and the edit dialog used z-50 for their overlays. The parent's overlay
intercepted clicks meant for the edit dialog's close button.

This fix hides the parent modal while the Edit dialog is open, then reopens it
when the Edit dialog closes. This is a cleaner UX than z-index hacks.

Signed-off-by: Black Circle Sentinel <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
* fix: make backend tests pass on Windows

* fix: address Windows locking + lazy graphiti imports

* fix: address CodeRabbit review comments

* fix: improve file_lock typing

* Update apps/backend/runners/github/file_lock.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: satisfy ruff + asyncio loop usage

* style: ruff format file_lock

* refactor: safer temp file close + async JSON read

* style: ruff format file_lock

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Andy <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
AndyMik90#351)

* fix(analyzer): add C#/Java/Swift/Kotlin project files to security hash

Fixes AndyMik90#222

The security profile hash calculation was missing key config files for
several languages, causing the profile not to regenerate when:
- C# projects (.csproj, .sln, .fsproj, .vbproj) changed
- Java/Kotlin/Scala projects (pom.xml, build.gradle, etc.) changed
- Swift packages (Package.swift) changed

Changes:
- Add Java, Kotlin, Scala, Swift config files to hash_files list
- Add glob patterns for .NET project files (can be anywhere in tree)
- Update fallback source extensions to include .cs, .swift, .kt, .java

Signed-off-by: Black Circle Sentinel <[email protected]>

* fix(analyzer): replace empty except pass with continue

---------

Signed-off-by: Black Circle Sentinel <[email protected]>
Co-authored-by: Andy <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
…ik90#358)

* fix(terminal): preserve terminal state when switching projects

Fixes terminal state loss when switching between project tabs (AndyMik90#342).

Two issues addressed:
1. PTY health check: Added checkTerminalPtyAlive IPC method to detect
   terminals with stale state (no live PTY process). restoreTerminalSessions
   now removes dead terminals and restores from disk instead of skipping.

2. Buffer preservation: Added SerializeAddon to capture terminal buffer
   with ANSI escape codes before disposal. This preserves the shell prompt,
   colors, and output history when switching back to a project.

Closes AndyMik90#342

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

* fix(terminal): address PR review findings

Addresses 5 findings from Auto Claude PR Review:

1. [HIGH] Race condition protection: Added restoringProjects Set to prevent
   concurrent restore calls for the same project

2. [HIGH] Unnecessary disk restore: Skip disk restore when some terminals
   are still alive to avoid duplicates

3. [HIGH] Double dispose vulnerability: Added isDisposedRef guard to prevent
   corrupted serialization on rapid unmount/StrictMode

4. [MEDIUM] SerializeAddon disposal: Explicitly call dispose() before
   setting ref to null

5. [MEDIUM] projectPath validation: Added input validation at function start

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

* fix(terminal): allow disk restore when alive terminals exist

CodeRabbit review finding: When a project has mixed alive and dead
terminals, the early return was preventing disk restore, causing
dead terminals to be permanently lost.

The fix removes the early return since addRestoredTerminal() already
has duplicate protection (checks terminal ID before adding). This
allows dead terminals to be safely restored from disk while alive
terminals remain unaffected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

* fix(terminal): remove unused aliveTerminals variable

CodeQL flagged unused variable after previous fix removed the early
return that was using it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

---------

Co-authored-by: Claude Opus 4.5 <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
- Add getScoreReasonKeys() to return translation keys instead of hardcoded strings
- Convert tool labels in SubtaskActionList to use i18n translation keys
- Add comprehensive translations for score reasons in en/fr tasks.json
- Consolidate filterTopActions logic and improve edge case handling
- Update tests to verify i18n key generation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
… ruff version, and broken quality-dco workflow (AndyMik90#334)

* fix: Fixes issues to get clean pre-commit run

1. version-sync hook was failing due to formatting,
fixed with block scalar.
2. Python Tests step was failing because it could not locate python
or pytest. Fixed by referencing pytest in .venv,
[as was shown here in CONTRIBUTING.md](https://github.com/AndyMik90/Auto-Claude/blob/develop/CONTRIBUTING.md?plain=1#L299)

At this point pre-commit could run, then there were a few issues it found that had to be fixed:

3. "check yaml" hook failed for the file
".github/workflows/quality-dco.yml". Fixed indenting issue.

4. Various files had whitespace issues that were auto-fixed by the
pre-commit commands.

After this, "pre-commit run --all-files" passes for all checks.

Signed-off-by: Ian <[email protected]>

* docs: Update CONTRIBUTING.md with cmake dependency

cmake is not present by default on macs, can be installed via homebrew

Signed-off-by: Ian <[email protected]>

* Addressed PR comments on file consistency and install instructions.

Signed-off-by: Ian <[email protected]>

* Ran pre-commit autoupdate, disabled broken quality-dco workflow

The version of ruff in pre-commit was on a much older version than what was running as part of the lint github workflow. This caused it to make changes that were rejected by the newer version.
As far as disabling quality-dco workflow; according to https://github.com/AndyMik90/Auto-Claude/actions/workflows/quality-dco.yml, it has never actually successfully parsed since it was introduced in AndyMik90#266, and so it has not been running on any PRs to date. Given that, plus the fact that I see no mention/discussion of Developer Certificate of Origin in any github issues or the discord, I will run with the assumption this needs more explicit discussion before we turn it on and force all contributors to add these signoffs for every commit.

Signed-off-by: Ian <[email protected]>

* Fixed bad sed command in pre-commit version-sync hook

It resulted in bad version names being produced for beta versions, such as "Auto-Claude-2.7.2-beta.9-beta.9-arm64.dmg". Also addressed PR comment for needed spacing in markdown code blocks.

Signed-off-by: Ian <[email protected]>

* Fixed other sed command for version sync to avoid incorrect names

Addresses PR comment to keep this in line with existing sed command fix in the same PR.

Signed-off-by: Ian <[email protected]>

* Keep version of ruff in sync between pre-commit and github workflow

This will avoid situations where the checks done locally and in CI start to diverge and even conflict

Signed-off-by: Ian <[email protected]>

* Enabling DCO workflow

Signed-off-by: Ian <[email protected]>

* Fixed windows compatibility issue for running pytest

Also committing some more file whitespace changes made by the working pre-commit hook.

Signed-off-by: Ian <[email protected]>

* Removed out of date disabled banner on quality dco workflow

Signed-off-by: Ian <[email protected]>

* Fixed version-sync issue with incorrect version badge image url, fixed dco workflow

Updated readme with correct value as well
Fixed DCO workflow as it was pointing at a nonexistent step.
Improved DCO workflow failure message to warn about accidentally signing others commits.

---------

Signed-off-by: Ian <[email protected]>
Co-authored-by: Andy <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
* fix(subprocess): handle Python paths with spaces

Fixes AndyMik90#315

The packaged macOS app uses a Python path inside ~/Library/Application Support/
which contains a space. The subprocess-runner.ts was passing the path directly
to spawn(), causing ENOENT errors.

This fix adds parsePythonCommand() (already used by agent-process.ts) to properly
handle paths with spaces. This also affects Changelog generation and other
GitHub automation features.

Signed-off-by: Black Circle Sentinel <[email protected]>

* test(subprocess): add unit tests for python path spaces and arg ordering

---------

Signed-off-by: Black Circle Sentinel <[email protected]>
Co-authored-by: Andy <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
…AndyMik90#355)

* fix(security): invalidate profile cache when file is created/modified

Fixes AndyMik90#153

The security profile cache was returning stale data even after the
.auto-claude-security.json file was created or updated. This caused
commands like 'dotnet' to be blocked even when present in the file.

Root cause: get_security_profile() cached the profile on first call
without checking if the file's mtime changed on subsequent calls.

Fix: Track the security profile file's mtime and invalidate the cache
when the file is created (mtime goes from None to a value) or modified
(mtime changes).

This also helps with issue AndyMik90#222 where the profile is created after the
agent starts - now the agent will pick up the new profile on the next
command validation.

Signed-off-by: Black Circle Sentinel <[email protected]>

* fix(security): handle deleted profile file and add cache invalidation tests

* fix(security): handle deleted profile file and add cache invalidation tests

* test(security): improve cache tests with mocks and unique commands

* test(security): add mock-free tests for cache invalidation

* test(security): fix cache invalidation tests without mocks

* fix(security): address review comments and add debug logs for CI hash failure

* fix(analyzer): remove debug prints

* fix(lint): sort imports in profile.py

* fix(security): include spec_dir in cache key to prevent stale profiles

The cache key previously only included project_dir, but the profile
location can depend on spec_dir. This could cause stale cached profiles
to be returned if spec_dir changes between calls.

Fix: Add _cached_spec_dir to the cache validation logic and reset function.

---------

Signed-off-by: Black Circle Sentinel <[email protected]>
Co-authored-by: Andy <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
…op (AndyMik90#362)

The projectTabs array was being included in the useEffect dependency
array, but since it's computed fresh on every render (via getProjectTabs()),
it always has a new reference. This caused the effect to fire on every
render cycle, creating an infinite re-render loop.

Fix: Use openProjectIds.includes() instead of projectTabs.some() since
openProjectIds is stable state and already tracks the same information.

Fixes performance regression in beta.10 where UI interactions took 5-6 seconds.

Co-authored-by: Andy <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
- Fix formatTime to respect user locale (use undefined instead of 'en-US')
- Fix getFilenameFromPath to handle Windows paths (split on /[\\/]/)
- Fix O(n²) findIndex in TaskSubtasks by precomputing index map
- Add i18n translations for tooltip strings (actionsCount, averageScore, topScore)
- Fix tiebreaker test to assert exact original order for ties
- Fix quoted-path regex: move quoted patterns first, remove /g flags, use exec()
- Fix CodeQL warning: combine undefined checks in isTimeAnomaly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: kevin rajan <[email protected]>
@kvnloo kvnloo force-pushed the feat/enhanceSubtaskView branch from cc49c2a to daa88db Compare December 27, 2025 22:29
@MikeeBuilds MikeeBuilds added the size/XL Extra large (1000+ lines) label Dec 28, 2025
@AlexMadera AlexMadera self-assigned this Dec 29, 2025
@AlexMadera AlexMadera added this to the Release 2.8 milestone Dec 30, 2025
@CLAassistant
Copy link

CLAassistant commented Dec 30, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
3 out of 5 committers have signed the CLA.

✅ kvnloo
✅ MikeeBuilds
✅ AndyMik90
❌ tosincarik
❌ ianstantiate
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/frontend This is frontend only feature New feature or request ❌ MERGE CONFLICTS size/XL Extra large (1000+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants