Commit Graph
16 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.8 b399acedbf surface Claude Code Workflow runs in convo + sidebar (T-416)
A `Workflow` tool-use launches its multi-agent run in the background and
returns immediately; the real fan-out arrives out-of-band on stream-json
`type:"system"` task_* events (task_started / task_progress / task_updated /
task_notification) keyed by the launching tool-use id — which clide was
dropping. (Wire shape captured by two live stream-json probes; recorded on
the ticket.)

- workflow_run.dart: a pure, Flutter-free WorkflowRun/WorkflowAgent model
  that folds those events (phases, per-agent start→progress→done deltas,
  usage) into a snapshot.
- StreamJsonSession recognises the events, accumulates a
  Map<toolUseId, WorkflowRun>, and exposes `workflows` + `workflowsStream`.
- A `Workflow` tool-use with a live run renders a dedicated run card —
  phase groups, per-agent rows with spinner/check status, usage, and the
  script — falling back to the generic tool card pre-progress or on reload.
  The run breaks the activity cluster so it's always first-class (like T-342).
- The sidebar Activity tab adds a WORKFLOWS section: one row per run with its
  done/total agent count, tinted by running/done state.

Closes T-416 and the T-410 epic (all children done).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:44:41 +02:00
jpmschweitzerandClaude Fable 5 0fd8a241db Activity tab: session controls + live usage block (T-415)
The Activity tab gains the power-panel's session strip and a usage block:

- SESSION controls (clear / compact / fork / resume + refresh-usage)
  publish their slash command on builtin.claude/command — the same path
  as typing it, so /clear semantics (and any future confirm behavior)
  live in exactly one place.
- The usage block revisits T-158's "blocked on upstream": probed against
  claude 2.1.175, a forwarded /usage IS answered headless, free
  (num_turns 0), as parseable text. parseUsageText() extracts session /
  week / week-Sonnet percentages (timezone parentheticals stripped); the
  sidebar watches the primary session's synthetic output for
  usage-shaped responses and renders them as a USAGE section. Refresh is
  user-initiated (the control sends /usage) — no polling, no background
  calls (D-64).
- The runtime row gains the session's effort level (T-412's status
  field).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:04:55 +02:00
jpmschweitzerandClaude Fable 5 959ec7ddc4 Config tab → live control panel; sidebar styling pass (T-414)
The Claude sidebar's settings table was read-only 12px rows. It becomes
the power panel's core:

- model / effort / permission-mode rows are popover controls on the
  owned anchored-menu primitive (ClideAnchoredOverlay + ClideMenu),
  showing the LIVE session values (SessionStatus, falling back to the
  probe/settings) with the active option marked.
- Picking an option publishes the explicit slash command (`/effort
  xhigh`) on builtin.claude/command; the PRIMARY pane subscribes and
  executes it through the same _send routing the composer uses — the
  control and the typed command are one code path (D-6), which is also
  what lets the sidebar drive /effort's respawn flow without reaching
  into the pane. Only the primary pane listens (controls target the
  primary session; a second listener would double-execute).
- Styling pass (user request): shared meta tables move from 12px-
  everything to 13px labels/values, accent-coloured section headers,
  wider row pitch; control rows get hover affordance + caret.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:25:49 +02:00
jpmschweitzerandClaude Fable 5 52d90be730 own the open-in-clide command family (T-413)
/permissions, /status, /config, /mcp, /agents, /hooks, /memory, and
/help move from the TUI-only notice catalog to clide-owned commands
with real behavior:

- /permissions <mode> sets the mode over set_permission_mode; bare
  /permissions opens a picker in the interaction zone — the same card
  /model and /effort use (kPermissionModes, bypass last and explicit
  per T-181).
- /status → Claude sidebar Activity tab; /config, /mcp, /agents,
  /hooks → Config tab. The pane activates the claude.meta sidebar tab
  and publishes a meta.tab message; the sidebar subscribes and switches
  its sub-tab — the same MessageBus addressing `clide ui open` uses
  (D-6), so the CLI can drive it too.
- /memory opens the workspace CLAUDE.md via editor.open.
- /help renders a local summary card (clide-owned + advertised
  commands) — the CLI's TUI help doesn't exist headless.

The catalog keeps empty-hint entries for these tokens as safety nets if
they're ever removed from owned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:06:10 +02:00
jpmschweitzerandClaude Fable 5 a919d79ce1 watch the claude process: drain stderr, surface exit (T-361)
The session observed its child only via stdout. Two failure modes:
with --verbose the CLI chats on stderr, and an undrained 64KB pipe
blocks the child mid-turn with zero diagnostics; and nothing watched
the exit code, so a crashed process just looked thoughtful forever.

ClaudeStreamJsonProcess now drains stderr from construction into a
bounded tail buffer, and StreamJsonSession watches exitCode: on death
it flips busy off, clears any unanswerable pending prompt, and emits
a SessionEnd (exit code + stderr tail) — replayed via session.end for
late binders. The pane reports the exit in its status line and logs
the stderr tail; a deliberate dispose suppresses the watch so /clear
and teardown don't read as crashes. Test fakes extend the process
base instead of implementing it, so its defaults carry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:54:12 +02:00
jpmschweitzerandClaude Opus 4.8 6d0ebab721 chore: adopt Dart 3.9 toolchain — honest floor + tall-style reformat (T-353)
Raise the declared minimums in pubspec.yaml to what our deps already
require: Flutter >=3.35.0 / Dart >=3.9.0 (was 3.19.0 / 3.5.0). alchemist
0.12 needs Flutter 3.32; Dart 3.9 first ships in Flutter 3.35, so 3.35 is
the binding floor. Pin the exact build toolchain in .fvmrc (Flutter
3.44.1).

Moving to the Dart 3.9 language level switches `dart format` to the new
"tall" style and enables two new lints. This commit is the resulting
mechanical churn, isolated from any behaviour change:
  - whole-tree `dart format` reformat (tall style)
  - `dart fix` for unnecessary_underscores + use_null_aware_elements

No runtime behaviour change; `make test` green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 12:11:53 +02:00
Jeroen SchweitzerandClaude Opus 4.8 6337bec152 make Claude sidebar sub-tabs keyboard-activatable
The Activity / Team / Config sub-tabs were built on a raw GestureDetector,
so Tab traversal skipped them and Enter/Space did nothing — a gap against
the repo's a11y contract. Switch to ClideTappable (focusable, Enter/Space
activates) wrapped in button + selected semantics, and add a test that
drives the switch via ActivateIntent rather than a pointer tap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:19:35 +02:00
jpmschweitzerandClaude c56b60622b open markdown files in the reader, not the editor
The files panel and the Claude Config tab called ipc.request('editor.open')
for every file, which targets the editor — so a .md click never reached the
right-side markdown reader (it opens only when something publishes
('builtin.markdown','selection')). Route .md clicks from the files panel
(tree + filtered rows), the Config tab's file-backed rows, and .md wiki links
in the viewer to that channel; non-.md files still open in the editor. Also
remove the dead DaemonEvent fallback that listened for 'editor.buffer_activated'
(the registry emits 'editor.active-changed').

T-187.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-31 16:16:34 +02:00
jpmschweitzerandClaude 494a6f13a5 build the Config sidebar tab
The Config sub-tab grows from a static settings table into a browser of
the Claude environment: the pinned settings table stays, and below it
expandable accordions list the full (never-truncated) sets of skills,
agents, commands, hooks, permissions (grouped + colour-coded by allow/
ask/deny), and MCP servers. File-backed entries are clickable and open
their .md via editor.open. ClaudeConfig gains agents, hooks, and
mcpServers loaders plus path fields on skills/commands, kept live by the
existing .claude file watcher.

T-183.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-31 11:30:02 +02:00
jpmschweitzerandClaude a0636c2e5a add the team chat inbox over the broker
Renders broker traffic as a chat timeline and makes the user a first-class
participant. The broker grows a Stream<TeamMessage> and a recipient field,
auto-registers a virtual `user` member, and gains sendAsUser. A Flutter-free
TeamChatModel (owned by the orchestrator) accumulates the feed and exposes
postAsUser with @-routing (a new at_commands helper mirroring slash) and an
optional interrupt that cancels the target's turn before delivery. One model
backs two surfaces: a compact cockpit widget that pops out into a full
workspace chat pane. CLI parity via clide.team-chat.open / .post.

