Skip to content

Fix/oom guards and gui improvements - #10

Merged
fathriAbanoub merged 4 commits into
mainfrom
fix/oom-guards-and-gui-improvements
Jul 4, 2026
Merged

Fix/oom guards and gui improvements#10
fathriAbanoub merged 4 commits into
mainfrom
fix/oom-guards-and-gui-improvements

Conversation

@fathriAbanoub

@fathriAbanoub fathriAbanoub commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

This PR addresses a critical system freeze bug and improves the GUI UX for exclude patterns.

Changes

🔒 Safety Guards (Critical Fix)

  • OOM/Freeze Prevention: Added DEFAULT_IGNORE_DIR_NAMES to automatically skip node_modules, .git, .next, dist, build, etc. during recursive traversal
  • Memory Cap: Added DEFAULT_MAX_TOTAL_BYTES (20MB) hard ceiling on total glued content size with pre-flight and post-read size verification
  • CLI Controls: Added --no-default-ignore and --max-size <MB> flags to override safety defaults when needed
  • Root Cause: Recursive glue on dependency directories without explicit --exclude patterns caused system swap-thrashing requiring hard restart

🎨 GUI Improvements

  • Chip-Based Excludes: Replaced comma-separated text entry with FlowBox chips + manual entry field
  • Browse Button: Added multi-select file picker (GTK 4.10+ FileDialog with FileChooserNative fallback)
  • Pattern Normalization: Strips ./ and trailing / for better deduplication
  • Heavy Directory Guard: Added _looks_heavy() heuristic to prevent file picker freezes on node_modules-heavy directories
  • Error Handling: Surface file picker errors via dialogs instead of silent failures
  • Debug Mode: Added CODEGLUER_DEBUG=1 environment variable for verbose logging

🐛 Bug Fixes

  • Fixed Pango.EllipsizeMode import (was incorrectly Gtk.EllipsizeMode)
  • Prevented GC during async dialog interaction with _active_picker reference
  • Added proper ACCEPT/OK response handling for file chooser dialogs

Migration Notes

No breaking changes. Default behavior is safer (auto-skips dependency directories, 20MB cap). Users can override with:

  • --no-default-ignore to disable auto-skip
  • --max-size 0 to disable memory cap
  • --max-size <MB> to set custom limit

Files Changed

  • codegluer/core.py - Safety guards, size checks, config fields
  • codegluer/cli.py - New CLI flags
  • codegluer/__init__.py - Export new constants
  • codegluer_gui.py - Chip UI, browse button, error handling

Summary by CodeRabbit

  • New Features

    • Added safer defaults for glueing content, including automatic skipping of common heavy folders and an optional size limit.
    • Expanded the GUI with chip-based exclude patterns and a multi-select file picker for adding exclusions more easily.
  • Bug Fixes

    • Improved folder selection so the app is less likely to freeze on large or build-heavy directories.
    • Added runtime safeguards to prevent running out of memory or exceeding content limits during glue operations.

- Add DEFAULT_IGNORE_DIR_NAMES to skip node_modules/.git/.next/etc during -r walk
- Add DEFAULT_MAX_TOTAL_BYTES (20MB) hard ceiling on total glued content size
- Add skip_default_ignore_dirs and max_total_bytes to GlueConfig
- Implement pre-flight file size check before reading to avoid loading huge files
- Add post-read encoded size verification to catch UTF-8 replacement bloat
- Thread safety guards through collect_files() and glue_files()
- Export new constants and config fields in __init__.py

Prevents system freeze/swap-thrash when recursing into dependency directories
without explicit --exclude patterns.

Fixes: system freeze requiring hard restart when gluing JS/build-heavy projects
- Add --no-default-ignore to disable auto-skip of node_modules/.git/etc
- Add --max-size <MB> to set custom content size limit (0 disables)
- Wire flags through to GlueConfig.skip_default_ignore_dirs and max_total_bytes
- Default behavior preserves safety guards (20MB cap, default ignores enabled)

Allows users to override safety defaults when intentionally gluing dependency
directories or large codebases.
- Implement FlowBox with removable chips for exclude patterns
- Add manual entry field that commits patterns on Enter
- Add Browse button with multi-select file picker (GTK 4.10+ FileDialog,
  FileChooserNative fallback for older versions)
