Skip to content

Add command dashboard cards#201

Merged
gnanam1990 merged 5 commits into
mainfrom
context-command-card
Jun 14, 2026
Merged

Add command dashboard cards#201
gnanam1990 merged 5 commits into
mainfrom
context-command-card

Conversation

@Vasanthdev2004

@Vasanthdev2004 Vasanthdev2004 commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add a reusable command-card renderer for bounded command dashboards
  • migrate /context and /tools away from raw status: ... command dumps
  • render command-card transcript rows as styled titled cards instead of muted system notes
  • add regression coverage for card redaction, sorted /tools output, and action-line rendering

Why

Several slash commands looked unchanged because they still flowed through the generic grey rowSystem note renderer. This PR makes the first command-card surfaces visibly product-like: titled card border, summary line, section headings, aligned fields, bullets, and actions.

The scope stays intentionally small so it does not collide with active doctor, sandbox/permissions, or transcript polish PRs.

Validation

  • go test ./internal/tui -run 'TestCommandCardRowTrimsIndentedActionsLabel|TestCommandCardRowRendersAsTitledCard' -count=1
  • go test ./internal/tui -run Tools -count=1
  • go test ./internal/tui -count=1
  • go test ./...
  • go vet ./...
  • go run ./cmd/zero-release build
  • go run ./cmd/zero-release smoke

Summary by CodeRabbit

  • New Features
    • Redesigned /tools command display with organized card layout showing registry status and tool counts.
    • Redesigned /context command with improved information organization across Runtime, Session, and Tools sections.
    • Added aligned field formatting and action buttons to command displays.
    • Enhanced visual presentation with better structured command output.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: efea8f10-6506-4254-9728-402c5a8c2e35

📥 Commits

Reviewing files that changed from the base of the PR and between f88841e and 593b9e8.

📒 Files selected for processing (2)
  • internal/tui/command_polish_test.go
  • internal/tui/command_views.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/tui/command_views.go
  • internal/tui/command_polish_test.go

Walkthrough

Introduces commandCard and commandCardSection structs with rendering logic that outputs aligned, pipe-separated card text. Refactors /context and /tools command views to use the card renderer with new field structure and actions. Integrates card rendering into the row display pipeline with contextual line styling. Adds helper functions pluralizeCount and contextCompactionStatus for label formatting and status normalization. Tests are updated to assert the new output format with aligned fields, pipe-separated summary/actions lines, and bordered card rendering.

Changes

commandCard rendering and view refactoring

Layer / File(s) Summary
commandCard data model and rendering engine
internal/tui/command_output.go
Adds commandCard struct (title, summary, sections, actions) and commandCardSection struct (title, fields, lines, rows, hints). renderCommandCard assembles the card into newline-separated text with "Zero" fallback for empty titles and conditional pipe-separated summary/actions lines. formatCommandCardSection renders sections with optional title, compacted/aligned key/value fields, and prefixed rows/lines. compactCommandCardList filters empty strings using existing compactCommandOutputText.
commandCard rendering unit tests
internal/tui/command_output_test.go
TestFormatCommandCardRendersBoundedDashboard validates renderCommandCard with a two-section card and asserts exact column-aligned, multi-line output including pipe-separated summary and actions. TestFormatCommandCardRedactsTokenLikeText (existing test position shifted) remains unchanged in functionality.
contextText() and toolsText() refactoring
internal/tui/command_views.go
toolsText() switches to renderCommandCard with Registry/Available sections and card actions; empty-registry path now shows "0 registered"/"no tools available" via card fields. contextText() switches to renderCommandCard, moving Runtime/Session/Tools attributes into card sections with card Summary (go runtime, permission, tool count) and actions. Adds registeredTools() (safe nil-registry handling), sessionRootDir() (avoids nil deref), pluralizeCount(count, singular, plural) for numeric labels, and contextCompactionStatus(status) (maps "not compacted""idle").
Row rendering integration for commandCard transcripts
internal/tui/rendering.go
renderRowModeUncached detects commandCardTranscriptPayload in rowSystem rows and routes matching text to renderCommandCardRow before other system rendering paths. renderCommandCardRow parses card transcript text into title and styled content lines (blank lines, first content, heading detection, actions: lines, - list items, muted default). isCommandCardHeading distinguishes headings from empty/list/action/multi-space lines. Uses styledBlockFillTitle for bordered output.
Integrated view and row rendering tests
internal/tui/command_polish_test.go, internal/tui/rendering_lime_test.go, internal/tui/model_test.go, internal/tui/session_controls_test.go
TestToolsCommandRendersCommandCard validates /tools card layout and actions for empty/single-tool registries. TestToolsCommandCardHandlesNilRegistry and TestToolsCommandShowsFullSortedCatalog validate catalog sorting and nil-registry handling. TestContextAndPermissionsCommandsRenderProductState updated with grouped /context card assertions (runtime/cwd/provider/model, session/compaction, tools, actions) and negative checks (no status: ok or permission mode:). TestContextCommandCardHandlesNilRegistryAndStableStyle validates nil-registry behavior. TestCommandCardRowRendersAsTitledCard validates bordered row rendering with section content, field/value formatting, bullets, and actions. TestCommandCardRowTrimsIndentedActionsLabel validates trimming of indented actions labels. TestContextCommandShowsSessionState and TestUsageEventsUpdateFooterAndContext updated to match pipe-separated summary and space-aligned field/usage formatting.

Sequence Diagrams

sequenceDiagram
  participant Caller
  participant renderCommandCard
  participant formatCommandCardSection
  participant compactCommandCardList

  Caller->>renderCommandCard: commandCard{title, summary, sections[], actions[]}
  renderCommandCard->>renderCommandCard: compact title (fallback to "Zero")
  renderCommandCard->>compactCommandCardList: summary items
  compactCommandCardList-->>renderCommandCard: filtered items
  loop for each section
    renderCommandCard->>formatCommandCardSection: commandCardSection
    formatCommandCardSection->>compactCommandCardList: fields + lines + rows
    compactCommandCardList-->>formatCommandCardSection: filtered entries
    formatCommandCardSection->>formatCommandCardSection: compute key column width
    formatCommandCardSection-->>renderCommandCard: aligned section text
  end
  renderCommandCard->>compactCommandCardList: actions items
  compactCommandCardList-->>renderCommandCard: filtered items
  renderCommandCard-->>Caller: newline-separated card string
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Gitlawb/zero#98: Introduces foundational commandOutput/formatCommandOutput rendering in internal/tui/command_output.go, which this PR extends with the new commandCard/renderCommandCard layer.
  • Gitlawb/zero#160: Modifies internal/tui/rendering.go row-rendering pipeline (renderRowMode/renderRowModeUncached), with this PR extending it to recognize and display command-card transcript payloads.
  • Gitlawb/zero#66: Modifies internal/tui/command_views.go for /context output and session_controls_test.go usage footer format, both refactored in this PR to use the new card-based rendering.

Suggested reviewers

  • anandh8x
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add command dashboard cards' directly matches the main PR objective of introducing a reusable command-card renderer component for bounded command dashboards.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch context-command-card

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 14, 2026

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

🧹 Nitpick comments (1)
internal/tui/command_output_test.go (1)

52-88: ⚡ Quick win

Add a redaction regression test for the command-card path.

This new test validates layout, but it doesn’t assert token-like redaction in Summary, Fields, or Actions. Adding one targeted case will protect /context output from secret-leak regressions.

Suggested test addition
+func TestFormatCommandCardRedactsTokenLikeText(t *testing.T) {
+	got := renderCommandCard(commandCard{
+		Title:   "Context",
+		Summary: []string{"sk-proj-sensitive-token"},
+		Sections: []commandCardSection{{
+			Title: "Runtime",
+			Fields: []commandField{
+				{Key: "provider", Value: "openai"},
+				{Key: "note", Value: "AIza1234567890abcdef"},
+			},
+		}},
+		Actions: []string{"copy sk-ant-api03-abcdefghijklmnopqrstuvwxyz"},
+	})
+	for _, secret := range []string{
+		"sk-proj-sensitive-token",
+		"AIza1234567890abcdef",
+		"sk-ant-api03-abcdefghijklmnopqrstuvwxyz",
+	} {
+		if strings.Contains(got, secret) {
+			t.Fatalf("expected token-like text to be redacted, got:\\n%s", got)
+		}
+	}
+}
🤖 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 `@internal/tui/command_output_test.go` around lines 52 - 88, Add a new test
function (such as TestFormatCommandCardRedactsTokens) that creates a commandCard
with token-like or secret-like patterns embedded in the Summary field values,
Field values within the Sections, and Action strings. Call renderCommandCard
with this test data and assert that the output properly redacts or masks these
sensitive patterns rather than exposing them as-is. This regression test will
ensure that future changes to the command card rendering do not inadvertently
leak secrets in the /context 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 `@internal/tui/command_views.go`:
- Around line 475-482: The `style` field in the Fields slice is passed as
`m.responseStyle` without a fallback value, causing it to be skipped during
rendering when empty, which makes the Runtime section shape inconsistent. Modify
the `style` field entry to use the `displayValue` helper function (like the
other fields do) with an appropriate fallback value such as "none" to ensure the
field maintains a stable presence in the context output.

---

Nitpick comments:
In `@internal/tui/command_output_test.go`:
- Around line 52-88: Add a new test function (such as
TestFormatCommandCardRedactsTokens) that creates a commandCard with token-like
or secret-like patterns embedded in the Summary field values, Field values
within the Sections, and Action strings. Call renderCommandCard with this test
data and assert that the output properly redacts or masks these sensitive
patterns rather than exposing them as-is. This regression test will ensure that
future changes to the command card rendering do not inadvertently leak secrets
in the /context output.
🪄 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 Plus

Run ID: 3c1ca95b-9703-4019-be10-b830dc5867f5

📥 Commits

Reviewing files that changed from the base of the PR and between 7153ec7 and 29e011e.

📒 Files selected for processing (6)
  • internal/tui/command_output.go
  • internal/tui/command_output_test.go
  • internal/tui/command_polish_test.go
  • internal/tui/command_views.go
  • internal/tui/model_test.go
  • internal/tui/session_controls_test.go

Comment thread internal/tui/command_views.go
coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 14, 2026

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

🤖 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 `@internal/tui/command_views.go`:
- Around line 17-20: The code unconditionally calls m.registry.All() at multiple
locations (around line 17 and around line 476) without checking if m.registry is
nil, which will cause a panic if the registry is uninitialized. Add a nil-safe
guard before each call to m.registry.All() that checks if m.registry is nil and
returns an empty slice as a fallback when it is, ensuring the file preserves
zero-value model behavior consistently across all code paths.
🪄 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 Plus

Run ID: a1e50fc3-49a2-4d21-8ce3-a51970275360

📥 Commits

Reviewing files that changed from the base of the PR and between 29e011e and 8291d2a.

📒 Files selected for processing (3)
  • internal/tui/command_output_test.go
  • internal/tui/command_polish_test.go
  • internal/tui/command_views.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/tui/command_output_test.go

Comment thread internal/tui/command_views.go Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 14, 2026

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

🤖 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 `@internal/tui/rendering.go`:
- Around line 444-446: The actions: label parsing in the rendering code uses
inconsistent variables. The condition checks `strings.HasPrefix(trimmed,
"actions:")` to detect the action label, but then uses `strings.TrimPrefix(line,
"actions:")` which operates on the original untrimed line. When the line has
leading whitespace like "  actions: ...", TrimPrefix cannot remove the
"actions:" prefix from the original line since it starts with spaces, causing
duplication. Fix this by changing the TrimPrefix call in the same case statement
to use the `trimmed` variable instead of `line` so that both the prefix
detection and removal operate on the same trimmed version of the input.
🪄 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 Plus

Run ID: 9b73bebc-4dcd-4df9-b9c8-95112bd7283e

📥 Commits

Reviewing files that changed from the base of the PR and between 8291d2a and 0821e14.

📒 Files selected for processing (4)
  • internal/tui/command_output.go
  • internal/tui/command_views.go
  • internal/tui/rendering.go
  • internal/tui/rendering_lime_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/tui/command_views.go

Comment thread internal/tui/rendering.go
@Vasanthdev2004
Vasanthdev2004 dismissed stale reviews from coderabbitai[bot], coderabbitai[bot], and coderabbitai[bot] June 14, 2026 11:37

Addressed in follow-up commits on PR #201; CodeRabbit status context is passing on f88841e.

@Vasanthdev2004
Vasanthdev2004 marked this pull request as ready for review June 14, 2026 11:38
@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Zero automated PR review

Verdict: No blockers found

Blockers

  • None found.

Validation

  • [pass] Diff hygiene: git diff --check
  • [pass] Tests: go test ./...
  • [pass] Build: go run ./cmd/zero-release build
  • [pass] Smoke build: go run ./cmd/zero-release smoke

Scope

Head: 593b9e829c29
Changed files (8): internal/tui/command_output.go, internal/tui/command_output_test.go, internal/tui/command_polish_test.go, internal/tui/command_views.go, internal/tui/model_test.go, internal/tui/rendering.go, internal/tui/rendering_lime_test.go, internal/tui/session_controls_test.go

This deterministic review checks validation status and basic diff hygiene. A human reviewer still owns product judgment and design quality.

@Vasanthdev2004 Vasanthdev2004 changed the title Add context command dashboard card Add command dashboard cards Jun 14, 2026
@Vasanthdev2004

Copy link
Copy Markdown
Collaborator Author

@coderabbitai fullreview

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR diff and file contents
gh pr view 201 --repo Gitlawb/zero --json title,body,state,files 2>/dev/null | head -100

echo "=== PR DIFF ==="
gh pr diff 201 --repo Gitlawb/zero 2>/dev/null

Length of output: 23005



@Vasanthdev2004 Here is the full review of PR #201.


Review: Add command dashboard cards

The overall design is clean — the card abstraction is well-isolated, the transcript sentinel prevents false positives, and the test coverage is solid (positive + negative assertions, sort-order verification, redaction). A few correctness issues need attention before merging.


🔴 Bug — wrong style when card has no summary

File: internal/tui/rendering.go, renderCommandCardRow

case index == 0:
    lines = append(lines, zeroTheme.ink.Bold(true).Render(line))
case isCommandCardHeading(trimmed):
    lines = append(lines, zeroTheme.accent.Bold(true).Render(line))

index == 0 is checked before isCommandCardHeading. renderCommandCard omits the summary line entirely when Summary is empty. So if a card has no summary, raw[1] is the first section title — it hits index == 0 and gets ink.Bold (white/default) instead of accent.Bold. The heading renders in the wrong colour.

Fix: check isCommandCardHeading first so section titles always win:

case index == 0 && !isCommandCardHeading(trimmed):
    lines = append(lines, zeroTheme.ink.Bold(true).Render(line))
case isCommandCardHeading(trimmed):
    lines = append(lines, zeroTheme.accent.Bold(true).Render(line))

🟡 Fragile heuristic in isCommandCardHeading

File: internal/tui/rendering.go

return !strings.Contains(value, " | ") && !strings.Contains(value, "  ")

The double-space check (" ") is the only way the renderer distinguishes a section heading from an aligned field line. Any section title that accidentally contains two consecutive spaces (e.g. "Go Runtime", abbreviations, copy-paste artefacts) will silently fall through to the muted field style. This is invisible in the current tests because all headings are single words.

Consider an explicit approach: renderCommandCard could tag heading lines (e.g. prefix with a sentinel byte in the internal string, stripped before display) so the renderer doesn't have to infer structure from whitespace.


🟡 Dead guard: len(raw) == 0 is unreachable

File: internal/tui/rendering.go, renderCommandCardRow

raw := strings.Split(strings.TrimRight(...), "\n")
if len(raw) == 0 {          // ← never true; strings.Split always returns ≥ 1 element
    return renderSystemNote(text, width)
}

strings.Split on any input returns at least [""]. The guard is dead code and misleads readers about the function's behaviour. The real edge case is title == "" (empty first line), which passes through and calls styledBlockFillTitle with an empty title — worth guarding explicitly:

if len(raw) == 0 || strings.TrimSpace(raw[0]) == "" {
    return renderSystemNote(text, width)
}

🟡 Null-byte sentinel is fragile

File: internal/tui/command_output.go

const commandCardTranscriptPrefix = "\x00command-card\x00"

Null bytes are stripped by JSON marshalling (json.Marshal encodes \x00 as \u0000, but some decoders silently truncate at it), many logging frameworks, SQLite TEXT columns, and anything that treats the string as a C string. If the transcript is ever serialised/deserialised (e.g. persisted sessions, logging), the prefix will be silently corrupted and cards fall back to rendering as raw grey system notes with no error.

A printable prefix like "\x1ecommand-card\x1e" (ASCII Record Separator) or "§card§" would survive most serialisation pipelines without ambiguity.


🟢 Minor nits

Location Note
command_output.go formatCommandCardSection Key alignment uses len(key) (byte count). No issue for current ASCII keys; add a comment if Unicode keys are ever expected.
command_views.go contextCompactionStatus Only maps "not compacted""idle"; all other statuses pass through. Fine for now, but worth a comment listing the expected input set so future contributors know what to expect.
command_output.go renderCommandCard lines := []string{}var lines []string to avoid a redundant heap allocation when the card is empty.

✅ What's solid

  • compactCommandCardList correctly filters empty/whitespace strings — redaction tests verify this path.
  • pluralizeCount is properly extracted and reusable.
  • TestToolsCommandShowsFullSortedCatalog verifying positional order (not just presence) of tool names is exactly the right way to test sort behaviour.
  • Negative assertions (assertNotContains) throughout the new tests catch regression to the old format reliably.
  • The \x00 sentinel being detected in renderRowModeUncached before the other system-row branches means there's no ambiguity with /sessions or /mcp rows.

The two issues that need fixes before merge are the heading style bug (wrong colour when no summary) and the dead guard + empty title edge case. The null-byte sentinel is the highest-risk follow-up.

@gnanam1990
gnanam1990 merged commit e1f1b11 into main Jun 14, 2026
7 checks passed
@Vasanthdev2004
Vasanthdev2004 deleted the context-command-card branch June 28, 2026 08:27
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