Skip to content

Tier TUI event display by verbosity#43

Merged
m4r1k merged 9 commits intomainfrom
feat/tui-event-verbosity
Apr 30, 2026
Merged

Tier TUI event display by verbosity#43
m4r1k merged 9 commits intomainfrom
feat/tui-event-verbosity

Conversation

@m4r1k
Copy link
Copy Markdown
Owner

@m4r1k m4r1k commented Apr 30, 2026

Summary

  • Change monitor event verbosity to Power-only by default, Diagnostics with -v / first <V>, and Lifecycle with -vv / second <V>.
  • Group live TUI events by tier while keeping --once flat and timestamp-sorted.
  • Preserve event caps in Power, Diagnostics, Lifecycle order and update unit/E2E coverage.

Verification

  • bash -n tests/e2e/groups/stats.sh
  • pytest tests/test_tui.py tests/test_cli.py (134 passed)
  • pytest (990 passed)
  • Local agent-skills:code-reviewer pass: APPROVE

Summary by CodeRabbit

  • New Features

    • Event display now uses tier-based presentation: Power events show by default, Diagnostics via -v, and Lifecycle via -vv.
    • Live TUI events are grouped by tier; --once output remains timestamp-sorted.
    • Event cap now preserves higher tiers first.
  • Documentation

    • Updated changelog with 5.3.0-rc0 release notes describing new event tier behavior.
    • Refined testing documentation for event tier filtering and TUI grouping.

m4r1k and others added 4 commits May 1, 2026 00:15
Default monitor event output now shows only Power Events so outage transitions are not buried by daemon noise. Count-style verbosity exposes Diagnostics with -v / the first live <V> press and Lifecycle with -vv / the second <V> press.

The live TUI groups enabled tiers as Power Events, Diagnostics, then Lifecycle, while --once remains a flat timestamp-sorted list for scripts. Event caps preserve Power first, fill with Diagnostics second, and only use Lifecycle rows last; crash/restart classifier rows remain Diagnostics.

This also bumps the code version to 5.3.0-rc0, adds a light 5.3.0 changelog entry, and updates tests/docs for the new event-tier behavior.

Co-Authored-By: opencode <noreply@opencode.ai>
Align the Stats E2E event assertions with the new 5.3.0 display contract: default output shows Power Events only, -v adds Diagnostics, and -vv adds Lifecycle.

Seed a Power row alongside the existing Diagnostic marker so the default path proves it still surfaces operator-critical events while hiding diagnostics and lifecycle noise.

Co-Authored-By: opencode <noreply@opencode.ai>
Count live TUI section headers inside the grouped event cap so preserved Power Events remain in the rendered viewport when Diagnostics or Lifecycle sections are enabled.

Also seed E2E event rows in the past to avoid races with the events query end timestamp, and cover the grouped-cap behavior with a unit test.

Co-Authored-By: opencode <noreply@opencode.ai>
Keep emitted safety-critical bypass and overload event names in the default Power Events tier so operators see active protection-loss conditions without increasing verbosity.

Also keep the newest rows when a grouped section is truncated by live-panel header accounting, preserving the previous most-recent-within-tier cap behavior.

Co-Authored-By: opencode <noreply@opencode.ai>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Important

Review skipped

Auto reviews are disabled on this repository. 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.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3f62672d-f311-405a-9a1b-26dcd6b801fb

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change implements a three-tier event display system for version 5.3.0-rc0, transitioning from a boolean priority model to count-based verbosity levels (Power events at default, Diagnostics with -v, Lifecycle with -vv). The CLI, TUI rendering logic, event filtering, and tests are updated accordingly to support tier-based event display, grouping, and cap preservation.

Changes

