Skip to content

v0.6.0 — Workflow visibility

Choose a tag to compare

@anhyobin anhyobin released this 30 May 06:47
· 1 commit to main since this release

Summary

Workflow visibility. When a dynamic workflow fans out into a fleet of subagents, the monitor no longer goes dark. A new "Workflows" section at the top of the session detail view surfaces each run as a per-phase agent tree, and the menu-bar count gently pulses purple while a workflow is running.

The problem

Dynamic workflows (e.g. ultracode orchestration) spawn agents under a directory the app never read. SubagentLoader scans the flat subagents/agent-*.jsonl, but workflow agents live one level deeper at subagents/workflows/{wf_id}/agent-*.jsonl. A workflow could spin up a dozen agents and burn hundreds of thousands of tokens with zero signal in the UI.

What you get

  • Workflows section at the top of an expanded session — above the flat agent list, so the phase structure stays prominent.
  • Phase tree per workflow: each phase shows its agents; a completed phase gets a check, an in-progress one a spinner. Running workflows are expanded by default; completed ones collapse to a one-line summary you can click to expand.
  • Per-agent detail — click any workflow agent to expand its recent messages, modified files, and tool breakdown, exactly like flat subagents (the nested transcript path is handled transparently).
  • Live progress — a progress bar (completed agents / total) and running token total, refreshed on the same 5s cadence as the rest of the app.
  • Menu-bar signal — the active-session count tints purple and pulses while any workflow is running. A /goal in progress still takes priority (blue), so an explicit goal is never masked.

How "running" is detected

The run-state file workflows/{wf_id}.json is written only at completion (startTime + durationMs == timestamp), so its status field can't tell you a workflow is currently running. Detection therefore reads two signals:

Signal Source Meaning
Unfinished agent journal.jsonl — a started event with no matching result Primary "still running" signal
Definitive done workflows/{wf_id}.json status: "completed" Overrides everything — the file only exists at completion
Activity fallback agent-dir mtime within 60s Bridges brief gaps between journal writes

This ordering closes a subtle bug where a just-finished workflow could otherwise stay pinned as a spinner forever (its directory mtime never changes again once complete).

Under the hood

  • New: WorkflowInfo / WorkflowPhase / WorkflowRunStatus models, WorkflowJournal (pure running-detection parser), WorkflowLoader (disk loader with per-wf_id mtime caching), and the WorkflowSection view.
  • SubagentScan was extracted from SubagentLoader so the flat and workflow loaders share one identical JSONL scanner (DRY) — flat-subagent behavior is unchanged.
  • SubagentInfo, AgentRow, and AgentDetailView are reused for workflow-phase agents; AgentRow/loadAgentDetail gained an optional workflowId to resolve the nested transcript path, with consistent cache keys across read, write, and the live-refresh loop.

Tests

WorkflowJournalTests (running-detection: complete / unfinished / malformed-line / empty / result-before-started / dedup) and WorkflowLoaderTests (workflow-name parsing, phase mapping) cover the pure logic.

Note: XCTest requires the full Xcode SDK; on Command Line Tools–only machines swift build and bash scripts/build-app.sh succeed, while swift test runs on a machine with Xcode. The disk-loading path was additionally verified against real on-disk workflow transcripts.

Version

Info.plist: 0.5.0 → 0.6.0, build 8 → 9.

Full Changelog: v0.5.0...v0.6.0