feat(status + dashboard): "ready/iterating" + 4 UX polish items#52
Merged
Conversation
Multi-loop projects (PA + SA driving the workspace through
several sequential milestone loops) had a misleading "COMPLETED"
badge between loops — the project wasn't done, it was iterating.
Fix: one new explicit transition + one label rename.
Transition: {completed, failed, stopped} + cfcf review
(standalone) -> idle. Triggered at the top of architect-runner's
startReview() path, BEFORE the SA spawn. Narrow trigger by
design — only SA (scope work). Not reflect (retrospection),
document (finalizing), or spec (PA, independent surface with
its own chip from v0.24.5).
Paused stays paused — preserves resume mechanics + refine_plan
action. In-loop architect (runReviewSync) doesn't flip — it
transitions through "running" already. failed and stopped stay
distinct internally for audit-trail preservation.
Label rename: idle -> "ready/iterating" in StatusBadge.tsx
(web) and a new formatStatus() helper in cfcf status CLI. The
slashed label covers both intents (fresh workspace = "ready",
post-terminal + SA run = "iterating") without derive-from-
history complexity. Internal value stays "idle" — zero
state-machine churn.
Implementation: TERMINAL_LOOP_STATUSES constant +
flipTerminalStatusToIdle(workspace) helper (returns bool for
testability + best-effort error handling). startReview() calls
it before ensureWorkspaceLogDir.
Test coverage: 8 new tests covering all status transitions
(completed/failed/stopped flip; paused/running/idle don't flip;
undefined status defensive case; TERMINAL_LOOP_STATUSES set
exhaustiveness). All 1079 tests pass; typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four small dogfood-driven UX polish items bundled together:
1. History tab section headers: split count into "(active: N |
total: M)" instead of just "(N)". Surfaces "is something
running RIGHT NOW" without scanning rows.
2. Status tab PhaseIndicator subtitle: "Iteration 24 (max: 28)"
instead of just "Iteration 24". Ceiling visible next to the
live timer without a click into Config.
3. Status tab Loop State block: trimmed. Iteration/max now in
PhaseIndicator above; pause-every is in Config tab. Block
replaced with conditional "Stall warning" that only renders
when consecutiveStalled > 0.
4. Workspace card three changes:
- Live elapsed timer for running loop. New
workspace.loopStartedAt field (server-enriched from
loopState.startedAt when activeAgent === "loop"), rendered
inside the loop chip via useElapsed hook.
- Chips moved BELOW title+badge row (was crowded when loop +
PA both active). Two-row layout, conditional rendering —
no chips = no row.
- Agents row adds Reflect (per-workspace). PA intentionally
NOT added (global config = same on every card). Architect
+ Documenter omitted to keep row scannable.
Server enrichment: /api/workspaces gets loopStartedAt populated
from loopState.startedAt when active. One getLoopState() call
per running workspace, in-memory cached.
No new tests — pure presentation. All 1079 tests still pass.
Typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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-themed PR bundling related dashboard UX work.
Part 1: "ready/iterating" status (the original PR scope)
Multi-loop projects (PA + SA driving the workspace through several sequential milestone loops, like the gmbot run) had a misleading "COMPLETED" badge between loops — the project wasn't done, it was iterating.
Fix: one new explicit transition + one label rename.
{completed, failed, stopped} + cfcf review (standalone)→idle. Triggered at the top ofstartReview(). Narrow trigger by design — only SA (scope work). Not reflect (retrospection), document (finalizing), or spec (PA, independent surface with its own chip from PR feat(ui): interactive-agent surfacing — History section + workspace card 'PA active' chip #51).refine_planaction.runReviewSync) doesn't flip — it transitions throughrunningalready.failedandstoppedstay distinct internally for audit-trail preservation.idle→\"ready/iterating\"in bothStatusBadge.tsx(web) andcfcf statusCLI. Internal value staysidle— zero state-machine churn.Part 2: 4 UX polish items (added during dogfood review)
1. History tab section headers:
(N)→(active: A | total: T). Surfaces "is something running RIGHT NOW" at a glance.2. Status tab PhaseIndicator subtitle:
\"Iteration 24\"→\"Iteration 24 (max: 28)\". The ceiling sits next to the live timer.3. Status tab Loop State block trimmed: iteration count + max moved to PhaseIndicator (above). Pause-every lives in Config tab already. Block replaced with conditional "Stall warning" — only renders when
consecutiveStalled > 0.4. Workspace card three changes:
workspace.loopStartedAtfield (server-enriched fromloopState.startedAtwhenactiveAgent === \"loop\"), rendered inside the loop chip via the existinguseElapsedhook.Test plan
bun run test— 1079 tests pass (+8 new for Part 1; Part 2 is pure presentation, no new tests)bun run typecheck— cleanarchitect-runner.test.tscoveringTERMINAL_LOOP_STATUSESexhaustiveness; flips from completed/failed/stopped; does NOT flip paused (load-bearing — preserves resume mechanics); does NOT flip running/idle; defensive undefined-status handlingcfcf review→ dashboard badge flips to "ready/iterating" +cfcf statusshows the new label\"● loop running · 12s\"ticking live; PA chip appears in a second row when PA is active\"Interactive sessions (active: 1 | total: 3)\"correctly\"Iteration N (max: M) · 15m 00s\"; "Loop State" block is gone unless consecutiveStalled > 0Versioning
Pairs naturally with PR #51 (also in
[Unreleased]). Recommend bundling both into v0.24.5 when tagging. The CHANGELOG already has both entries side by side.🤖 Generated with Claude Code