Skip to content

feat: Implement UI/UX enhancements#20

Merged
MnemOnicE merged 2 commits into
mainfrom
jules-ui-enhancements-778402483987234527
Jun 9, 2026
Merged

feat: Implement UI/UX enhancements#20
MnemOnicE merged 2 commits into
mainfrom
jules-ui-enhancements-778402483987234527

Conversation

@MnemOnicE

Copy link
Copy Markdown
Owner
  • Added "View Stats & Mastery" feature that calculates command mastery from session history and visualizes it as a progress bar.
  • Implemented visual color-coded category badges for improved dashboard layout.
  • Refactored main dashboard format.

PR created automatically by Jules for task 778402483987234527 started by @MnemOnicE

Co-authored-by: MnemOnicE <170563909+MnemOnicE@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@MnemOnicE, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a0eeec13-27ed-4d2d-bfad-795adeebcfe1

📥 Commits

Reviewing files that changed from the base of the PR and between 93c7135 and 0c00dbd.

📒 Files selected for processing (3)
  • commando/core/audit.py
  • commando/ui/dashboard.py
  • commando/utils/io.py
📝 Walkthrough

Walkthrough

This PR enhances the terminal dashboard with command mastery tracking and category badge formatting. A new view_stats_and_mastery() function displays sorted command mastery scores with color-coded 5-segment progress bars. Utility functions get_category_color() and format_badge() provide consistent colorized category labels throughout the UI.

Changes

Stats & Mastery Dashboard with Badge Formatting

Layer / File(s) Summary
Category badge utility functions
commando/utils/io.py
Introduces get_category_color() to map category strings to ANSI colors via substring matching (file/disk, network/web, process/system, navig/search, text/edit) and format_badge() to render colorized [ ... ] badges.
View Stats & Mastery feature implementation
commando/ui/dashboard.py
Imports badge utilities and updates dashboard header styling; implements view_stats_and_mastery() to read session_history, sort commands by mastery score (descending) and name, clamp scores to 0–5 range, render 5-segment colored progress bars (█/░), and pause for user input; adds menu option [9] View Stats & Mastery and wires routing in main_loop().
Apply badge formatting to category displays
commando/ui/dashboard.py
Updates explore_category(), manage_imports(), and review_pending_imports() to render category labels via colorized badges instead of raw bracketed text.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

📊 Dashboard drops the dope stats flow,
Mastery bars in colors glow,
Badges format category clean,
Finest terminal scene ever seen! 🎯

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: Implement UI/UX enhancements' is vague and overly broad, using generic phrasing that doesn't convey specific information about the primary changes. Consider a more specific title like 'feat: Add mastery dashboard and color-coded category badges' to clearly highlight the main features introduced.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description directly addresses the changeset by outlining the three main additions: mastery feature, category badges, and dashboard refactoring.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jules-ui-enhancements-778402483987234527

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a 'View Stats & Mastery' feature to the dashboard, allowing users to view their command mastery with colored progress bars. It also adds category color-coding and badges across several dashboard views. The review feedback highlights several robustness improvements, including defensive handling of non-string or null category values, safe parsing of mastery scores to prevent type errors during sorting, and fixing an ANSI color reset issue in the category header.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread commando/ui/dashboard.py
Comment on lines +81 to +90
# Sort history by mastery level (score) descending, then by name
sorted_history = sorted(session_history.items(), key=lambda x: (-x[1], x[0]))

print(f"\n{CYAN}{BOLD}Command Mastery:{RESET}")
for cmd, score in sorted_history:
# Mastery goes up to 5
score = min(5, max(0, score))
filled = "█" * score
empty = "░" * (5 - score)
bar = f"{filled}{empty}"

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.

medium

If session_history contains non-integer values (e.g., if the history file was modified or corrupted), sorting with key=lambda x: (-x[1], x[0]) will raise a TypeError due to the unary negation operator - on a non-numeric type. Additionally, multiplying strings by a non-integer score will raise a TypeError. We should safely parse the score to an integer.

    # Sort history by mastery level (score) descending, then by name
    def get_sort_key(item):
        cmd, score = item
        try:
            return -int(score), cmd
        except (TypeError, ValueError):
            return 0, cmd

    sorted_history = sorted(session_history.items(), key=get_sort_key)

    print(f'\n{CYAN}{BOLD}Command Mastery:{RESET}')
    for cmd, raw_score in sorted_history:
        try:
            score = int(raw_score)
        except (TypeError, ValueError):
            score = 0
        # Mastery goes up to 5
        score = min(5, max(0, score))
        filled = '█' * score
        empty = '░' * (5 - score)
        bar = f'{filled}{empty}'

Comment thread commando/ui/dashboard.py
selected_cat = categories[idx]
clear_screen()
print(f"{YELLOW}--- {selected_cat} Commands ---{RESET}\n")
print(f"{YELLOW}--- {format_badge(selected_cat)} Commands ---{RESET}\n")

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.

medium

