Skip to content

fix(codeflow): [CI/rebase] Terminal Sessions Memory Leak - #43

Open
nehraa wants to merge 1 commit into
mainfrom
claude-lane/task_1780281408931_2vxzzbu7l-20260602125813
Open

nehraa wants to merge 1 commit into
mainfrom
claude-lane/task_1780281408931_2vxzzbu7l-20260602125813

Conversation

@nehraa

@nehraa nehraa commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Original task: task_1780281408931_2vxzzbu7l
PR branch: claude-lane/task_1780281408931_2vxzzbu7l-20260602125813
CI failure: merge-conflict
Strategy: rebase

Hint: PR has merge conflicts with main. Run: git fetch origin && git rebase origin/main && git push --force-with-lease. The watcher's open_pr_for_task will detect the existing PR.

Failure log (last 3000 chars)

X Pull request #30 is not mergeable: the merge commit cannot be cleanly created.
To have the pull request merged after all the requirements have been met, add the `--auto` flag.

Workflow

  1. Read the failure log and the PR's diff (use git log origin/main..claude-lane/task_1780281408931_2vxzzbu7l-20260602125813)
  2. Apply the fix on top of the SAME branch (claude-lane/task_1780281408931_2vxzzbu7l-20260602125813) — the worktree is already set up by the dispatcher
  3. Commit with fix(ci): <one-line summary> (single line)
  4. The dispatcher will push your commit to the SAME branch and detect the existing PR
  5. The PR's CI re-runs automatically. Watcher picks it up on the next 5-min cycle.
  6. Report: files changed, commit SHA, what the fix was

Automated by DevPulse dispatcher.

Copilot AI lite review requested due to automatic review settings September 14, 2026 13:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 8fbe6ca1-ba44-491b-af12-ea9a4731c206


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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Bound terminal sessions to prevent resource leaks

🐞 Bug fix 🕐 Less than 10 minutes

Grey Divider

AI Description

• Caps retained terminal sessions at 50 to bound process and memory consumption.
• Purges stale sessions before enforcing the cap, preserving capacity for active sessions.
Diagram

graph TD
  A["Session Request"] --> B["Purge Sessions"] --> C{"Under Cap?"}
  C -->|Yes| D["Spawn Shell"] --> E["Session Registry"]
  C -->|No| F["Limit Error"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Configurable session cap
  • ➕ Supports different deployment sizes and resource budgets.
  • ➕ Allows operators to tighten limits without rebuilding. PR
  • ➖ Adds configuration validation and documentation requirements.
  • ➖ Misconfiguration could weaken the memory-leak safeguard.
2. Queue creation requests
  • ➕ Avoids rejecting users during temporary capacity spikes.
  • ➕ Can provide controlled admission as sessions expire.
  • ➖ Introduces queue lifecycle, timeout, and cancellation complexity.
  • ➖ Leaves requests pending with less predictable API behavior.

Recommendation: The fixed cap with immediate rejection is the best low-risk safeguard for this fix because it bounds resource use and preserves predictable API behavior. A configurable cap is worth considering later if deployment workloads vary significantly.

Files changed (1) +9 / -0

Bug fix (1) +9 / -0
terminal-sessions.tsEnforce a maximum retained terminal-session count +9/-0

Enforce a maximum retained terminal-session count

• Adds a hard limit of 50 retained terminal sessions. Creation first runs the existing purge process, then rejects new sessions with an actionable error when the registry remains at capacity.

packages/codeflow-store/src/shared/terminal-sessions.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36c1589d03

ℹ️ About Codex in GitHub

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

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

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

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

Comment on lines +249 to +253
// Reap idle/expired sessions first so the cap reflects live sessions only.
purgeIdleSessions();
if (sessions.size >= MAX_SESSIONS) {
throw new Error(
`Terminal session limit reached (${MAX_SESSIONS}). Close an existing session before opening a new one.`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reserve a slot before awaiting the working directory

When many requests create sessions simultaneously while the map has room, every call performs this size check and then suspends at await resolveInitialCwd before any session is inserted. Once those awaits complete, every call spawns and inserts a child, so a burst can exceed 50 by an arbitrary amount and bypass the resource cap. Reserve capacity before the await, or perform the check after it.

Useful? React with 👍 / 👎.

}): Promise<TerminalSessionSnapshot> => {
// Reap idle/expired sessions first so the cap reflects live sessions only.
purgeIdleSessions();
if (sessions.size >= MAX_SESSIONS) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude exited sessions from the concurrent-session cap

After 50 shells terminate naturally, their entries remain in sessions for the 60-second output grace period because purgeIdleSessions retains exited and error sessions until then. This sessions.size check still counts those non-running entries, so every new session creation fails during that period even when no terminal is concurrent. Count only running sessions for this limit or release capacity when a child exits.

Useful? React with 👍 / 👎.

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Session limits never reach users 🐞 Bug ≡ Correctness
Description
terminal-sessions.ts is absent from the package exports and has no production import; only its
colocated test imports it directly. The user-facing terminal panel updates local display state
instead, so the new guard is never executed through shipped terminal behavior.
Code

packages/codeflow-store/src/shared/terminal-sessions.ts[40]

+const MAX_SESSIONS = 50; // hard cap on concurrent sessions to bound resource use
Evidence
The package export map does not expose the shared terminal module, and repository-wide usage shows
only its test importing it. The sole user-facing terminal panel simulates command results in
component state rather than invoking this session implementation.

packages/codeflow-store/package.json[8-52]
packages/codeflow-store/src/shared/terminal-sessions.test.ts[2-11]
packages/Codeflow_master/src/components/panels/TerminalPanel.tsx[79-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new terminal-session limit is implemented in a module that is neither exported nor invoked by production code, so it cannot remediate shipped terminal behavior.

## Fix Focus Areas
- packages/codeflow-store/src/shared/terminal-sessions.ts[40-40]
- packages/codeflow-store/package.json[8-52]
- packages/Codeflow_master/src/components/panels/TerminalPanel.tsx[79-92]

## Recommended Fix
Apply the lifecycle and limit enforcement in the terminal implementation actually invoked by users, then expose and call that implementation through a supported package export and production route rather than importing test-only source directly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Concurrent requests bypass the cap 🐞 Bug ☼ Reliability
Description
createTerminalSession checks sessions.size without reserving a slot, then yields while awaiting
resolveInitialCwd before registering the new session. Concurrent calls can therefore all pass
below 50 and subsequently spawn and retain more than the intended maximum number of child processes.
Code

packages/codeflow-store/src/shared/terminal-sessions.ts[R250-251]

+  purgeIdleSessions();
+  if (sessions.size >= MAX_SESSIONS) {
Evidence
The limit check neither mutates the map nor records pending creation, line 257 then suspends on
filesystem access, and the first registration occurs only at line 304 after the shell has been
spawned. Multiple invocations can consequently observe the same map size before any invocation
inserts its session.

packages/codeflow-store/src/shared/terminal-sessions.ts[245-257]
packages/codeflow-store/src/shared/terminal-sessions.ts[259-266]
packages/codeflow-store/src/shared/terminal-sessions.ts[292-304]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The session limit check is separated from registration by asynchronous work, allowing concurrent creations to exceed the hard resource cap.

## Fix Focus Areas
- packages/codeflow-store/src/shared/terminal-sessions.ts[249-257]
- packages/codeflow-store/src/shared/terminal-sessions.ts[259-304]

## Recommended Fix
Atomically reserve a session slot before the first await, include reservations in the cap calculation, and release the reservation on every validation or spawn failure. Convert the reservation into the registered session only after successful initialization.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Idle sessions block new terminals 🐞 Bug ≡ Correctness
Description
createTerminalSession invokes purgeIdleSessions but immediately counts every remaining map
entry, while that purge only signals idle running sessions and deliberately leaves them mapped. At
50 idle sessions, creation still throws until child closure and the subsequent output-grace expiry,
even though all sessions have already been selected for reaping.
Code

packages/codeflow-store/src/shared/terminal-sessions.ts[R249-251]

+  // Reap idle/expired sessions first so the cap reflects live sessions only.
+  purgeIdleSessions();
+  if (sessions.size >= MAX_SESSIONS) {
Evidence
The purge implementation sends a termination signal and refreshes activity but does not delete an
idle running entry; non-running entries are deleted only after the grace cutoff. Existing tests
explicitly verify that idle sessions remain mapped after purge and require process closure plus a
later purge before deletion.

packages/codeflow-store/src/shared/terminal-sessions.ts[181-199]
packages/codeflow-store/src/shared/terminal-sessions.ts[202-221]
packages/codeflow-store/src/shared/terminal-sessions.test.ts[45-75]
packages/codeflow-store/src/shared/terminal-sessions.test.ts[77-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Sessions already selected for idle termination remain counted by the newly added capacity check and temporarily prevent replacement sessions from opening.

## Fix Focus Areas
- packages/codeflow-store/src/shared/terminal-sessions.ts[188-221]
- packages/codeflow-store/src/shared/terminal-sessions.ts[249-255]

## Recommended Fix
Base process capacity on running sessions that have not been selected for termination, or remove reaped entries from the capacity accounting immediately while retaining any required output snapshots separately. Keep pending creation reservations in the same capacity calculation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This is a runtime resource-management change that alters terminal-session creation and cleanup behavior; despite its small, localized diff, it warrants a careful single-pass review.

Grey Divider

Tip of the day
💡 Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

const EXPIRED_OUTPUT_GRACE_MS = 60 * 1000; // 60 s — after exit, retain snapshot for this long before deletion
const PURGE_INTERVAL_MS = 30 * 1000; // 30 s — background sweep cadence
const SIGKILL_TIMEOUT_MS = 5 * 1000; // 5 s — SIGKILL escalation if SIGTERM is ignored
const MAX_SESSIONS = 50; // hard cap on concurrent sessions to bound resource use

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Session limits never reach users 🐞 Bug ≡ Correctness

terminal-sessions.ts is absent from the package exports and has no production import; only its
colocated test imports it directly. The user-facing terminal panel updates local display state
instead, so the new guard is never executed through shipped terminal behavior.
Agent Prompt
## Issue description
The new terminal-session limit is implemented in a module that is neither exported nor invoked by production code, so it cannot remediate shipped terminal behavior.

## Fix Focus Areas
- packages/codeflow-store/src/shared/terminal-sessions.ts[40-40]
- packages/codeflow-store/package.json[8-52]
- packages/Codeflow_master/src/components/panels/TerminalPanel.tsx[79-92]

## Recommended Fix
Apply the lifecycle and limit enforcement in the terminal implementation actually invoked by users, then expose and call that implementation through a supported package export and production route rather than importing test-only source directly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +250 to +251
purgeIdleSessions();
if (sessions.size >= MAX_SESSIONS) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Concurrent requests bypass the cap 🐞 Bug ☼ Reliability

createTerminalSession checks sessions.size without reserving a slot, then yields while awaiting
resolveInitialCwd before registering the new session. Concurrent calls can therefore all pass
below 50 and subsequently spawn and retain more than the intended maximum number of child processes.
Agent Prompt
## Issue description
The session limit check is separated from registration by asynchronous work, allowing concurrent creations to exceed the hard resource cap.

## Fix Focus Areas
- packages/codeflow-store/src/shared/terminal-sessions.ts[249-257]
- packages/codeflow-store/src/shared/terminal-sessions.ts[259-304]

## Recommended Fix
Atomically reserve a session slot before the first await, include reservations in the cap calculation, and release the reservation on every validation or spawn failure. Convert the reservation into the registered session only after successful initialization.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +249 to +251
// Reap idle/expired sessions first so the cap reflects live sessions only.
purgeIdleSessions();
if (sessions.size >= MAX_SESSIONS) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Idle sessions block new terminals 🐞 Bug ≡ Correctness

createTerminalSession invokes purgeIdleSessions but immediately counts every remaining map
entry, while that purge only signals idle running sessions and deliberately leaves them mapped. At
50 idle sessions, creation still throws until child closure and the subsequent output-grace expiry,
even though all sessions have already been selected for reaping.
Agent Prompt
## Issue description
Sessions already selected for idle termination remain counted by the newly added capacity check and temporarily prevent replacement sessions from opening.

## Fix Focus Areas
- packages/codeflow-store/src/shared/terminal-sessions.ts[188-221]
- packages/codeflow-store/src/shared/terminal-sessions.ts[249-255]

## Recommended Fix
Base process capacity on running sessions that have not been selected for termination, or remove reaped entries from the capacity accounting immediately while retaining any required output snapshots separately. Keep pending creation reservations in the same capacity calculation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

2 participants