Skip to content

Make focusing a service view edit mode - #1144

Merged
edwin-zvs merged 4 commits into
mainfrom
tui-service-view-focus-and-nav
Aug 2, 2026
Merged

Make focusing a service view edit mode#1144
edwin-zvs merged 4 commits into
mainfrom
tui-service-view-focus-and-nav

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

Three UX fixes to the TUI service create/edit view.

1. Focusing a service view is edit mode

There is no longer a read-only service view the operator has to step out of. Every path that selects a service — /serve, /service edit, the title menu, a click on the pane, a pane-focus move (C-x o, windmove), the session-list row — leaves the editor open on that service. Selection is the hook (select_service / focus_main_window), not each individual call site, so new entry points get this for free.

/serve [name] additionally dismisses the minibuffer. It's normally typed into the orchestrator panel, which stayed open and swallowed every keystroke aimed at the brand-new view.

Since Esc can no longer "close to view-only", it now means:

  • unsaved edits → revert to the saved definition;
  • nothing unsaved → hand keyboard focus back to the session list, leaving the editor open in its pane;
  • a service still being created → discard the draft.

The editor also stopped closing itself to make room for C-x chords; it stands aside for the chord continuation instead, so the view stays in edit mode across global commands.

2. Unsaved marker in the title

The pane title is now service: assistant* while what's on screen differs from what the daemon last confirmed. ServiceDialog carries a saved baseline, refreshed everywhere a daemon-confirmed definition is adopted. A Create-mode service counts as unsaved until its first save. Channel attach/detach goes straight to the daemon and is excluded from the comparison, so toggling a channel never leaves a stale dirty flag.

3. Channels row removed; Down walks State → Channels → Sessions

The "Channels" definition row was redundant with the Channels section below it, so the fields are now Name, Instruction, Harness, Model, Working dir, Routing, State. The view is one continuous navigable list: fields → channel catalog rows → routed session rows → wrap. Up/BackTab and C-n/C-p follow the same order (the old selected_field == 6 special case is gone).

Selection is modelled explicitly as ServiceDialogFocus::{Field, Channel, Session} rather than overloading a field index alongside a separate channel index. All channel-row actions are unchanged (Space attach/detach, a create, e/Enter edit, d delete, r rotate, p/o/y publication). New: Enter on a routed session row opens that session, matching a click. With an empty catalog the "no channels" line stays navigable so a/Enter can still reach channel creation by keyboard.

Spec

specs/0175-service-view-focus-is-edit-mode.md.

Testing

  • cargo test -p construct-cli — 1320 passed (existing service_view_* tests updated; new coverage for /serve landing focused + editing, the * marker appearing/clearing/reverting, and Down walking State → channel rows → session rows).
  • cargo test --workspace — one pre-existing failure, playbook_selection_fork_run_delivers_and_submits_prompt ("annotated block should shimmer"), which reproduces identically on main at aa3229e and is unrelated to this change.

Focusing a service view is now editing it. Every path that selects a
service — /serve, /service edit, the title menu, a click, a pane focus
move, a session-list row — leaves its editor open, so the old view-only
state (and the extra keystroke to leave it) is gone. /serve also closes
the orchestrator panel it was typed into, which used to keep swallowing
every keystroke aimed at the new view.

With no view-only state to close back into, Esc reverts unsaved edits
and, once there is nothing to revert, hands keyboard focus back to the
session list with the editor still open. A trailing `*` on the pane
title says whether what is on screen has been saved; channel
attach/detach goes straight to the daemon and never counts as unsaved.

The redundant "Channels" definition row is gone — the Channels section
below it already lists them. The view is now one navigable list:
fields, then channel rows, then routed session rows, wrapping back.
Enter on a routed session opens it, matching a click.
Renaming a service that has not been saved yet left the pane pointing at
the old name, so the view rendered "service definition is no longer
available" while the editor was still open behind it. The selection now
follows the Name field while a service is being created.
@edwin-zvs

Copy link
Copy Markdown
Contributor Author

After (recording)

service view: /serve lands focused in edit mode, the * marker, and Down walking State → Channels → Sessions

Recorded with vhs against an isolated daemon (/tmp/svcd) running this branch's debug build, with a pre-seeded assistant service whose HTTP channel took a real request (so the Sessions section has a real routed row). In order, the clip shows:

  1. /serve demo typed into the operator panel — the panel closes and the new service view is focused and already editing, title service: demo*.
  2. Typing -bot into Name (the pane follows the rename), then the instruction, then C-s — the * clears on save.
  3. Typing again re-marks the title demo-bot*; Esc reverts the edit and clears it; the footer switches between "Esc reverts edits" and "Esc to session list".
  4. C-x o + Up to the assistant row in the session list — selecting it opens its editor, no extra keystroke.
  5. Down from the last definition row (State) into the channel catalog row, then into the routed session row, with the contextual help following each.

The GIF blob is committed on this branch only so the link resolves; it is removed in the next commit (the refs/pull ref keeps the blob alive, so the link stays good).

@edwin-zvs
edwin-zvs merged commit 18c3c46 into main Aug 2, 2026
1 check passed
@edwin-zvs
edwin-zvs deleted the tui-service-view-focus-and-nav branch August 2, 2026 02:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant