Skip to content

Match Exposé status + recency to the dashboard (shared semantics) - #153

Merged
TraderSamwise merged 3 commits into
masterfrom
chore/tui-next-8
Jun 16, 2026
Merged

Match Exposé status + recency to the dashboard (shared semantics)#153
TraderSamwise merged 3 commits into
masterfrom
chore/tui-next-8

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jun 16, 2026

Copy link
Copy Markdown
Owner

What

Exposé and the dashboard were computing an agent's state and recency from different inputs, so they disagreed (e.g. dashboard "Working" vs Exposé "Waiting"; dashboard "output 16m ago" vs Exposé a bare "16m ago"). This makes them share a single source of truth.

Status label parity

  • Exposé mapped raw activity/attention directly; the dashboard maps the richer deriveSessionSemantics().user.label (e.g. activity:"waiting"Working, alive-idle → Ready).
  • Now the semantic user label is computed once in the runtime (buildTmuxWindowMetadata) and stored on the tmux window metadata as userLabel; agentStatusChip prefers it over the raw fallback. Added ready/offline border tints.

Recency parity (reusable)

  • Extracted the dashboard's per-state time-anchor selection into a shared sessionRecencyAnchor() (src/session-recency.ts) — returns which timestamp to show and its verb (output/prompted/idle/blocked/failed/offline).
  • The dashboard renderer now delegates to it (behavior unchanged). The runtime computes the same anchor from sessionMetadata.derived and stores recencyAt + recencyLabel; Exposé renders output 16m ago / prompted 1m ago verbatim.

Preview

┏ ▸ 1 claude(coder) (here) · aimux / beautify-tui ━━━━━━━━━━━┓
┃    WORKING   output 16m ago · editing files                ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃    READY   output 16m ago · awaiting prompt                ┃
┃    NEEDS INPUT   prompted 1m ago · approve?                ┃

Known follow-up

The runtime doesn't plumb per-session unread-notification time / last-used time into window metadata, so for needs input/blocked/error the anchor value falls back to last-output/became-idle (verb is exact; working/ready/idle cases are exact).

Tests

  • typecheck ✓, lint ✓, build ✓; 1337 tests pass. Added sessionRecencyAnchor coverage, userLabel-precedence coverage, and updated Exposé tile tests.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Session status now displays semantic labels (e.g., "working", "ready") for improved clarity.
    • Session recency displays with contextual labels (e.g., "output 7m ago").
  • Style

    • Added color styling for "ready" and "offline" session states.
  • Tests

    • Added test coverage for recency logic and updated existing tests for semantic labeling.

test and others added 2 commits June 16, 2026 10:46
Exposé mapped raw activity/attention directly (activity:"waiting" → "Waiting",
alive-idle → "Idle"), while the dashboard maps the richer deriveSessionSemantics
user label (→ "Working" / "Ready"). They disagreed for the same agent.

Compute the semantic user label once in the runtime (buildTmuxWindowMetadata)
and store it on the tmux window metadata as userLabel; the agent-status chip now
prefers userLabel over the raw activity/attention fallback, so Exposé and the
dashboard always show the same state. Add ready/offline border tints for the
states this newly surfaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the dashboard's per-state time-anchor selection into a reusable
sessionRecencyAnchor() (which timestamp to show + its verb: output/prompted/
idle/…). The dashboard renderer now delegates to it, and the runtime computes
the same anchor from sessionMetadata.derived and stores recencyAt/recencyLabel
on the tmux window metadata. Exposé renders "output 16m ago" / "prompted 1m
ago" verbatim, matching the dashboard instead of a bare last-event time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jun 16, 2026 3:12am

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

More reviews will be available in 13 minutes and 14 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 30a0e70a-a778-49ea-b1b9-d045ece288e2

📥 Commits

Reviewing files that changed from the base of the PR and between ec6ddf9 and 3e4792f.

📒 Files selected for processing (3)
  • src/multiplexer/session-runtime-core.ts
  • src/session-recency.test.ts
  • src/tui/render/agent-status.test.ts
📝 Walkthrough

Walkthrough

Introduces src/session-recency.ts with a sessionRecencyAnchor function that maps SessionUserLabel values to canonical display labels and selects the most relevant timestamp via priority fallbacks. This replaces ad-hoc lastActivityAt handling across the dashboard renderer, TmuxWindowMetadata (which gains userLabel/recencyAt/recencyLabel fields), expose tile rendering, and the agentStatusChip renderer (which gains a userLabel precedence override).

Changes

Session recency anchor integration

Layer / File(s) Summary
sessionRecencyAnchor module: types, logic, and tests
src/session-recency.ts, src/session-recency.test.ts
Defines SessionRecencyInput, SessionRecencyAnchor, and sessionRecencyAnchor(), mapping SessionUserLabel values to canonical display labels (output, prompted, idle, failed, blocked, offline) with priority timestamp fallbacks. Tests cover all lifecycle states.
agentStatusChip: userLabel precedence
src/tui/render/agent-status.ts, src/tui/render/agent-status.test.ts
Adds optional userLabel to AgentStatusInput, introduces a USER_LABEL mapping from semantic labels to AgentStatusChip variants, and short-circuits agentStatusChip to return the mapped chip when present. Tests verify override over raw activity/attention.
TmuxWindowMetadata contract and tile rendering
src/tmux/runtime-manager.ts, src/tmux/expose.ts, src/tmux/expose-tile.test.ts
Removes lastActivityAt from TmuxWindowMetadata; adds userLabel, recencyAt, recencyLabel. Extends STATE_BORDER with ready/offline color entries. Updates drawTile to prefix recency with recencyLabel. Tests validate pill source and labeled recency strings.
buildTmuxWindowMetadata: compute and emit recency anchor
src/multiplexer/session-runtime-core.ts
Imports deriveSessionSemantics, sessionRecencyAnchor, and isAgentOutputEventKind; derives semantic context and lastOutputAt, calls sessionRecencyAnchor, and populates the new userLabel/recencyAt/recencyLabel fields on returned metadata.
dashboard-renderers: delegate to sessionRecencyAnchor
src/tui/screens/dashboard-renderers.ts
Replaces the prior inline multi-branch conditional in sessionTimeAnchor with a single call to sessionRecencyAnchor, passing semantic label and recency-relevant timestamps.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • TraderSamwise/aimux#128: Derives the same session-state timestamps (lastOutputAt, becameIdleAt) and semantic labels (needs_response, next_step) that this PR consumes in sessionRecencyAnchor and the recency/userLabel metadata fields.
  • TraderSamwise/aimux#151: Directly precedes this PR by adding lastActivityAt to buildTmuxWindowMetadata / TmuxWindowMetadata and rendering it in the expose tile header — the fields replaced here.
  • TraderSamwise/aimux#150: Touches the same agent-status pill derivation and expose.ts/expose-tile.test.ts rendering pipeline that this PR extends with userLabel-driven semantics and recencyAt formatting.

Poem

🐇 Hoppity-hop through timestamps galore,
Old lastActivityAt? We need it no more!
sessionRecencyAnchor leaps to the scene,
With labels like output, prompted, offline — so clean.
The pill says "WORKING" with semantic delight,
A bunny-approved recency, perfectly right! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% 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 clearly and concisely summarizes the main objective of the PR: aligning Exposé status and recency display with dashboard semantics. It accurately reflects the two key improvements (status label parity and recency parity) that are the focus of this changeset.
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 chore/tui-next-8

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

@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 `@src/multiplexer/session-runtime-core.ts`:
- Around line 402-406: The sessionRecencyAnchor() call is missing latestUnreadAt
and lastUsedAt parameters that are included in the dashboard path, which can
cause recency mismatches for the same session state. Add latestUnreadAt and
lastUsedAt to the object passed to sessionRecencyAnchor() by sourcing these
values from the derived and semantic objects that are already available in this
context, ensuring the parameters match what the dashboard uses.

In `@src/session-recency.test.ts`:
- Around line 15-17: The test function with title "returns null for
working/ready with no output yet" only asserts the working state but claims to
test both working and ready states. Add a second expect statement in this test
to verify that sessionRecencyAnchor with label set to "ready" also returns null,
ensuring both branches mentioned in the test title are properly validated.

In `@src/tui/render/agent-status.test.ts`:
- Around line 34-44: The test description claims that the user label wins over
both activity and attention, but the current test cases in the "prefers the
dashboard-semantic user label over raw activity/attention" test only demonstrate
userLabel overriding activity. Add an additional assertion using agentStatusChip
that passes both activity and attention parameters along with a userLabel to
explicitly verify that userLabel takes precedence over the attention parameter,
ensuring the test intent is fully covered.
🪄 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

Run ID: a3b64a54-7a3e-4e68-9614-929994ca6551

📥 Commits

Reviewing files that changed from the base of the PR and between 2a3c0ad and ec6ddf9.

📒 Files selected for processing (9)
  • src/multiplexer/session-runtime-core.ts
  • src/session-recency.test.ts
  • src/session-recency.ts
  • src/tmux/expose-tile.test.ts
  • src/tmux/expose.ts
  • src/tmux/runtime-manager.ts
  • src/tui/render/agent-status.test.ts
  • src/tui/render/agent-status.ts
  • src/tui/screens/dashboard-renderers.ts

Comment thread src/multiplexer/session-runtime-core.ts
Comment thread src/session-recency.test.ts
Comment thread src/tui/render/agent-status.test.ts
- buildTmuxWindowMetadata now passes lastUsedAt and (for needs/blocked/error
  states only, to keep the common path cheap) latestUnreadAt into
  sessionRecencyAnchor, so Exposé's prompted/blocked/failed anchors match the
  dashboard's exact timestamp rather than falling back to output/idle.
- Add the missing ready null-path assertion and an attention-conflict case to
  the userLabel-precedence test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TraderSamwise
TraderSamwise merged commit 1b7a88d into master Jun 16, 2026
3 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