Skip to content

feat(w1): agent terminal theme renderer — 4090-claude convergence - #1065

Merged
POWERFULMOVES merged 2 commits into
mainfrom
feat/w1-agent-terminal-theme
Mar 22, 2026
Merged

POWERFULMOVES merged 2 commits into
mainfrom
feat/w1-agent-terminal-theme

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Mar 22, 2026

Copy link
Copy Markdown
Owner

Summary

Terminal renderer features

  • --banner — full themed banner with glyph, name, voice, resonance
  • --status "text" — single-line themed status bar
  • --session — combined agent+node identity display (hardware, strengths)
  • --roster — compact roster of all 11 agents
  • --demo — renders all agents with full banners
  • Cross-platform: Windows UTF-8 stdout reconfigure, ANSI 24-bit color

z890 handoff validation

  • 0 open PRs confirmed (clean slate)
  • Node specialization matrix examined (4090 = noise-reducer)
  • Dual sniffer keywords examined (pattern/docs → 4090)

Test plan

  • python pmoves/tools/agent_terminal_theme.py --demo — all 11 agents render
  • python pmoves/tools/agent_terminal_theme.py --agent 4090-claude --session — session header with node spec
  • python pmoves/tools/agent_terminal_theme.py --roster — compact roster

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a new terminal rendering tool that displays styled information with ANSI colors and text formatting capabilities
    • Includes multiple viewing modes: detailed information banners, single-line status displays, roster listings, and interactive demonstrations
    • Built-in terminal capability detection ensures proper and optimal color rendering across different platforms and terminal applications

New tool: pmoves/tools/agent_terminal_theme.py — reads flat 1.0.0
agent_signatures.yaml + node-agent-specialization.yaml, renders
ANSI 24-bit themed output (banners, status bars, session headers,
agent roster). Cross-platform (Windows UTF-8 reconfigure).

Functions: load_agent(), render_banner(), render_status_bar(),
session_header(), colorize(), render_roster(). Integration-ready
for sign_trail.py and pr_hedge_trim.py.

Claims W1 (terminal renderer + Gate 3) in AGNOTE4482PHI.t1.md
and AGNOTE4482_ROADMAP_W1-W5.md Agent Claim Register.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@POWERFULMOVES has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 23 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3fa0cd6f-a973-4bc6-b4c6-f4cd2270f8ae

📥 Commits

Reviewing files that changed from the base of the PR and between fa3d331 and e7c2379.

📒 Files selected for processing (1)
  • pmoves/tools/agent_terminal_theme.py
📝 Walkthrough

Walkthrough

A new Python CLI tool is introduced to render ANSI-styled terminal output for agents, along with documentation entries tracking the work assignment. The tool loads agent and node configuration from YAML files, supports ANSI capability detection, and provides multiple rendering modes including banners, status bars, and session headers.

Changes

Cohort / File(s) Summary
Documentation & Claims
pmoves/docs/AGENTS/AGNOTE4482PHI.t1.md, pmoves/docs/AGENTS/AGNOTE4482_ROADMAP_W1-W5.md
Added claim register entries for W1 terminal renderer work assignment to agent 4090-claude on branch feat/w1-agent-terminal-theme.
Terminal Rendering Tool
pmoves/tools/agent_terminal_theme.py
New executable CLI script implementing ANSI terminal theming for agents and nodes. Includes dataclasses for AgentTheme and NodeSpec, YAML configuration loading with safe fallback, ANSI escape sequence helpers, and CLI modes for --demo, --roster, --banner, --status, and --session rendering.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A terminal blooms in colors bright,
With glyphs and themes in ANSI light,
4090-claude paints banners true,
Where agents and nodes wear their hue!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is missing the required Testing section with actual commands/output and lacks clear documentation of manual test execution results. Add a Testing section documenting the executed commands and their output to verify the three test scenarios work as expected.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing an agent terminal theme renderer for the W1 workstream with 4090-claude convergence.
Docstring Coverage ✅ Passed Docstring coverage is 86.67% which is sufficient. The required threshold is 80.00%.

✏️ 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/w1-agent-terminal-theme

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.

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

🧹 Nitpick comments (1)
pmoves/tools/agent_terminal_theme.py (1)