Cohort / File(s) Summary
Version Update
src/eneru/version.py
Bumps version from 5.2.2 to 5.3.0-rc0.
CLI Verbosity
src/eneru/cli.py
Converts --verbose/-v flag from boolean to counted verbosity level; updates help text to describe Power, Diagnostics, and Lifecycle event categories at each level.
TUI Event Tier System
src/eneru/tui.py
Refactors event filtering from boolean priority_only to numeric verbosity (0–2); updates query_events_for_display() with tier-based filtering, optional grouping, and revised cap-trimming priority; adds events_db_available() helper; extends Power event types; updates render_logs_panel(), run_tui(), and run_once() signatures to accept verbosity level instead of bool.
Changelog & Testing Docs
docs/changelog.md, docs/testing.md
Documents new tier-based event display semantics and TUI grouping behavior; updates test-area description to mention "event tier filtering."
Unit Tests
tests/test_cli.py, tests/test_tui.py
Converts verbosity assertions from boolean to integer counts; adds test for -vv flag; refactors event-filtering tests to validate three tiers; adds grouped-output tests; updates empty-message and placeholder text checks.
E2E Test
tests/e2e/groups/stats.sh
Seeds both Power (ON_BATTERY) and Lifecycle (DAEMON_START) events; updates assertions to validate tier-specific output at default, -v, and -vv levels.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant TUI
    participant EventQuery as Event Filter<br/>(query_events_for_display)
    participant Database as SQLite<br/>Events DB
    participant Renderer as Log Panel<br/>Renderer

    User->>CLI: eneru monitor [-v] [-vv]
    CLI->>CLI: Parse verbosity level (0/1/2)
    CLI->>TUI: run_tui(verbose=level) or run_once(verbose=level)
    TUI->>EventQuery: query_events_for_display(verbosity=level)
    EventQuery->>Database: Fetch all events from events table
    Database-->>EventQuery: Event records
    EventQuery->>EventQuery: Filter by verbosity tier<br/>(Power always,<br/>Diagnostics if ≥1,<br/>Lifecycle if ≥2)
    EventQuery->>EventQuery: Trim cap: preserve Power > Diagnostics > Lifecycle
    EventQuery->>EventQuery: Optionally group by tier
    EventQuery-->>TUI: Filtered event list
    TUI->>Renderer: render_logs_panel(..., verbosity=level)
    Renderer->>Renderer: Render tier headers (bold)
    Renderer->>Renderer: Display events grouped by tier
    Renderer->>Renderer: Update footer hint with tier level
    Renderer-->>User: Display filtered events in TUI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit's delight with tiers so bright,
Power, Diagnostics, and Lifecycle in sight!
Press -v for more, -vv for all,
Event verbosity answers the call!
Grouped by tier, capped with care,
Higher tiers preserved everywhere! 🌟

🚥 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 'Tier TUI event display by verbosity' clearly and concisely describes the main change: restructuring event display in the TUI interface based on verbosity levels.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.
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 feat/tui-event-verbosity

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.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

❌ Patch coverage is 82.85714% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.54%. Comparing base (93a7fef) to head (21fa5f6).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
src/eneru/tui.py 82.52% 13 Missing and 5 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #43      +/-   ##
==========================================
+ Coverage   79.31%   79.54%   +0.23%     
==========================================
  Files          25       25              
  Lines        4530     4616      +86     
  Branches      843      861      +18     