T-180.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-31 10:49:04 +02:00
jpmschweitzerandClaude e3c0b0146b fork a Claude conversation into a new pane
Adds fork-into-a-pane: /fork in the composer, a roster Fork button, and a
clide.agent.fork command all branch a session via
--resume <source> --fork-session, so the branch gets its own claude
session id and diverges without touching the original. SpawnSpec/
ManagedSession gain forkSourceSessionId; the orchestrator selects the
fork argv via a new forkSessionArgs helper; the session host opens the
fork as a new secondary pane.

The branch's real claude session-id (assigned by --fork-session, arriving
in the init event) is not yet captured back — tracked as T-185.

T-172.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-30 23:34:50 +02:00
jpmschweitzerandClaude 2888efbe5f add per-agent permission-mode badge to the cockpit roster
Each roster row shows a D/A/P mode badge reflecting the session's live
permission mode. Click cycles the safe trio default -> acceptEdits ->
plan and sends a set_permission_mode control_request to that session
(mirrors interrupt(); fire-and-forget). bypassPermissions is a footgun,
so it is reachable only on Shift-click and behind an inline confirm. A
clide.agent.set-permission-mode command gives the CLI parity.

T-181.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-30 23:25:07 +02:00
jpmschweitzerandClaude 4220d97a49 add the Claude team cockpit: roster controls + live task list
The meta sidebar's Team tab becomes a control surface for clide-managed
agents instead of a read-only roster. Each row gains show/hide, mute,
close, and inject-a-message; a live task list renders from the broker
with reassign. The broker grows a Dart change-stream (kept Flutter-free
for dart test) plus tasks/reassign; the orchestrator gains mute/unmute,
injectMessage, and member-name session resolution. Every new UI action
has a matching clide command (D-6 parity).

T-171.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-30 23:11:22 +02:00
jpmschweitzerandClaude Opus 4.7 25c11c1edb split the Claude meta sidebar into Activity / Team / Config sub-tabs
test / unit + widget + golden + a11y (push) Failing after 29s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 34s
The sidebar had outgrown one scroll (stats + roster + config don't fit). A
sub-tab strip now switches between three surfaces: Activity (usage stats +
the primary session's live runtime), Team (the member roster, auto-fronted
when a team spawns and otherwise quiet), and Config (the Claude-environment
settings table over ClaudeConfig).

Activity and Config render their key→value rows through one shared table
(same label column + row pitch + header style) so toggling tabs doesn't move
anything. The expandable skills/agents/commands/permissions/MCP browser on
the Config tab is the follow-up (T-183). Exposes StreamJsonSession.status so
the runtime row can seed from the session's current state.

T-182, D-77.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:07:45 +02:00
jpmschweitzerandClaude Opus 4.7 6e4f357c09 show live per-member status in the team sidebar
test / unit + widget + golden + a11y (push) Failing after 31s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 29s
The teammate status was emitted by each TranscriptPublisher's statusStream
but never reached the bus. The observer now forwards it onto a shared
member-status channel ({agentId, model, permissionMode, contextTokens});
the meta sidebar subscribes and folds each member's live permission-mode
and context-token count into its roster row. No re-tailing — reuses the
existing stream (D-75).

T-157.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 22:57:01 +02:00
jpmschweitzerandClaude Opus 4.7 3038cd5eed add Claude meta sidebar — activity + team roster
test / unit + widget + golden + a11y (push) Failing after 28s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 25s
An always-pickable left-panel tab. Shows Claude activity read from
~/.claude/stats-cache.json (latest day's messages/sessions/tool-calls +
lifetime totals, polled) and, when a tmux agent team is running, a roster
of its members (colour · name · agent type · model) from the observer's
join/left events — nothing re-tailed here.

Scoped down from the original ticket: the account/team token budget isn't
programmatically exposed under subscription auth (TUI-only; upstream
#44328) and live per-member status needs the teammate status stream wired
onto the bus — filed as T-158 and T-157 respectively.

T-141.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 22:49:37 +02:00