125-145: Consolidate duplicated agent-mapping logic.

load_agent and load_all_agents repeat the same field mapping. Extracting a helper reduces drift risk.

Refactor sketch
+def _to_agent_theme(agent_id: str, entry: Dict[str, Any]) -> AgentTheme:
+    return AgentTheme(
+        agent_id=entry.get("agent_id", agent_id),
+        display_name=entry.get("display_name", agent_id),
+        glyph=entry.get("glyph", "?"),
+        color=entry.get("color", "#FFFFFF"),
+        accent=entry.get("accent", "#CCCCCC"),
+        voice=entry.get("voice", "analytical"),
+        resonance=entry.get("resonance", []),
+        description=entry.get("description", ""),
+        co_author=entry.get("co_author", ""),
+        specialization=entry.get("specialization", ""),
+        routes_to=entry.get("routes_to", []),
+    )
+
 def load_agent(agent_id: str) -> Optional[AgentTheme]:
@@
-    return AgentTheme(
-        agent_id=entry.get("agent_id", agent_id),
-        display_name=entry.get("display_name", agent_id),
-        glyph=entry.get("glyph", "?"),
-        color=entry.get("color", "#FFFFFF"),
-        accent=entry.get("accent", "#CCCCCC"),
-        voice=entry.get("voice", "analytical"),
-        resonance=entry.get("resonance", []),
-        description=entry.get("description", ""),
-        co_author=entry.get("co_author", ""),
-        specialization=entry.get("specialization", ""),
-        routes_to=entry.get("routes_to", []),
-    )
+    return _to_agent_theme(agent_id, entry)
@@
-        agents.append(AgentTheme(
-            agent_id=entry.get("agent_id", aid),
-            display_name=entry.get("display_name", aid),
-            glyph=entry.get("glyph", "?"),
-            color=entry.get("color", "#FFFFFF"),
-            accent=entry.get("accent", "#CCCCCC"),
-            voice=entry.get("voice", "analytical"),
-            resonance=entry.get("resonance", []),
-            description=entry.get("description", ""),
-            co_author=entry.get("co_author", ""),
-            specialization=entry.get("specialization", ""),
-            routes_to=entry.get("routes_to", []),
-        ))
+        agents.append(_to_agent_theme(aid, entry))

Also applies to: 147-166

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

In `@pmoves/tools/agent_terminal_theme.py` around lines 125 - 145, Both load_agent
and load_all_agents duplicate the same mapping from a signature dict to an
AgentTheme; create a small helper (e.g., _theme_from_entry(entry: dict,
default_id: str) -> AgentTheme) that centralizes the mapping logic used to build
AgentTheme instances (map agent_id, display_name, glyph, color, accent, voice,
resonance, description, co_author, specialization, routes_to with the same
defaults currently in load_agent), then replace the construction in load_agent
and the corresponding block in load_all_agents to call this helper (use
_load_yaml/_SIGNATURES_PATH as before and pass appropriate default_id).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pmoves/docs/AGENTS/AGNOTE4482_ROADMAP_W1-W5.md`:
- Line 280: Update the W1 section so its owner/status matches the claimed row:
change the "Owner: Unclaimed" text in the W1 section to reflect the new claim
"4090-claude" and set status to "CLAIMED" (or mirror the exact phrasing used in
the table row "W1 (terminal renderer + Gate 3) | 4090-claude | 2026-03-22 |
CLAIMED | feat/w1-agent-terminal-theme") so the section and the claim row are
consistent.

In `@pmoves/tools/agent_terminal_theme.py`:
- Around line 112-123: The _load_yaml function currently lets file I/O and YAML
parse errors propagate; wrap the file open and yaml.safe_load call in a
try/except that catches exceptions from reading/parsing (e.g., OSError,
yaml.YAMLError, or a broad Exception), print a concise warning to stderr that
includes the path and the exception message, and return {} on any failure; keep
the existing ImportError handling for missing pyyaml and the existing behavior
when path.exists() is false. Use the function name _load_yaml and reference
yaml.safe_load and path to locate where to add the try/except and error message.
- Around line 288-291: The --roster branch currently returns 0 even when no
agents were loaded; change it to fail closed by checking the result of
load_all_agents() and returning a non-zero exit code (or raising SystemExit)
when agents is empty or loading failed: after calling load_all_agents() in the
args.roster block, detect if agents is falsy or len(agents) == 0, print a clear
error message about missing/failed signature loading, and return 1 (or raise
SystemExit(1)) instead of returning 0; keep the successful path that prints
render_roster(agents) and returns 0.
- Around line 302-304: When args.session is set, the code currently calls
load_node(args.node or args.agent) which silently falls back to agent-only
output if an explicit --node is unknown; change the logic to call load_node with
args.node when args.node is provided, then if args.node was supplied and
load_node returns falsy, emit an explicit error (e.g., print to stderr or log
via the same logger) and exit with a non-zero status instead of continuing;
otherwise proceed to call session_header(agent, node) as before. Ensure you
modify the block that uses args.session, referencing load_node, args.node,
args.agent, agent, node, and session_header.

---

Nitpick comments:
In `@pmoves/tools/agent_terminal_theme.py`:
- Around line 125-145: Both load_agent and load_all_agents duplicate the same
mapping from a signature dict to an AgentTheme; create a small helper (e.g.,
_theme_from_entry(entry: dict, default_id: str) -> AgentTheme) that centralizes
the mapping logic used to build AgentTheme instances (map agent_id,
display_name, glyph, color, accent, voice, resonance, description, co_author,
specialization, routes_to with the same defaults currently in load_agent), then
replace the construction in load_agent and the corresponding block in
load_all_agents to call this helper (use _load_yaml/_SIGNATURES_PATH as before
and pass appropriate default_id).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3be28772-1ae8-4d47-8abd-a1fc7ffcac5e

📥 Commits

Reviewing files that changed from the base of the PR and between ca9d1ae and fa3d331.

📒 Files selected for processing (3)
  • pmoves/docs/AGENTS/AGNOTE4482PHI.t1.md
  • pmoves/docs/AGENTS/AGNOTE4482_ROADMAP_W1-W5.md
  • pmoves/tools/agent_terminal_theme.py

| W4 (partial: content stubs) | 5090-claude | 2026-03-19 | SHIPPED `2a681471` | main |
| W4 (beats pipeline runner) | claude-opus | 2026-03-20 | SHIPPED #1039 | main |
| W5 (partial: TZ models, TACs) | 5090-claude | 2026-03-19 | SHIPPED `2a681471` | main |
| W1 (terminal renderer + Gate 3) | 4090-claude | 2026-03-22 | CLAIMED | feat/w1-agent-terminal-theme |

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.

⚠️ Potential issue | 🟡 Minor

Update W1 owner/status text for internal consistency.

This new claim row marks W1 as actively claimed, but the W1 section still says “Owner: Unclaimed” (Line 52). Please reconcile both sections in this doc.

As per coding guidelines, "pmoves/docs/**: Check docs for operational accuracy: Keep status claims aligned with evidence in runbooks and smokes."

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

In `@pmoves/docs/AGENTS/AGNOTE4482_ROADMAP_W1-W5.md` at line 280, Update the W1
section so its owner/status matches the claimed row: change the "Owner:
Unclaimed" text in the W1 section to reflect the new claim "4090-claude" and set
status to "CLAIMED" (or mirror the exact phrasing used in the table row "W1
(terminal renderer + Gate 3) | 4090-claude | 2026-03-22 | CLAIMED |
feat/w1-agent-terminal-theme") so the section and the claim row are consistent.

Comment on lines +112 to +123
def _load_yaml(path: Path) -> Dict[str, Any]:
"""Load YAML file, returning empty dict on failure."""
try:
import yaml # type: ignore[import-untyped]
except ImportError:
print("WARNING: pyyaml not installed, using fallback", file=sys.stderr)
return {}
if not path.exists():
return {}
with open(path, encoding="utf-8") as f:
return yaml.safe_load(f) or {}

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.

⚠️ Potential issue | 🟠 Major

Handle YAML/file errors explicitly in _load_yaml.

Malformed YAML or read failures currently raise and terminate the CLI. This should fail gracefully and return {} with an error message.

Suggested fix
 def _load_yaml(path: Path) -> Dict[str, Any]:
     """Load YAML file, returning empty dict on failure."""
     try:
         import yaml  # type: ignore[import-untyped]
     except ImportError:
         print("WARNING: pyyaml not installed, using fallback", file=sys.stderr)
         return {}
     if not path.exists():
         return {}
-    with open(path, encoding="utf-8") as f:
-        return yaml.safe_load(f) or {}
+    try:
+        with open(path, encoding="utf-8") as f:
+            loaded = yaml.safe_load(f) or {}
+    except (OSError, yaml.YAMLError) as exc:
+        print(f"ERROR: Failed to load {path}: {exc}", file=sys.stderr)
+        return {}
+    if not isinstance(loaded, dict):
+        print(f"ERROR: Unexpected YAML root type in {path}", file=sys.stderr)
+        return {}
+    return loaded
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pmoves/tools/agent_terminal_theme.py` around lines 112 - 123, The _load_yaml
function currently lets file I/O and YAML parse errors propagate; wrap the file
open and yaml.safe_load call in a try/except that catches exceptions from
reading/parsing (e.g., OSError, yaml.YAMLError, or a broad Exception), print a
concise warning to stderr that includes the path and the exception message, and
return {} on any failure; keep the existing ImportError handling for missing
pyyaml and the existing behavior when path.exists() is false. Use the function
name _load_yaml and reference yaml.safe_load and path to locate where to add the
try/except and error message.

Comment on lines +288 to +291
if args.roster:
agents = load_all_agents()
print(render_roster(agents))
return 0

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.

⚠️ Potential issue | 🟠 Major

--roster should fail closed when signatures cannot be loaded.

This path currently exits 0 even if the file is missing/empty and prints a 0-agent roster, which masks configuration errors.

Suggested fix
     if args.roster:
         agents = load_all_agents()
+        if not agents:
+            print("ERROR: Could not load agent_signatures.yaml", file=sys.stderr)
+            return 1
         print(render_roster(agents))
         return 0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if args.roster:
agents = load_all_agents()
print(render_roster(agents))
return 0
if args.roster:
agents = load_all_agents()
if not agents:
print("ERROR: Could not load agent_signatures.yaml", file=sys.stderr)
return 1
print(render_roster(agents))
return 0
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pmoves/tools/agent_terminal_theme.py` around lines 288 - 291, The --roster
branch currently returns 0 even when no agents were loaded; change it to fail
closed by checking the result of load_all_agents() and returning a non-zero exit
code (or raising SystemExit) when agents is empty or loading failed: after
calling load_all_agents() in the args.roster block, detect if agents is falsy or
len(agents) == 0, print a clear error message about missing/failed signature
loading, and return 1 (or raise SystemExit(1)) instead of returning 0; keep the
successful path that prints render_roster(agents) and returns 0.

Comment on lines +302 to +304
if args.session:
node = load_node(args.node or args.agent)
print(session_header(agent, node))

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.

⚠️ Potential issue | 🟡 Minor

Return an error when an explicit --node is unknown.

If --node is provided but not found, the command silently degrades to agent-only output. That makes bad input hard to detect.

Suggested fix
     if args.session:
         node = load_node(args.node or args.agent)
+        if args.node and node is None:
+            print(f"ERROR: Node '{args.node}' not found in {_NODE_SPEC_PATH}", file=sys.stderr)
+            return 1
         print(session_header(agent, node))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pmoves/tools/agent_terminal_theme.py` around lines 302 - 304, When
args.session is set, the code currently calls load_node(args.node or args.agent)
which silently falls back to agent-only output if an explicit --node is unknown;
change the logic to call load_node with args.node when args.node is provided,
then if args.node was supplied and load_node returns falsy, emit an explicit
error (e.g., print to stderr or log via the same logger) and exit with a
non-zero status instead of continuing; otherwise proceed to call
session_header(agent, node) as before. Ensure you modify the block that uses
args.session, referencing load_node, args.node, args.agent, agent, node, and
session_header.

Adds missing docstring for CodeRabbit >=80% coverage gate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@POWERFULMOVES
POWERFULMOVES merged commit 993edb0 into main Mar 22, 2026
4 of 5 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.

2 participants