Skip to content

fix: enforce concurrency limit for manual feature execution#622

Closed
ScotTFO wants to merge 2 commits intoAutoMaker-Org:mainfrom
ScotTFO:fix/manual-run-concurrency-limit
Closed

fix: enforce concurrency limit for manual feature execution#622
ScotTFO wants to merge 2 commits intoAutoMaker-Org:mainfrom
ScotTFO:fix/manual-run-concurrency-limit

Conversation

@ScotTFO
Copy link
Contributor

@ScotTFO ScotTFO commented Jan 20, 2026

Summary

  • Add concurrency check at the start of executeFeature() method
  • Manual "Run" clicks are now subject to the same maxConcurrency limit as auto-mode
  • Prevents users from exceeding configured agent limit

Problem

The maxConcurrency check only ran in the auto-mode loop (auto-mode-service.ts:407), but run-feature.ts calls executeFeature() directly with no capacity check. This allowed users to bypass the limit by manually clicking "Run" on features, potentially running 8+ agents when max was set to 5.

Solution

Add concurrency check at the start of executeFeature() for non-auto-mode executions:

if (!isAutoMode) {
  const maxConcurrency = this.config?.maxConcurrency || 3;
  if (this.runningFeatures.size >= maxConcurrency) {
    throw new Error(`Cannot start: ${this.runningFeatures.size}/${maxConcurrency} agents already running`);
  }
}

Auto-mode is skipped since it already has its own check in the auto-loop.

Test plan

  • Set max concurrent agents to 3
  • Start 3 features manually
  • Try to start a 4th feature manually - should get error message
  • Start auto-mode with 3 running - should wait, not exceed limit

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Implemented concurrency limits for manual runs, restricting the maximum number of simultaneously active agents (default: 3, configurable). Auto-mode runs remain unaffected by this limit.

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

Add concurrency check at the start of executeFeature() so manual "Run"
clicks are subject to the same maxConcurrency limit as auto-mode. This
prevents users from exceeding the configured limit by clicking Run
multiple times.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ScotTFO, 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 a critical issue where manual feature executions could bypass the maxConcurrency limit, potentially leading to an overload of agents beyond the system's configured capacity. By integrating the concurrency check directly into the executeFeature() method for non-auto-mode calls, the system now consistently enforces the agent limit, ensuring stability and resource management regardless of how features are initiated.

Highlights

  • Concurrency Enforcement: A concurrency check has been added to the executeFeature() method to ensure manual feature executions respect the configured maxConcurrency limit.
  • Manual Execution Limit: Manual 'Run' actions for features are now subject to the same maxConcurrency limit that was previously only applied to auto-mode executions.
  • Agent Limit Prevention: This change prevents users from inadvertently or intentionally exceeding the configured maximum number of concurrent agents.

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

Using Gemini Code Assist

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

Invoking Gemini

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

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

Customization

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

Limitations & Feedback

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

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

Footnotes

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

A concurrency control mechanism was added to the auto-mode service's executeFeature function to limit non-auto-mode runs to a maximum of 3 concurrent agents (configurable), while auto-mode runs remain unaffected.

Changes

Cohort / File(s) Summary
Concurrency Control
apps/server/src/services/auto-mode-service.ts
Added concurrency limit check for manual (non-auto-mode) runs; enforces maximum concurrent agents and throws error if exceeded; auto-mode exempted from this restriction

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A gate to control the rushing stream,
Three agents max—a balanced scheme!
Auto-mode runs wild and free,
While manual runs wait patiently. ✨

🚥 Pre-merge checks | ✅ 3
✅ 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 and concisely summarizes the main change: enforcing a concurrency limit for manual feature execution, which is the core intent of this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@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 correctly identifies and addresses a concurrency limit bypass for manual feature executions. The approach of adding a check at the beginning of executeFeature is sound. My review includes a suggestion to make this fix more robust by ensuring it respects the user's configured concurrency limit from settings, rather than falling back to a hardcoded value. This will make the behavior consistent and fully deliver on the goal of enforcing the configured limit.