The format_badge function ends with a {RESET} ANSI escape sequence. This will reset the terminal color formatting, causing the subsequent text ' Commands ---' to lose its {YELLOW} color and render in the default terminal color. To maintain the yellow color for the entire header, re-apply {YELLOW} immediately after the badge.

Suggested change
print(f"{YELLOW}--- {format_badge(selected_cat)} Commands ---{RESET}\n")
print(f'{YELLOW}--- {format_badge(selected_cat)}{YELLOW} Commands ---{RESET}\n')

Comment thread commando/utils/io.py
Comment on lines +86 to +87
def get_category_color(category):
cat_lower = category.lower()

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.

medium

If category is None or not a string, calling category.lower() will raise an AttributeError. We should add a defensive check to handle non-string or None values gracefully.

def get_category_color(category):
    if not isinstance(category, str):
        return BOLD
    cat_lower = category.lower()

Comment thread commando/utils/io.py
Comment on lines +101 to +103
def format_badge(category):
color = get_category_color(category)
return f"[{color}{category}{RESET}]"

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.

medium

If category is None, format_badge will display [None]. We should handle None or empty values by defaulting to a fallback string like 'Custom'.

Suggested change
def format_badge(category):
color = get_category_color(category)
return f"[{color}{category}{RESET}]"
def format_badge(category):
category_str = str(category) if category else 'Custom'
color = get_category_color(category_str)
return f'[{color}{category_str}{RESET}]'

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

Actionable comments posted: 3

🤖 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 `@commando/ui/dashboard.py`:
- Around line 85-100: In the for-loop over sorted_history in
commando/ui/dashboard.py, avoid reusing the loop variable score for the clamped
value: introduce a new name like display_score (or clamped_score) for the result
of min(5, max(0, score)) and use display_score for building the bar and color
logic; also replace the chained elifs that set bar_color with independent if
statements (i.e., if display_score >= 4: set GREEN; if display_score >= 2: set
YELLOW; if display_score < 2: set RED) to match the early-return style used
elsewhere (refer to the loop that constructs bar and the variables
filled/empty/bar for locating the code).
- Around line 34-35: The "Recent" list uses session_history.keys() which only
reflects insertion order, not last-activity order; update the code that
records/updates an entry in session_history so it moves the key to the end on
each use (e.g., when updating a command's score/populate, either pop and
reassign session_history[cmd] = value or switch session_history to an
OrderedDict and call move_to_end(cmd)). Ensure this change affects the same
mapping referenced by the recent variable so that recent =
list(session_history.keys())[-5:] shows truly most-recently-used entries.

In `@commando/utils/io.py`:
- Around line 86-99: The get_category_color function currently uses an elif
cascade even though every branch returns; refactor it to use independent if
statements instead of elif so each condition checks and returns immediately
(e.g., in get_category_color replace the elifs with plain ifs while keeping the
same order and returns for the CYAN, MAGENTA, RED, GREEN, YELLOW cases and the
final return BOLD); ensure you still call category.lower() once and preserve the
same constants (CYAN, MAGENTA, RED, GREEN, YELLOW, BOLD) and behavior.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c97c396d-da53-42a9-8ff3-c2e3b4e6a813

📥 Commits

Reviewing files that changed from the base of the PR and between 6252ce6 and 93c7135.

📒 Files selected for processing (2)
  • commando/ui/dashboard.py
  • commando/utils/io.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{py,toml,md,txt,yaml,yml,json}

📄 CodeRabbit inference engine (AGENTS.md)

Ensure the application is identified as cli-commando (or commando), not legacy names like 'bashlearn'

