fix(pi-agents-tmux): Monitor times are run-times and local wall time (VST-316) - #1438
Conversation
… not UTC ISO or a jumpy clock (VST-316) Claude-Session: https://claude.ai/code/session_012epxJEzGqT7q3qcFhdZUt5
…shows Duration only once terminal (VST-316) Claude-Session: https://claude.ai/code/session_012epxJEzGqT7q3qcFhdZUt5
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
ApprovabilityVerdict: Approved f747ed8 This PR improves time display formatting in the monitor UI - switching from ambiguous clock-of-day times to clearer elapsed run-times. Changes are self-contained presentation logic with comprehensive test coverage, no business logic impact. You can customize Macroscope's approvability policy. Learn more. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR updates the tmux agents “Monitor” UI to display human-friendly timing: elapsed/total run-time for tasks (instead of a clock-of-day that jumped on polls) and local wall-time timestamps in detail panes.
Changes:
- Replace clock-of-day task timestamps with elapsed/total run-time (
createdAt → nowwhile running,createdAt → completedAtwhen terminal). - Render local, human-readable date/time strings in session/task detail panes and add a “Duration” line for terminal tasks.
- Add/adjust tests and bump
@vanillagreen/pi-agents-tmuxversion + changelogs.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pi-extensions/pi-agents-tmux/extensions/subagent/browser/monitor-tree.ts | Adds run-duration + local datetime formatting; switches task row labels to elapsed/total run-time. |
| pi-extensions/pi-agents-tmux/extensions/subagent/browser/monitor-task-detail.ts | Uses local datetime formatting and adds terminal-only Duration line in summary. |
| pi-extensions/pi-agents-tmux/extensions/subagent/browser/monitor-session-detail.ts | Uses shared local datetime formatter for Start/Latest timestamps. |
| pi-extensions/pi-agents-tmux/extensions/subagent/browser.ts | Forces periodic re-render so elapsed run-times tick even without spinner animation. |
| pi-extensions/pi-agents-tmux/tests/monitor-times.test.ts | Adds focused tests for duration/date formatting and “updatedAt not a time source”. |
| pi-extensions/pi-agents-tmux/tests/dashboard-ux.test.ts | Updates UX assertions to match the new elapsed/total timing display. |
| pi-extensions/pi-agents-tmux/package.json | Version bump to 2.8.3. |
| pi-extensions/pi-agents-tmux/CHANGELOG.md | Documents the timing display change in the extension changelog. |
| CHANGELOG.md | Notes the extension change in the repo-level Unreleased changelog. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Merge queue ejected this PR ( Ejecting merge-group run: https://github.com/vanillagreencom/vstack/actions/runs/32031167093 ( Failing job(s):
No usable same-named comparison on the PR head (checks absent, skipped, or still running) — no flake-vs-genuine call is available; inspect the failing run before re-arming. Automated by merge-queue-ejection-alert (VST-196). This alert never re-arms auto-merge. |
…0, dashboard-ux.test.ts 1171) Claude-Session: https://claude.ai/code/session_012epxJEzGqT7q3qcFhdZUt5
Dismissing prior approval to re-evaluate f747ed8
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (3)
pi-extensions/pi-agents-tmux/extensions/subagent/browser/monitor-session-detail.ts:28
formatDurationBetweennow sits alongside the newformatRunDuration/monitorTaskRunTimeformatting, but it produces a different shape (e.g.,1h 1mvs1h 01m, and it includes seconds for minute durations while run-time rows do not). This can lead to inconsistent UI output across monitor panes. Consider consolidating duration formatting so session and task durations share a single formatter (or share the same padding/seconds rules) to keep output consistent and reduce future drift.
function formatDurationBetween(start: string | undefined, end: string | undefined): string {
const startMs = Date.parse(start ?? "");
const endMs = Date.parse(end ?? "");
if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || endMs < startMs) return "—";
const totalSeconds = Math.floor((endMs - startMs) / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
if (hours > 0) return `${hours}h ${minutes}m`;
if (minutes > 0) return `${minutes}m ${seconds}s`;
return `${seconds}s`;
}
pi-extensions/pi-agents-tmux/extensions/subagent/browser/monitor-tree.ts:115
- Passing
\"\"as a sentinel for missingcompletedAtrelies onDate.parse(\"\")yieldingNaNto produce\"—\". That works, but it’s indirect and makes the terminal-path behavior less explicit. Consider handling the missing-completedAtcase directly (e.g., early-return\"—\"when terminal andcompletedAtis absent) and only callingformatRunDuration(createdAt, completedAt)with a real timestamp.
export function monitorTaskRunTime(record: PaneTaskRecord): string {
if (monitorStatusIsTerminal(record.status)) return formatRunDuration(record.createdAt, record.completedAt ?? "");
// Minute granularity while running: the popup refreshes elapsed times on a
// slow cadence, so a seconds display would visibly lag between renders.
const elapsed = formatRunDuration(record.createdAt);
return /^\d+s$/.test(elapsed) ? "<1m" : elapsed;
}
pi-extensions/pi-agents-tmux/extensions/subagent/browser.ts:226
- The new elapsed-time refresh behavior introduces additional timing constants (
20_000,120) that control render cadence. To make the intent easier to maintain (and to avoid accidental mismatches with the minute-granularity requirement), consider extracting these into named constants (e.g.,LIVE_TIMER_INTERVAL_MS,ELAPSED_REFRESH_INTERVAL_MS) and documenting why 20s is the chosen threshold.
let lastElapsedRender = Date.now();
const liveTimer = setInterval(() => {
if (closed) return;
if (refreshMonitorView()) {
lastElapsedRender = Date.now();
requestRender();
return;
}
const hasLiveItems = getActiveItems().some((item) => isDashboardAnimatingStatus(item.status));
if (spinnersAnimated() && hasLiveItems) {
lastElapsedRender = Date.now();
requestRender();
return;
}
// Elapsed run-times tick at minute granularity; keep them moving even
// with spinner animation off and no lifecycle changes.
if (hasLiveItems && Date.now() - lastElapsedRender >= 20_000) {
lastElapsedRender = Date.now();
requestRender();
}
}, 120);
Fixes the two Agents-popup time-display bugs (VST-316).
Left Monitor tree: task rows showed a local
HH:MMclock sourced fromcompletedAt ?? updatedAt ?? createdAt— ambiguous (reads as a duration) and jumpy, because registry polls refreshupdatedAtevery cycle. Rows now show run-time only: elapsed (createdAt→ now, minute-granular,<1munder a minute) while active, total (createdAt→completedAt) once terminal,—when a terminal record has nocompletedAt.updatedAtis no longer a time source anywhere in the tree.Detail panes: Session Start/Latest and Task Summary Created/Done printed raw UTC ISO; they now render local human time (
Mar 24, 16:59, year added when not current). The Task Summary gains aDurationline once the task is terminal — only then, because that text is cached until status changes and a live elapsed would freeze at load time.Live refresh: with spinner animation disabled and no lifecycle changes the popup never re-rendered, freezing running elapsed. The popup timer now re-renders on a slow (20s) cadence while any task is live — matching the minute granularity of the running display.
Tests: new
tests/monitor-times.test.ts(8 pins: elapsed vs clock, updatedAt immunity, terminal stability, no-completedAt dash,<1mgranularity, terminal-only Duration, duration shapes, local-time format); two existing dashboard-ux pins updated from the oldHH:MMcontract. 355 green.Closes VST-316.
https://claude.ai/code/session_012epxJEzGqT7q3qcFhdZUt5