Skip to content

fix: include monorepo root dependencies in project_index dependency_locations#1902

Open
BlackStar1453 wants to merge 2 commits intoAndyMik90:developfrom
BlackStar1453:fix/worktree-dependency-locations
Open

fix: include monorepo root dependencies in project_index dependency_locations#1902
BlackStar1453 wants to merge 2 commits intoAndyMik90:developfrom
BlackStar1453:fix/worktree-dependency-locations

Conversation

@BlackStar1453
Copy link

@BlackStar1453 BlackStar1453 commented Feb 25, 2026

Base Branch

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

Description

ProjectAnalyzer._find_and_analyze_services() iterates subdirectories of service_locations to discover services but never analyzes the project root itself. In monorepo projects where the root has package.json + node_modules (npm/pnpm workspaces pattern), the root-level node_modules (~1GB) is completely missed from dependency_locations, causing worktrees to duplicate the full node_modules instead of symlinking it.

This fix adds a root-level dependency check after the monorepo service discovery loop. If the project root has dependency-bearing files and contributes dependency_locations, it's included as a "root" service.

Related Issue

Closes #1901

Type of Change

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

Area

  • Frontend
  • Backend
  • Fullstack

AI Disclosure

  • This PR includes AI-generated code (Claude, Codex, Copilot, etc.)

Tool(s) used: Claude Code (Claude Opus 4.6)
Testing level:

  • Untested -- AI output not yet verified

  • Lightly tested -- ran the app / spot-checked key paths

  • Fully tested -- all tests pass, manually verified behavior

  • I understand what this PR does and how the underlying code works

What Changed

Single file: apps/backend/analysis/analyzers/project_analyzer_module.py (+18 lines)

After the existing monorepo service discovery loop (which finds apps/frontend, apps/backend, etc.), added a check for root-level dependencies:

  1. Checks if the project root is already covered by discovered services
  2. If not, checks if root has dependency-bearing files (package.json, requirements.txt, pyproject.toml)
  3. If so, runs ServiceAnalyzer on the root and includes it if it has dependency_locations

Before: dependency_locations in project_index.json was missing root node_modules

[
  {"type": "node_modules", "path": "apps/frontend/node_modules", "service": "frontend"},
  {"type": "venv", "path": "apps/backend/.venv", "service": "backend"}
]

After:

[
  {"type": "node_modules", "path": "apps/frontend/node_modules", "service": "frontend"},
  {"type": "venv", "path": "apps/backend/.venv", "service": "backend"},
  {"type": "node_modules", "path": "node_modules", "service": "root", "package_manager": "npm"}
]

Verification

Ran the analyzer on the Auto-Claude project itself and confirmed root node_modules now appears in dependency_locations. The existing _aggregate_dependency_locations() method already handles root paths correctly (Path(".") / "node_modules""node_modules").

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)

Platform Testing Checklist

  • Windows tested (either on Windows or via CI)
  • macOS tested (either on macOS or via CI)
  • Linux tested (CI covers this)
  • Used centralized platform/ module instead of direct process.platform checks
  • No hardcoded paths (used findExecutable() or platform abstractions)

CI/Testing Requirements

  • All CI checks pass on all platforms (Windows, macOS, Linux)
  • All existing tests pass
  • New features include test coverage
  • Bug fixes include regression tests

Feature Toggle

  • N/A - Feature is complete and ready for all users

Breaking Changes

Breaking: No

The change only adds previously-missing data to dependency_locations. All consumers already handle arbitrary entries in this list, so no downstream changes are needed.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed potential UI performance issues by disabling console output in production builds.
    • Enhanced monorepo root dependency analysis to ensure shared dependencies are properly detected and included.

BlackStar1453 and others added 2 commits February 25, 2026 18:12
In packaged Electron apps, console.log writes to a pipe/PTY whose buffer
can fill up, causing the synchronous write() syscall to block the main
thread indefinitely. This was observed as a 66-second UI freeze on
2026-02-25 (macOS hang report). Setting console transport level to false
in production eliminates the blocking write path entirely.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
ProjectAnalyzer._find_and_analyze_services() iterates subdirectories
of service_locations but never analyzes the project root itself as a
service. In monorepo projects where the root has package.json +
node_modules (e.g., npm/pnpm workspaces), these root-level
dependencies are completely missed, causing dependency_locations to
be empty for the largest dependency directory (~1GB node_modules).