Files:

  • commando/utils/io.py
  • commando/ui/dashboard.py
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Map internal state and telemetry files (history, pending, custom) to ~/.commando state directory
When processing batches of operations, use concurrent.futures.ThreadPoolExecutor for I/O-bound execution with explicit throttling
Enforce a strict max_workers=4 or 5 when using ThreadPoolExecutor to balance UI fluidity with thermal and memory constraints on constrained hardware
Never blindly invoke [cmd, '--help'] on newly discovered binaries without verification; use static analysis instead
Implement the Containment Protocol for static analysis: (1) Read first 4 bytes for ELF magic number (\x7fELF), (2) If ELF, use strings to extract usage motifs, (3) If shebang (#!), parse as raw text, (4) Only run known-safe OS queries like whatis or help
For kinetic audit mode, gracefully degrade when ptrace is denied: catch exceptions and fall back to static library analysis using ldd
Tag binaries linked to libssl or libcurl as [Network Mutator] during static library analysis fallback
Tag binaries with heavy libc usage as [File Reader/Writer] during static library analysis fallback
When --json flag is utilized, output a JSON object adhering strictly to the schema with fields: command, status, kinetic_tags, audit_method, without polluting output with human-readable UI strings
Ensure JSON headless output schema strictly adheres to: command (string), status (string), kinetic_tags (array of strings), audit_method (string)

Files:

  • commando/utils/io.py
  • commando/ui/dashboard.py
🪛 Ruff (0.15.15)
commando/utils/io.py

[warning] 90-90: Unnecessary elif after return statement

Remove unnecessary elif

(RET505)

commando/ui/dashboard.py

[warning] 87-87: for loop variable score overwritten by assignment target

(PLW2901)

🔇 Additional comments (6)
commando/utils/io.py (1)

101-103: LGTM!

commando/ui/dashboard.py (5)

22-23: LGTM!


29-31: LGTM!


48-50: LGTM!


162-162: LGTM!

Also applies to: 187-188, 302-302


448-450: LGTM!

Comment thread commando/ui/dashboard.py
Comment thread commando/ui/dashboard.py
Comment thread commando/utils/io.py Outdated
@MnemOnicE

Copy link
Copy Markdown
Owner Author

@jules 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 @commando/ui/dashboard.py:

  • Around line 85-100: In the for-loop over sorted_history in
    commando/ui/dashboard.py, avoid reusing the loop variable score for the clamped
    value: introduce a new name like display_score (or clamped_score) for the result
    of min(5, max(0, score)) and use display_score for building the bar and color
    logic; also replace the chained elifs that set bar_color with independent if
    statements (i.e., if display_score >= 4: set GREEN; if display_score >= 2: set
    YELLOW; if display_score < 2: set RED) to match the early-return style used
    elsewhere (refer to the loop that constructs bar and the variables
    filled/empty/bar for locating the code).
  • Around line 34-35: The "Recent" list uses session_history.keys() which only
    reflects insertion order, not last-activity order; update the code that
    records/updates an entry in session_history so it moves the key to the end on
    each use (e.g., when updating a command's score/populate, either pop and
    reassign session_history[cmd] = value or switch session_history to an
    OrderedDict and call move_to_end(cmd)). Ensure this change affects the same
    mapping referenced by the recent variable so that recent =
    list(session_history.keys())[-5:] shows truly most-recently-used entries.

In @commando/utils/io.py:

  • Around line 86-99: The get_category_color function currently uses an elif
    cascade even though every branch returns; refactor it to use independent if
    statements instead of elif so each condition checks and returns immediately
    (e.g., in get_category_color replace the elifs with plain ifs while keeping the
    same order and returns for the CYAN, MAGENTA, RED, GREEN, YELLOW cases and the
    final return BOLD); ensure you still call category.lower() once and preserve the
    same constants (CYAN, MAGENTA, RED, GREEN, YELLOW, BOLD) and behavior.

@google-labs-jules

Copy link
Copy Markdown
Contributor

@jules 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 @commando/ui/dashboard.py:

  • Around line 85-100: In the for-loop over sorted_history in
    commando/ui/dashboard.py, avoid reusing the loop variable score for the clamped
    value: introduce a new name like display_score (or clamped_score) for the result
    of min(5, max(0, score)) and use display_score for building the bar and color
    logic; also replace the chained elifs that set bar_color with independent if
    statements (i.e., if display_score >= 4: set GREEN; if display_score >= 2: set
    YELLOW; if display_score < 2: set RED) to match the early-return style used
    elsewhere (refer to the loop that constructs bar and the variables
    filled/empty/bar for locating the code).
  • Around line 34-35: The "Recent" list uses session_history.keys() which only
    reflects insertion order, not last-activity order; update the code that
    records/updates an entry in session_history so it moves the key to the end on
    each use (e.g., when updating a command's score/populate, either pop and
    reassign session_history[cmd] = value or switch session_history to an
    OrderedDict and call move_to_end(cmd)). Ensure this change affects the same
    mapping referenced by the recent variable so that recent =
    list(session_history.keys())[-5:] shows truly most-recently-used entries.

In @commando/utils/io.py:

  • Around line 86-99: The get_category_color function currently uses an elif
    cascade even though every branch returns; refactor it to use independent if
    statements instead of elif so each condition checks and returns immediately
    (e.g., in get_category_color replace the elifs with plain ifs while keeping the
    same order and returns for the CYAN, MAGENTA, RED, GREEN, YELLOW cases and the
    final return BOLD); ensure you still call category.lower() once and preserve the
    same constants (CYAN, MAGENTA, RED, GREEN, YELLOW, BOLD) and behavior.

I have implemented the requested changes:

  1. Changed the dashboard variable for mastery display from score to display_score, and refactored the chained elif statements to independent if statements.
  2. Addressed the Recent list issue by updating session_history insertion to pop and reinsert elements (moving them to the end of the list) to accurately reflect the most recent activity.
  3. Modified get_category_color to use independent if statements instead of elif cascades.

- Refactored `get_category_color` to use independent if statements
- Updated mastery display loop to use `display_score` instead of redefining `score`, and replaced elif chains with ifs
- Updated `session_history` dictionary inserts to pop the key first so it's moved to the end, correctly tracking the most recently used items.

Co-authored-by: MnemOnicE <170563909+MnemOnicE@users.noreply.github.com>
@MnemOnicE MnemOnicE merged commit c2ae65e into main Jun 9, 2026
7 checks passed
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