// Check global concurrency limit for manual executions
// (Auto-mode has its own check in the auto-loop, so skip for isAutoMode)
if (!isAutoMode) {
const maxConcurrency = this.config?.maxConcurrency || 3;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This is a good fix for enforcing a concurrency limit on manual runs. However, it currently falls back to a hardcoded limit of 3, as this.config is typically not set in that context. This might not reflect the user's actual configured maxConcurrency setting.

To ensure the user's configured limit is always respected, we should fetch the global settings as a fallback. Additionally, we can use the DEFAULT_GLOBAL_SETTINGS.maxConcurrency constant for the ultimate fallback value to avoid magic numbers.

You'll need to add DEFAULT_GLOBAL_SETTINGS to your imports from @automaker/types.

      const globalSettings = await this.settingsService?.getGlobalSettings();
      const maxConcurrency =
        this.config?.maxConcurrency ??
        globalSettings?.maxConcurrency ??
        DEFAULT_GLOBAL_SETTINGS.maxConcurrency;

Apply PR review feedback: use settingsService.getGlobalSettings() as
fallback for maxConcurrency instead of hardcoded value. Uses
DEFAULT_GLOBAL_SETTINGS.maxConcurrency as ultimate fallback to avoid
magic numbers and ensure user's configured limit is always respected.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ScotTFO ScotTFO marked this pull request as draft January 20, 2026 05:19
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

🤖 Fix all issues with AI agents
In `@apps/server/src/services/auto-mode-service.ts`:
- Around line 500-506: When handling manual executions in executeFeature (where
isAutoMode is false) the code falls back to this.config which is only set by
startAutoLoop; instead fetch maxConcurrency from the injected SettingsService by
calling settingsService.getGlobalSettings() and reading its maxConcurrency when
this.config is undefined or isAutoMode is false, then use that value for the
runningFeatures.size check (preserve the existing error message and logic).
Update the branch around isAutoMode in executeFeature to prefer
this.config?.maxConcurrency when set, otherwise use
settingsService.getGlobalSettings().maxConcurrency, and ensure the existing
throw still triggers when runningFeatures.size >= resolved maxConcurrency.

Comment on lines 500 to 506
if (!isAutoMode) {
const maxConcurrency = this.config?.maxConcurrency || 3;
if (this.runningFeatures.size >= maxConcurrency) {
throw new Error(
`Cannot start: ${this.runningFeatures.size}/${maxConcurrency} agents already running`
);
}
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

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and examine its key sections
git ls-files | grep -i auto-mode-service

Repository: AutoMaker-Org/automaker

Length of output: 314


🏁 Script executed:

# Search for maxConcurrency and config-related patterns
rg -n --type=ts 'maxConcurrency' -B 2 -A 2

Repository: AutoMaker-Org/automaker

Length of output: 43754


🏁 Script executed:

# Search for this.config assignments and references
rg -n --type=ts 'this\.config\s*=' -B 1 -A 2

Repository: AutoMaker-Org/automaker

Length of output: 1654


🏁 Script executed:

# Look for AutoModeService class definition and constructor
rg -n --type=ts 'class AutoModeService|constructor\s*\(' -A 5 apps/server/src/services/auto-mode-service.ts

Repository: AutoMaker-Org/automaker

Length of output: 536


🏁 Script executed:

# Check the imports and config types
head -30 apps/server/src/services/auto-mode-service.ts

Repository: AutoMaker-Org/automaker

Length of output: 902


🏁 Script executed:

# Search for executeFeature calls to understand manual execution paths
rg -n 'executeFeature' --type=ts -B 2 -A 1 apps/server/src/

Repository: AutoMaker-Org/automaker

Length of output: 3679


🏁 Script executed:

# Check the SettingsService to see how maxConcurrency is accessed
rg -n 'settingsService' --type=ts apps/server/src/services/auto-mode-service.ts | head -20

Repository: AutoMaker-Org/automaker

Length of output: 1491


🏁 Script executed:

# Get the full executeFeature method signature and context
sed -n '480,530p' apps/server/src/services/auto-mode-service.ts

Repository: AutoMaker-Org/automaker

Length of output: 1663


🏁 Script executed:

# Check if this.config is initialized anywhere else besides startAutoLoop
rg -n 'this\.config\s*=' apps/server/src/services/auto-mode-service.ts

Repository: AutoMaker-Org/automaker

Length of output: 90


🏁 Script executed:

# Verify SettingsService has getGlobalSettings method
rg -n 'getGlobalSettings' --type=ts apps/server/src/services/settings-service.ts | head -5

Repository: AutoMaker-Org/automaker

Length of output: 341


🏁 Script executed:

# Check the full route file to confirm manual execution path
cat apps/server/src/routes/auto-mode/routes/run-feature.ts

Repository: AutoMaker-Org/automaker

Length of output: 1611


Manual executions ignore user-configured maxConcurrency; use settings instead.

When executeFeature is called manually (before auto-mode starts or via the run-feature route), this.config is undefined because it's only initialized in startAutoLoop. This causes the check at line 500–506 to default to 3, bypassing any user-configured limit from GlobalSettings.

The SettingsService is injected into AutoModeService (constructor line 279–281) and has a getGlobalSettings() method that returns the configured maxConcurrency. Use it for manual executions: retrieve maxConcurrency from settingsService.getGlobalSettings() when isAutoMode is false.

🤖 Prompt for AI Agents
In `@apps/server/src/services/auto-mode-service.ts` around lines 500 - 506, When
handling manual executions in executeFeature (where isAutoMode is false) the
code falls back to this.config which is only set by startAutoLoop; instead fetch
maxConcurrency from the injected SettingsService by calling
settingsService.getGlobalSettings() and reading its maxConcurrency when
this.config is undefined or isAutoMode is false, then use that value for the
runningFeatures.size check (preserve the existing error message and logic).
Update the branch around isAutoMode in executeFeature to prefer
this.config?.maxConcurrency when set, otherwise use
settingsService.getGlobalSettings().maxConcurrency, and ensure the existing
throw still triggers when runningFeatures.size >= resolved maxConcurrency.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant