feat(ui): interactive-agent surfacing — History section + workspace card 'PA active' chip#51
Merged
Conversation
Dogfood feedback from gmbot: PA sessions can stay alive for hours
or days. In a single chronological History list, an active
long-running PA's row gets pushed deep as iteration events
accumulate above it. Scanning for "is PA still running?" forced
scrolling.
Fix: partition the History tab into two sections — "Interactive
agents" (PA + HA events, today only pa-session) at the top, and
the existing "Loop history" below. Both sorted newest-first
within their section.
Critical UX rule: every event has ONE permanent home. A PA's row
stays in the Interactive section regardless of status — no
disappearing on completion, no relocating to chronological slot
in the Loop section. Status badge handles running-vs-completed
within the section. The "active-only" framing would have hidden
terminated history; partition by event-type only preserves it.
When there are zero interactive events, no top section + no
header — the table looks exactly like today. The new structure
only appears when it's needed.
Complements F.22 (v0.24.0): F.22's chip surfaces loop-spawned
active agents on the dashboard card + Status tab; this PR
surfaces interactive agents in the History tab. Together they
close the "what's running RIGHT NOW" question for both classes.
Implementation: new pure helper
`partitionInteractiveEvents(events)` in
packages/web/src/utils/history-partition.ts (returns
{interactive, loop}). WorkspaceHistory.tsx renders two
<section> blocks with count-bearing headers when interactive
events exist.
INTERACTIVE_EVENT_TYPES is a Set — when HA grows a history-event
type, add it; no other changes needed.
Test coverage: 10 new tests covering partition correctness,
sorting, status-independence, empty input, totality, immutability
of input. All 1059 tests pass. Typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Natural extension of the History tab partition (same PR): F.22's active-agent chip on the workspace card shows loop / review / document / reflect activity but doesn't surface PA. PA runs outside the cfcf server (interactive cfcf spec) and is tracked separately. This adds a parallel chip — "● PA active" — that appears alongside the F.22 chip when a PA session is alive. Why separate chip vs new activeAgent enum value: F.22's activeAgent is mutually exclusive. PA can run concurrently with loop / standalone runs. Two chips can coexist; different accent color makes them visually separable. Liveness check: per-call process.kill(launcherPid, 0) against the PID in the most-recent pa-session event with status=running. Same primitive F.28's boot-reconcile uses, just called on every /api/workspaces poll. Side benefit: PA sessions that terminate uncleanly (shell killed) get the chip cleared in real time instead of waiting for next server boot. Status tab chip: matching "PA active" tag in the workspace detail header, derived from history (same trust level as the History tab). Pre-v0.24 events without launcherPid are skipped — no precise verification possible, stale chip worse than no chip. Boot-reconcile's mtime fallback handles them at next boot. Implementation: - packages/core/src/product-architect/pa-liveness.ts (new): getPaSessionLiveness, getPaSessionsForWorkspaces, isPidAlive - packages/server/src/app.ts: /api/workspaces enriched with paSession in parallel with activeAgent - packages/web/src/types.ts: mirror paSession field - packages/web/src/components/WorkspaceCard.tsx: PA active chip - packages/web/src/pages/WorkspaceDetail.tsx: PA active header tag Test coverage: 12 new tests covering null cases (missing history, no pa-session, no running event, no launcherPid, dead PID), positive case (live PID), ordering (newest-running wins), fall through stale to older live, batch shape, empty input, primitive correctness. All 1071 tests pass. Typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… visually distinct Dogfood feedback after PR #51 first pass: - "Interactive agents" → "Interactive sessions" (more accurate; each PA invocation IS a session, and the row content shows sessions, not agents-as-entities) - Sections previously looked visually similar; user wanted them optically distinct + collapsible Changes (display-only, no logic): - <section>+<h3> → <details open>+<summary>: native HTML collapsible (no React state). Disclosure triangle affordance, click-to-collapse, default open. Browser handles persistence across rerenders. - Each section gets a 3px left-border accent: interactive section uses var(--color-accent) (purple-ish), loop section uses var(--color-border) (subtle gray). Distinct at a glance. - Summary has a light background tint + radius to read as a header-like band rather than plain text. - Extracted LoopHistoryTable subcomponent so the loop section can render either inside a <details> (paired with interactive) or as a plain bare table (when no interactive events exist). The no-interactive-events case looks EXACTLY like today. No test changes — pure presentation tweaks. Existing partition tests still pass (10/10). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
fstamatelopoulos
added a commit
that referenced
this pull request
May 19, 2026
…polish Bumps version 0.24.4 -> 0.24.5 and consolidates [Unreleased] into a [0.24.5] release entry. Shipped via PR #51 + PR #52. Net-new since v0.24.4: - PR #51: History tab partition (Interactive sessions + Loop history sections) + workspace card "PA active" chip + Status tab tag; server-side PA PID liveness check - PR #52: ready/iterating status semantics (cfcf review flips terminal status to idle) + 4 dashboard polish items (history active counts, in-page iteration max, card timer, card layout) Test coverage: 1079 tests pass (+22 new). Typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two complementary UI improvements for surfacing interactive agents (PA today, HA when it grows history), bundled because they address the same underlying gap: F.22 (v0.24.0) tracks loop / review / document / reflect activity but not PA — PA runs outside the cfcf server entirely and isn't in the
active-processesregistry. This PR closes that gap on two surfaces.Part 1 — History tab: separate section for interactive agents
Dogfood feedback from the gmbot run: PA sessions can stay alive for hours or days. In a single chronological History list, an active long-running PA row gets pushed deep as iteration events accumulate above it.
Fix: partition the History tab into two sections.
pa-session), newest-first within the section. Active sessions naturally appear at the top because they're the newest. Header:Interactive agents (N).Loop history (N)header when the interactive section is present.Critical UX rule: every event has ONE permanent home. A PA row stays in the Interactive section regardless of status — no disappearing on completion. Status badge differentiates running/completed/failed within the section. (This was the load-bearing correction in design review: "active-only" would have hidden terminated history.)
When there are zero interactive events, no top section + no header on the bottom — looks exactly like today.
Part 2 — Workspace card + Status tab: "PA active" chip
Same problem on a different surface: F.22's active-agent chip on the workspace card / Status tab doesn't cover PA. This adds a parallel chip — "● PA active" — alongside the F.22 chip.
Liveness check: per-call
process.kill(launcherPid, 0)against the PID recorded on the most-recentpa-sessionevent withstatus === \"running\". Same primitive F.28's boot-reconcile uses, but called on every/api/workspacespoll instead of only at server boot.Side benefit: PA sessions that terminate uncleanly (shell killed, terminal closed) get the chip cleared in real time — no more waiting for the next server boot's reconcile pass.
Why a separate chip, not a new
activeAgentenum value: F.22'sactiveAgentis mutually exclusive. PA can run concurrently with the loop / standalone runs. Two chips can coexist; different accent color makes them visually separable.Test plan
bun run test— 1071 tests pass (+22 new across both parts)bun run typecheck— cleanhistory-partition.test.ts: partition splits correctly; both arrays newest-first; active PA stays at top regardless of startedAt; terminated events stay in their section (status does NOT change partition); handles all loop event types; empty input; partition is total; does not mutate inputpa-liveness.test.ts: null cases (missing history, no pa-session, no running event, no launcherPid, dead PID); positive case (live PID); ordering (newest-running wins); falls through stale newer to surface older live; batch shape; empty input; isPidAlive primitive● PA activechip alongside any loop chip; Status tab header showsPA activetag; chip clears immediately when PA terminatesVersioning
Target: v0.24.5 patch. Pure UX improvement, no behaviour / API contract change beyond the additive
paSessionfield on/api/workspaces. Same shape as v0.24.4.Files
Part 1:
packages/web/src/utils/history-partition.ts(new) +.test.tspackages/web/src/components/WorkspaceHistory.tsxPart 2:
packages/core/src/product-architect/pa-liveness.ts(new) +.test.tspackages/core/src/product-architect/index.ts(export)packages/server/src/app.ts(/api/workspacesenrichment)packages/web/src/types.ts(mirror)packages/web/src/components/WorkspaceCard.tsx(chip)packages/web/src/pages/WorkspaceDetail.tsx(header tag)Multiple-PA edge case
If a user accidentally runs multiple PAs against the same workspace, all of them appear in History section A. The chip surfaces the newest live one. No warning today — deferred until real users hit it.
🤖 Generated with Claude Code