This causes worktrees to either fail to create symlinks or have
agents run npm install, duplicating the full node_modules per
worktree.

After the monorepo service discovery loop, check if the project root
has dependency-bearing files (package.json, requirements.txt,
pyproject.toml) and analyze it as a "root" service if it contributes
dependency_locations. This ensures root-level node_modules gets
included and properly symlinked into worktrees.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

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

This pull request addresses two distinct issues: one related to backend dependency analysis in monorepos and another concerning frontend logging performance. The primary goal is to enhance the accuracy of dependency tracking for monorepo root projects and to improve application stability by optimizing console logging behavior in production builds.

Highlights

  • Monorepo Root Dependencies: The ProjectAnalyzer now correctly identifies and includes root-level dependencies (like node_modules in monorepos using npm/pnpm workspaces) in dependency_locations, preventing unnecessary duplication in worktrees.
  • Frontend Logging Behavior: Modified the electron-log console transport to disable logging in production environments to prevent UI hangs caused by synchronous writes to potentially full stdio buffers.
Changelog
  • apps/backend/analysis/analyzers/project_analyzer_module.py
    • Added logic to detect and analyze dependencies in the project root for monorepos.
    • Ensured the root is only analyzed if not already covered by existing services and if dependency indicator files are present.
    • Included root service information in the services dictionary if dependencies are found.
  • apps/frontend/src/main/app-logger.ts
    • Changed the console log level from warn to false for production builds.
    • Added a comment explaining the rationale for disabling console logging in production to prevent UI hangs.
Activity
  • The author, BlackStar1453, has provided a detailed description of the bug fix, including before/after examples of dependency_locations.
  • The change was developed with the assistance of AI (Claude Code, Claude Opus 4.6) and was lightly tested by running the app and spot-checking key paths.
  • Verification was performed by running the analyzer on the Auto-Claude project itself, confirming the root node_modules now appears.
  • The PR targets the develop branch and is classified as a bug fix in the backend area.
  • The author confirmed understanding of the PR's functionality and adherence to code principles and testing checklists, including macOS testing.
Using Gemini Code Assist

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

Invoking Gemini

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

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

Customization

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

Limitations & Feedback

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

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

Footnotes

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

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🎉 Thanks for your first PR!

A maintainer will review it soon. Please make sure:

  • Your branch is synced with develop
  • CI checks pass
  • You've followed our contribution guide

Welcome to the Auto Claude community!

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request addresses an issue where dependencies in a monorepo's root were not being detected. The fix introduces a check for root-level dependencies after scanning for services in subdirectories, which correctly identifies and includes them in the project index. This is a good improvement for monorepo support. I've added one suggestion to improve code maintainability by extracting a hardcoded list of files into a constant. The other change in app-logger.ts to disable console logging in production is also a good performance fix.

Path(s.get("path", "")) for s in services.values()
}
if not already_covered:
dep_indicators = ("package.json", "requirements.txt", "pyproject.toml")
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This tuple of dependency indicator files is hardcoded. For better maintainability and clarity, consider defining this as a named constant at the module level, for example ROOT_DEPENDENCY_FILES. This makes the purpose of this list explicit and easier to update in the future.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Adds logic to analyze root-level dependencies in monorepo projects when the root contains dependency indicators and no service already covers it, ensuring root-level dependencies are included in analysis results. Also disables console logging in production builds to prevent potential stdio buffering issues.

Changes

Cohort / File(s) Summary
Monorepo Root Dependency Analysis
apps/backend/analysis/analyzers/project_analyzer_module.py
Extends dependency detection to analyze the project root in monorepos when it contains dependency files (package.json, requirements.txt, pyproject.toml) and is not already covered by service-level analysis. Adds a synthetic "root" service entry to include root-level dependencies in aggregated results.
Logger Configuration
apps/frontend/src/main/app-logger.ts
Disables console transport in non-development environments (changed from 'warn' level to false) to prevent potential UI hangs from stdio buffering. Updated documentation to explain production behavior rationale.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

bug, area/fullstack, size/S

Suggested reviewers

  • AndyMik90
  • AlexMadera

Poem

🐰 Root dependencies were lost in the maze,
Monorepo mysteries in a confusing haze,
Now the analyzer seeks the deepest ground,
While logs fall silent—no console sound!
Disk space saved, and peace profound!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR includes an unrelated commit (fix: disable console transport in production) that is not part of the linked issue #1901 requirements, which specifically addresses monorepo root dependency analysis. Remove the console transport commit or separate it into a different PR, as issue #1901 only requires fixing the monorepo root dependency analysis in project_analyzer_module.py.
Out of Scope Changes check ⚠️ Warning The commit addressing Electron console transport blocking (apps/frontend/src/main/app-logger.ts) is out of scope for issue #1901, which focuses exclusively on backend monorepo dependency analysis. Move the console transport fix to a separate PR to keep this PR focused on the monorepo root dependency issue.
✅ 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 directly and specifically describes the main change: adding monorepo root dependencies to the project_index dependency_locations field, which matches the primary modification in project_analyzer_module.py.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

❤️ Share

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

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/backend/analysis/analyzers/project_analyzer_module.py`:
- Around line 123-136: The check for already_covered should compare
normalized/resolved paths and the insertion of a synthetic root should not
clobber a real service named "root"; modify the logic that builds
already_covered to use Path(...).resolve() (or .absolute()) for each
s.get("path") and self.project_dir.resolve(), and before assigning
services["root"] ensure you do not overwrite an existing key (e.g., skip if
"root" in services or choose a non-colliding key), and keep the existing
creation flow that uses ServiceAnalyzer(self.project_dir, "root") and
root_info.get("dependency_locations") to populate the synthetic root only when
safe.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60c4890 and e79693f.

📒 Files selected for processing (2)
  • apps/backend/analysis/analyzers/project_analyzer_module.py
  • apps/frontend/src/main/app-logger.ts

Comment on lines +123 to +136
already_covered = self.project_dir in {
Path(s.get("path", "")) for s in services.values()
}
if not already_covered:
dep_indicators = ("package.json", "requirements.txt", "pyproject.toml")
root_has_deps = any(
(self.project_dir / f).exists() for f in dep_indicators
)
if root_has_deps:
root_analyzer = ServiceAnalyzer(self.project_dir, "root")
root_info = root_analyzer.analyze()
root_deps = root_info.get("dependency_locations", [])
if root_deps:
services["root"] = root_info
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 | 🟠 Major

Avoid overwriting a real root service and harden root coverage detection.

Line 136 unconditionally writes services["root"], which can clobber an actual discovered service named root. Also, Line 123-Line 125 compares non-normalized paths, which can mis-detect already_covered and trigger unintended insertion.

Proposed fix
-            already_covered = self.project_dir in {
-                Path(s.get("path", "")) for s in services.values()
-            }
+            discovered_paths: set[Path] = set()
+            for service in services.values():
+                raw_path = service.get("path")
+                if not raw_path:
+                    continue
+                discovered_paths.add(Path(raw_path).resolve())
+            already_covered = self.project_dir in discovered_paths
             if not already_covered:
                 dep_indicators = ("package.json", "requirements.txt", "pyproject.toml")
                 root_has_deps = any(
                     (self.project_dir / f).exists() for f in dep_indicators
                 )
                 if root_has_deps:
                     root_analyzer = ServiceAnalyzer(self.project_dir, "root")
                     root_info = root_analyzer.analyze()
                     root_deps = root_info.get("dependency_locations", [])
                     if root_deps:
-                        services["root"] = root_info
+                        root_key = "root" if "root" not in services else "project_root"
+                        services[root_key] = root_info
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/backend/analysis/analyzers/project_analyzer_module.py` around lines 123
- 136, The check for already_covered should compare normalized/resolved paths
and the insertion of a synthetic root should not clobber a real service named
"root"; modify the logic that builds already_covered to use Path(...).resolve()
(or .absolute()) for each s.get("path") and self.project_dir.resolve(), and
before assigning services["root"] ensure you do not overwrite an existing key
(e.g., skip if "root" in services or choose a non-colliding key), and keep the
existing creation flow that uses ServiceAnalyzer(self.project_dir, "root") and
root_info.get("dependency_locations") to populate the synthetic root only when
safe.

@AndyMik90 AndyMik90 self-assigned this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Worktree dependency_locations empty for monorepo root — causes ~1GB node_modules duplication per worktree

3 participants