- Implement _normalize_exclude_pattern() to strip ./ and trailing / for dedup
- Add _looks_heavy() heuristic to prevent file picker freeze on heavy directories
- Add _active_picker reference to prevent GC during async dialog interaction
- Fix Pango.EllipsizeMode import (was incorrectly Gtk.EllipsizeMode)
- Add CODEGLUER_DEBUG env var for verbose logging
- Implement _show_error_dialog() with GTK version-aware fallback
- Surface file picker errors instead of silent failures

Improves UX by making exclude patterns visible and removable, prevents common
mistakes with comma separation, and avoids GTK file chooser freezes on
node_modules-heavy directories.
@fathriAbanoub fathriAbanoub added bug Something isn't working enhancement New feature or request feature GUI UX labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@fathriAbanoub, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 74cde1c1-f8e3-4408-bb48-40c55a83c0c3

📥 Commits

Reviewing files that changed from the base of the PR and between 7ec76cb and 97d3b22.

📒 Files selected for processing (2)
  • codegluer/__init__.py
  • codegluer_gui.py
📝 Walkthrough

Walkthrough

This PR adds safety guards to prevent OOM/freeze during recursive glue operations: GlueConfig gains skip_default_ignore_dirs and max_total_bytes options enforced in collect_files/glue_files, wired through new CLI flags and package exports. The GUI is reworked with a chip-based exclude-pattern interface and heavy-directory detection to prevent file-picker freezes.

Changes

Core Safety Guards and CLI/Package Wiring

Layer / File(s) Summary
Core guard constants and enforcement
codegluer/core.py
Adds DEFAULT_IGNORE_DIR_NAMES and DEFAULT_MAX_TOTAL_BYTES constants, new GlueConfig fields, directory filtering during os.walk in collect_files, and cumulative byte-tracking with CodeGluerError enforcement in glue_files.
CLI flags and package exports
codegluer/cli.py, codegluer/__init__.py
Adds --no-default-ignore and --max-size CLI arguments that wire into GlueConfig, and exports the new constants from the package.

GUI Exclude-Chip Interface and Heavy-Directory Detection

Layer / File(s) Summary
Heavy-directory heuristic and chip theme CSS
codegluer_gui.py
Adds _HEAVY_DIR_HINTS/_looks_heavy heuristic and CHIP_CSS_BASE plus per-theme chip styling used by theme_css().
Window state and chip UI wiring
codegluer_gui.py
Adds exclude-chip state fields to CodeGluerWindow and builds the FlowBox chip container, manual entry, and Browse button.
Chip management and options collection
codegluer_gui.py
Implements _add_exclude_chip/_remove_exclude_chip, Enter-key chip commit, and updates _collect_opts()/Glue flow to derive excludes from chips.
File-picker flows for exclude chips
codegluer_gui.py
Implements Browse button handling with version-aware Gtk.FileDialog/Gtk.FileChooserNative flows and response handlers adding selected files as chips.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant GlueConfig
  participant collect_files
  participant glue_files

  CLI->>GlueConfig: set skip_default_ignore_dirs, max_total_bytes
  glue_files->>collect_files: pass skip_default_ignore_dirs
  collect_files->>collect_files: filter DEFAULT_IGNORE_DIR_NAMES during traversal
  glue_files->>glue_files: track total_bytes per file
  glue_files->>glue_files: raise CodeGluerError if limit exceeded
Loading
sequenceDiagram
  participant User
  participant BrowseButton
  participant FileDialog
  participant CodeGluerWindow

  User->>BrowseButton: click Browse
  BrowseButton->>CodeGluerWindow: _on_browse_clicked()
  CodeGluerWindow->>FileDialog: open dialog (with _looks_heavy guard)
  FileDialog-->>CodeGluerWindow: selected files
  CodeGluerWindow->>CodeGluerWindow: extract basenames, add exclude chips
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main themes of the PR: OOM/freeze guards and GUI improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/oom-guards-and-gui-improvements

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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
codegluer/__init__.py (1)

30-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: Ruff RUF022 flags __all__ as unsorted.