==========================================
+ Hits         3593     3672      +79     
- Misses        736      738       +2     
- Partials      201      206       +5     
Files with missing lines Coverage Δ
src/eneru/cli.py 71.62% <100.00%> (ø)
src/eneru/version.py 100.00% <100.00%> (ø)
src/eneru/tui.py 65.79% <82.52%> (+2.29%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Update the monitor CLI reference and TUI events documentation for the new Power, Diagnostics, and Lifecycle event verbosity model.

Clarify that live TUI grouping is tiered while --once stays flat and timestamp-sorted, and that length caps preserve Power before Diagnostics before Lifecycle.

Co-Authored-By: opencode <noreply@opencode.ai>
@m4r1k
Copy link
Copy Markdown
Owner Author

m4r1k commented Apr 30, 2026

@coderabbitai full review

@m4r1k
Copy link
Copy Markdown
Owner Author

m4r1k commented Apr 30, 2026

@cubic-dev-ai review this pull request

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Full review triggered.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Apr 30, 2026

@cubic-dev-ai review this pull request

@m4r1k I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/testing.md (1)

73-85: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Refresh the test-count sections on this page too.

This PR adds/updates coverage, but this edit only updates the area description. Please also refresh the pyramid/table counts and per-file breakdown here so the testing doc stays in sync with the current suite.

As per coding guidelines, "When adding or removing tests, update docs/testing.md with test counts in pyramid/table, per-file breakdown, and E2E test case table".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/testing.md` around lines 73 - 85, Update docs/testing.md to refresh the
test-counts and breakdowns to match the changes: update the pyramid/table
summary counts, per-file test-count breakdown, and the E2E test case table to
include the newly added/updated coverage described in the "Test areas" section
(e.g., Config loading and validation, Monitor state machine, Shutdown mixins,
Multi-UPS coordinator, Redundancy runtime, Health monitoring, Notifications,
Statistics and TUI, Packaging). Ensure each referenced area has its
corresponding numeric test counts and any per-file entries updated to reflect
added or removed tests so the overall totals and tables remain consistent with
the current test suite.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/eneru/tui.py`:
- Around line 499-514: The current legacy shim maps priority_only=True to
EVENTS_VERBOSITY_POWER which incorrectly drops lifecycle events; change the
mapping so that when priority_only is True you set verbosity to PRIORITY_EVENTS
(the legacy "priority rows" set: power + lifecycle), otherwise keep the existing
mapping to EVENTS_VERBOSITY_ALL; then pass that value through _events_verbosity
as before (update the conditional handling around priority_only in the function
where priority_only, _events_verbosity, EVENTS_VERBOSITY_POWER,
EVENTS_VERBOSITY_ALL, and PRIORITY_EVENTS are referenced).

In `@tests/test_tui.py`:
- Around line 1705-1706: The comprehensions in tests/test_tui.py use the
ambiguous variable name "l" (e.g., in the expression that builds lines = [l for
l in out.splitlines() if "ON_BATTERY" in l]) which triggers Ruff E741; rename
the loop variable to a clearer identifier like "line" in both occurrences
(around the ON_BATTERY comprehension and the similar one at ~1722-1723) and
update any references inside the comprehension accordingly so the logic remains
identical but the variable name is unambiguous.

---

Outside diff comments:
In `@docs/testing.md`:
- Around line 73-85: Update docs/testing.md to refresh the test-counts and
breakdowns to match the changes: update the pyramid/table summary counts,
per-file test-count breakdown, and the E2E test case table to include the newly
added/updated coverage described in the "Test areas" section (e.g., Config
loading and validation, Monitor state machine, Shutdown mixins, Multi-UPS
coordinator, Redundancy runtime, Health monitoring, Notifications, Statistics
and TUI, Packaging). Ensure each referenced area has its corresponding numeric
test counts and any per-file entries updated to reflect added or removed tests
so the overall totals and tables remain consistent with the current test suite.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bab8a492-a969-4025-8fe2-d0dff8e7c139

📥 Commits

Reviewing files that changed from the base of the PR and between 93a7fef and a88b6f7.

📒 Files selected for processing (8)
  • docs/changelog.md
  • docs/testing.md
  • src/eneru/cli.py
  • src/eneru/tui.py
  • src/eneru/version.py
  • tests/e2e/groups/stats.sh
  • tests/test_cli.py
  • tests/test_tui.py

Comment thread src/eneru/tui.py
Comment on lines +499 to +514
``verbosity`` selects enabled tiers: ``0`` shows Power Events only,
``1`` adds Diagnostics, and ``2`` adds Lifecycle. ``priority_only`` is
accepted as a legacy shim for tests / older internal callers.

``max_events=None`` (or 0) disables the row cap entirely.

Trim is **3-tier**: POWER_EVENTS always survive the cap; remaining
slots are filled first with most-recent LIFECYCLE_EVENTS, then with
chatter (only reachable when ``priority_only=False`` widens the
upstream filter). Power events are never evicted; lifecycle context
outranks voltage-flap chatter when the cap is hit in verbose mode.
slots are filled first with most-recent Diagnostics, then with
Lifecycle. Power events are never evicted; diagnostics outrank daemon
lifecycle context when the cap is hit in verbose mode.
"""
if priority_only is not None:
# Legacy compatibility: the old boolean API had priority_only=False
# mean "show every event type".
verbosity = EVENTS_VERBOSITY_POWER if priority_only else EVENTS_VERBOSITY_ALL
verbosity = _events_verbosity(verbosity)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve the old priority_only=True semantics or remove the shim.

priority_only=True used to mean “priority rows,” which in this module is still PRIORITY_EVENTS = power + lifecycle. Mapping it to EVENTS_VERBOSITY_POWER now hides lifecycle rows like DAEMON_START, so any stale caller using the documented compatibility arg gets a narrower result than before.

💡 One localized way to keep the shim honest
-    if priority_only is not None:
-        # Legacy compatibility: the old boolean API had priority_only=False
-        # mean "show every event type".
-        verbosity = EVENTS_VERBOSITY_POWER if priority_only else EVENTS_VERBOSITY_ALL
+    legacy_priority_only = priority_only
     verbosity = _events_verbosity(verbosity)
@@
-                if not _event_enabled(etype, verbosity):
-                    continue
+                if legacy_priority_only is True:
+                    if etype not in PRIORITY_EVENTS:
+                        continue
+                elif legacy_priority_only is None:
+                    if not _event_enabled(etype, verbosity):
+                        continue
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/eneru/tui.py` around lines 499 - 514, The current legacy shim maps
priority_only=True to EVENTS_VERBOSITY_POWER which incorrectly drops lifecycle
events; change the mapping so that when priority_only is True you set verbosity
to PRIORITY_EVENTS (the legacy "priority rows" set: power + lifecycle),
otherwise keep the existing mapping to EVENTS_VERBOSITY_ALL; then pass that
value through _events_verbosity as before (update the conditional handling
around priority_only in the function where priority_only, _events_verbosity,
EVENTS_VERBOSITY_POWER, EVENTS_VERBOSITY_ALL, and PRIORITY_EVENTS are
referenced).

Comment thread tests/test_tui.py Outdated
Comment on lines +1705 to +1706
# Should see exactly 5 lines -- the most-recent 5 ON_BATTERY rows.
lines = [l for l in out.splitlines() if "ON_BATTERY" in l]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Rename the comprehension variable to clear Ruff E741.

l is flagged as an ambiguous name in both comprehensions here, so this test file will keep failing lint until it's renamed to something like line.

♻️ Minimal fix
-        lines = [l for l in out.splitlines() if "ON_BATTERY" in l]
+        lines = [line for line in out.splitlines() if "ON_BATTERY" in line]
...
-        lines = [l for l in out.splitlines() if "ON_BATTERY" in l]
+        lines = [line for line in out.splitlines() if "ON_BATTERY" in line]

Also applies to: 1722-1723

🧰 Tools
🪛 Ruff (0.15.12)

[error] 1706-1706: Ambiguous variable name: l

(E741)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_tui.py` around lines 1705 - 1706, The comprehensions in
tests/test_tui.py use the ambiguous variable name "l" (e.g., in the expression
that builds lines = [l for l in out.splitlines() if "ON_BATTERY" in l]) which
triggers Ruff E741; rename the loop variable to a clearer identifier like "line"
in both occurrences (around the ON_BATTERY comprehension and the similar one at
~1722-1723) and update any references inside the comprehension accordingly so
the logic remains identical but the variable name is unambiguous.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 8 files

Drop the internal priority_only compatibility argument from query_events_for_display so the new v5.3 event tier API has one explicit path: verbosity 0, 1, or 2.

Also address CodeRabbit follow-ups by renaming ambiguous test comprehension variables and documenting the updated Stats E2E event-tier check.

Co-Authored-By: opencode <noreply@opencode.ai>
@m4r1k
Copy link
Copy Markdown
Owner Author

m4r1k commented Apr 30, 2026

CodeRabbit follow-up: we removed the internal priority_only compatibility shim instead of preserving the old boolean path. This function is not a public config/API surface, and keeping the shim would leave two competing ways to express the same behavior while also making priority_only=True conflict with the new explicit verbosity-tier model. The code now has one path: verbosity=0 for Power Events, verbosity=1 for Power + Diagnostics, and verbosity=2 for all tiers. The lint and E2E docs follow-ups were addressed in the same local fix commit.

m4r1k and others added 3 commits May 1, 2026 00:58
Retry curses startup with xterm-256color when Ghostty advertises xterm-ghostty but the host terminfo database has not been updated yet.

Refresh packaged shell completions for the new event verbosity flags and bump the release candidate to 5.3.0-rc1.

Co-Authored-By: opencode <noreply@opencode.ai>
Make the non-events-only --once Recent Events block respect --length instead of applying an extra hard cap of 10 rows.

This matches the documented flag semantics: --time remains graph-only, --verbose selects event tiers, and --length controls the event row cap in both --once output modes.

Co-Authored-By: opencode <noreply@opencode.ai>
Grouped query_events_for_display previously returned an empty list when
max_events=1 because the per-section guard `if remaining_lines < 2: break`
exited before any header could render, silently violating the docstring
contract that POWER_EVENTS are never evicted within the cap.

--once is unaffected (it calls grouped=False), but --length 1 from the
CLI is a valid value and the live-TUI panel-sizing path can in theory
reach length=1 on a tiny terminal.

Add an early return at max_events==1 that surfaces the single most-recent
row from the trimmed `rows` list -- which the tier-priority trim block
above has already reduced to the highest-priority survivor (Power before
Diagnostics before Lifecycle). The bare row is rendered without a header
because the cap is too small to honor both. Polish the existing `< 2`
inline comment to spell out what 2 is (1 header + 1 row).

Three regression tests cover the contract: grouped length=1 with a Power
event renders bare ON_BATTERY, ungrouped length=1 keeps the Power event,
and grouped length=1 with no Power falls back to the most-recent
Diagnostic.
@m4r1k m4r1k merged commit 9e65ff3 into main Apr 30, 2026
40 checks passed
@m4r1k m4r1k deleted the feat/tui-event-verbosity branch April 30, 2026 23:29
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