The list is intentionally grouped (version → constants → errors → config → functions), which conflicts with the isort-style ordering RUF022 wants. If this rule is enforced in CI, either apply the sort or add a # noqa: RUF022 to preserve the current grouping.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@codegluer/__init__.py` around lines 30 - 54, The __all__ export list is
intentionally grouped but violates Ruff RUF022’s sorted-order expectation.
Update the __all__ definition in the module-level export block to either match
the required sort order or add a targeted noqa for RUF022 if you want to
preserve the current grouping; use the existing __all__ symbol and the adjacent
import/export block as the reference point.

Source: Linters/SAST tools

codegluer_gui.py (1)

534-534: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Gate debug prints behind CODEGLUER_DEBUG.

The PR describes debug logging via CODEGLUER_DEBUG=1, but these print(..., file=sys.stderr) statements (throughout _add_exclude_chip, _on_browse_clicked, and the picker response handlers) are unconditional, so normal runs emit verbose stderr output. Route them through a small helper that checks the env var (or logging) to match the stated design.

♻️ Example gating helper
import os
_DEBUG = os.environ.get("CODEGLUER_DEBUG") == "1"

def _dbg(msg: str) -> None:
    if _DEBUG:
        print(msg, file=sys.stderr)

Also applies to: 571-571, 610-611, 684-684, 695-695, 751-751

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@codegluer_gui.py` at line 534, The debug prints in the GUI code are
unconditional, so normal runs still emit stderr noise instead of respecting
CODEGLUER_DEBUG. Update the related paths in codegluer_gui.py, especially
_add_exclude_chip, _on_browse_clicked, and the picker response handlers, to use
a shared debug helper (or logging) that checks CODEGLUER_DEBUG before printing.
Keep the existing debug messages but route them through that helper so only
debug-enabled runs produce output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@codegluer_gui.py`:
- Around line 591-592: The empty-state branch in the chip update logic hides
self.chip_flowbox after the last chip is removed, which can trigger the same
hidden→visible reflow issue called out in the add path. Update the chip
management code around the self.excludes check to keep self.chip_flowbox visible
even when there are no chips, or remove the earlier warning only if the reflow
behavior is no longer relevant. Use the existing chip add/remove flow in
codegluer_gui.py to locate the affected logic.

---

Nitpick comments:
In `@codegluer_gui.py`:
- Line 534: The debug prints in the GUI code are unconditional, so normal runs
still emit stderr noise instead of respecting CODEGLUER_DEBUG. Update the
related paths in codegluer_gui.py, especially _add_exclude_chip,
_on_browse_clicked, and the picker response handlers, to use a shared debug
helper (or logging) that checks CODEGLUER_DEBUG before printing. Keep the
existing debug messages but route them through that helper so only debug-enabled
runs produce output.

In `@codegluer/__init__.py`:
- Around line 30-54: The __all__ export list is intentionally grouped but
violates Ruff RUF022’s sorted-order expectation. Update the __all__ definition
in the module-level export block to either match the required sort order or add
a targeted noqa for RUF022 if you want to preserve the current grouping; use the
existing __all__ symbol and the adjacent import/export block as the reference
point.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d2fc6e5e-f97d-4369-a2d7-b1503430c11e

📥 Commits

Reviewing files that changed from the base of the PR and between 3b2e7f2 and 7ec76cb.

📒 Files selected for processing (4)
  • codegluer/__init__.py
  • codegluer/cli.py
  • codegluer/core.py
  • codegluer_gui.py

Comment thread codegluer_gui.py Outdated
…re chip colors

- Sort __all__ list alphabetically to satisfy Ruff RUF022
- Remove flowbox visibility toggle in _remove_exclude_chip to prevent
  chips from silently not appearing after first add (reflow issue)
- Route all debug output through debug_print() helper that respects
  CODEGLUER_DEBUG environment variable
- Move chip colors from shared CHIP_CSS_BASE to per-theme THEME_CSS blocks
  so chips match the active theme palette:
  * Light: dark blue #1e3a5f with white text
  * Dark: lighter blue #4a6fa5 with white text
  * Roselle: theme red #C62734 with #fff0f0 text
@fathriAbanoub
fathriAbanoub merged commit 92b042d into main Jul 4, 2026
1 check passed
@fathriAbanoub
fathriAbanoub deleted the fix/oom-guards-and-gui-improvements branch July 4, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request feature GUI UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant