Skip to content

Desktop facelift round 2: DMG feedback, Fusion backend, reply-last turns - #454

Open
plombeer31 wants to merge 10 commits into
facelift/integrationfrom
facelift/r2-feedback
Open

plombeer31 wants to merge 10 commits into
facelift/integrationfrom
facelift/r2-feedback

Conversation

@plombeer31

Copy link
Copy Markdown
Collaborator

Round 2 of the Soft Tactile facelift: everything Valerii reported after testing the facelift DMG (#450 UI with agent 0.6.1 from #451). This branch is based on facelift/integration (#450).

From the DMG test

First run

  • No build line on the title card or the rail, and no keycap hint strip under the action bar. The chords still work, and every verb the strip named is a button or a card.
  • The local model list shows a spinner while atag models list is out, instead of "reading the catalogue…".
  • The download screen always offers the "set up a cloud model" card beside "skip the wait", even when a cloud provider already exists.
  • Cloud model list (first run and composer popover): the picked row gets a tick on the right, and a double click is "Use this model". It fires once, not twice: both document listeners used to handle the row.
  • The closing screen shows a small comet crossing the middle of the column instead of a second "setting up…" line. It holds still under reduced motion.

Chat

  • One Stop while a turn runs: the composer's own button. The busy and waiting strips no longer carry a Stop pill.
  • No "Ready · " app-status strip under the transcript.
  • The agent's reply is the last row of its turn, live and when the chat is reopened. An approval now sits directly under the tool call that asked for it. It used to be appended below the live reply bubble. Reopened chats draw stored approvals as receipts; that needs the agent change in Desktop agent: merge main (v0.6.1) into atagdesktop #451.
  • Toasts have a dismiss cross, and the Settings button wears a house icon.
  • The mode popover drops the "A stance for this session…" paragraph.

Fusion as a backend mode

Parity with the latest atag's run-mode switch.

  • Backend popover: a Fusion row with the TUI's pre-flight blockers. The chip shows the effective mode.
  • Switching:
    • One whole-file config write per switch (activeTextProvider, runMode.mode, both seat pins, workers, managed.parallel), then the usual agent restart.
    • Choosing cloud or local now really leaves Fusion. Before, the stored mode survived the switch.
  • Seats under Fusion: the Provider chip is the orchestrator seat and the Model chip lists the orchestrator's models. A new Workers control lists local models, other cloud providers and "Download more models…", with ⇄ to swap the seats.
  • Settings › LLM: the run-mode card shows the effective mode and /runmode status, with workers 1–8 (default 2).
  • Other entry points: /runmode (bare, local|cloud|fusion, swap, workers N, status), Run › Where it runs…, and the first-switch intro in the transcript.
  • Approvals: fusion_fanout reads "fusion · fan-out" at level 4.
  • Live workers: a worker list with the busy strip, and one transcript line per worker event, fed by the agent's new fusion_worker SSE frame (Desktop agent: merge main (v0.6.1) into atagdesktop #451).
  • Prototype leftovers removed: the share slider, ctrl+r cycling and /run.

Also fixed on the way: a setup settle that was still in flight could close a flow opened after it (generation guard in obSettle). onboarding-mouse caught it on the merged build, solo.

Needs the agent from #451

The DMG pairs this desktop with the 0.6.1 agent built from desktop/sync-main-0.6.1. That branch now also carries:

  • the fusion_worker SSE frame
  • a stored approval record per tool result
  • text-only catalogue models no longer declared vision-capable (the repeated vision.describe 400s on deepseek-v4-flash)
  • shell results keep what the command printed (they were cut at 399 characters)
  • a reply that never streamed (stop message, loop breaker, non-streamed retry) still reaches a streaming client

Checks

Fixture = seed copy with ATOMIC_AGENT_STATE_DIR and a throwaway --user-data-dir.

Check Result Notes
Token check (all stylesheets) pass
Smoke, agent 0.6.1 528 pass / 5 fail The 4 known reds, plus skills tab: e toggle…, which reproduces only inside the smoke sequence: a standalone probe on 0.6.1 shows the disable written and listed as disabled
Smoke, dev agent 0.5.5 same 4 known reds Plus one Fusion check that needs agent ≥ 0.6.0, which strips llm.runMode below that
onboarding-mouse 61/61 (solo)
model-picks 29/29
drive-selector the 3 known custom-route fails
unverified 7/7
model-step 5/5
failure-line 5/5
visual pass
fusion.drive 17/17 Agent 0.6.1
turn-order.drive --receipts 8/8 Live and reopened both read user → tool → Approved → reply
Round-2 item driver 12/12, light and dark Trusted clicks, including a real double click
Packaged app out of the DMG, on a copy of a live desktop state (format 65) 9/9 Bundled agent connects; Tactile + Figtree; placeholder; house icon; no app-status strip; mode default → plan; Settings write with no version wall

Decisions to confirm

  • Composer row under Fusion. Captions and chevrons are hidden on the seat chips, and model ids drop the vendor prefix (full id in the tooltip), so seven controls fit.
  • Shell result budget. Raised from 400 to 2,000 characters / 40 lines, still under the per-result context limit.
  • Double click on a model row. It commits immediately, like "Use this model".

…osable toasts

From testing the facelift DMG:
- First-run screens: no build line on the title card or the rail, and no
  keycap hint strip under the action bar. Every chord it named is already a
  button or a card; the chords still work.
- Local model list: a spinner while `atag models list` is out, instead of
  "reading the catalogue…".
- Download screen: the "set up a cloud model" card is always offered next
  to "skip the wait", even when a cloud provider already exists.
- Cloud model list (first run and the composer popover): the picked row
  carries a tick on the right; a double click is "Use this model".
- Closing screen: a small comet crosses the middle of the column instead of
  a second "setting up…" line (held still under reduced motion).
- Chat: the "Ready · <last change>" app-status strip is no longer drawn;
  the approval / waiting / busy / switch-failed strips stay.
- Sidebar Settings button wears a house icon.
- Toasts have a dismiss cross (icon only, so their text is unchanged).
- Mode popover: the "A stance for this session…" paragraph is gone.

Smoke and cloud-setup driver follow: the title card has four children and
no build/strip, the cloud card count is 1 with a provider configured, the
Hugging Face clear chord is read from the chord table, and the local list's
way back is the action bar's Back.
From testing the facelift DMG: the busy strip and the waiting strip each
drew a "Stop" pill above the composer, next to the composer's own stop
button. The pills are gone; `.sendbtn.stop` (shown whenever a turn is busy
or pending) is the one Stop, and ⌘ . still aborts while a steer is being
typed. The parked-turn smoke check now asserts the strip carries no Stop.
Both document click listeners handled [data-wizmodel] while the first-run
flow was open, so the new double-click verb fired "Use this model" twice.
The composer's listener now leaves those rows to the first-run layer while
it is open. Caught by a driven double click (a single click only picked the
row twice, which is harmless).
…de and live workers

The composer's "Where it runs" gains fusion (last, with the TUI's
pre-flight line or "cloud plans · N local workers"), and the chip follows
the EFFECTIVE mode, resolved from config the way the agent resolves it:
a stored fusion whose orchestrator is not the active provider is cloud.

Under Fusion the row is fusion · orchestrator · its model ⇄ workers: the
provider control is the orchestrator seat (plus local-llama when a model
is on disk), the model control its catalogue, and a fourth Workers control
lists the downloaded models ("workers · on this machine") and the other
cloud providers ("workers · in the cloud"). ⇄ trades the seats; refused off
Fusion with "swap needs fusion — pick it first (`/runmode fusion`)".

Writes are RunModeOrchestrator's, main-process side (main/run-mode.ts
planners, backend-switch.ts enterFusion / swapFusionLegs /
setFusionWorkers / selectFusionWorkerModel): one whole-file write under
one hold of the config lock, then the restart every switch takes. Fixes
switching to cloud or local from Fusion: the stored runMode.mode now moves
with activeTextProvider, so the file really leaves Fusion; re-picking the
orchestrator's model keeps it and no longer stops the workers' daemon.

- first switch into Fusion puts fusion-intro.ts in the transcript
- /runmode (bare, local|cloud|fusion, swap, workers N, status) replaces
  the prototype /run; Run › Where it runs… Local/Cloud/Fusion in the menu
- Settings › LLM: effective mode, /runmode status line, workers 1–8
  (default 2) through the composer's path, with the TUI notice
- fusion_fanout reads "fusion · fan-out" at level 4
- `event: fusion_worker` frames: a live worker list under the busy strip
  (`title · model — tool|working|done`, no control of its own) and a
  transcript line per frame in the TUI's words
- gone: the share slider, ctrl+r run-type cycling, the fake runmode acts
- a slash line with arguments is sent by Enter (it was swallowed), and
  the command list keeps matching on the command word

Checks: `electron . --smoke --smoke-fusion` runs the 29 run-mode checks
alone; they also run in the full smoke. test/fusion.drive.mjs drives it
with trusted input on a configured copy.
…ened

Operator, 2026-09-15 DMG: "end agent results should be the last message
within the turn. At this moment approvals are the last ones".

startLiveTurn pushes the streaming assistant item when a turn opens and
every delta lands in it. Tool cards, reasoning and steers were spliced in
ahead of it, but onApprovalEvent and the notices raised mid-turn
(approval notes, steer notices) were S.log.push()ed after it, so a
finished turn read user -> tool -> reply -> approval.

- placeInLiveTurn: a row raised during this window's live turn goes before
  the streaming item; an approval goes directly under the newest card of the
  call that asked for it. Other sessions' requests append as before.
- approval notes sit under their card (placeAfterRow).
- openSession's mapping is sessionTurnsToLog: a tool_result's stored
  approvals (agent desktop/turn-fixes) become receipts under that call's
  card, so a reopened chat has the same shape as the live one; an older
  agent's chats show no receipt, as before. Reopened cards keep the store's
  truncated flag.
- smoke: two turn-order checks (live frames through onChatEvent /
  onApprovalEvent; stored rows through sessionTurnsToLog).
- test/turn-order.drive.mjs: a gated turn against a local stand-in provider,
  approved with a trusted click, then the app is relaunched and the chat
  reopened. Fixed build: 8/8 with the fixed agent, 7/7 with bundled 0.6.1.
  With onApprovalEvent back on S.log.push the live checks fail with
  'user -> tool -> assistant -> approval'.
The notice kept the TUI's `s` chord and `--parallel N` flag. It now says
to restart the local model under Manage › LLM › Local so it runs N at once;
the smoke and the Fusion driver expect the same sentence.
The backend pane and the external-route check expected three rows (cloud,
local, custom); Fusion is the fourth. The menu-tree count moves to 34 with
Run › Where it runs…, the deliberate addition that check is there to see.
obSettle awaits readiness, the agent scan and the stamp write. When the
flow was closed and opened again while one of those was out (the menu's
`onboarding`, or a driven re-stage), the stale settle carried on and closed
the new flow or raised a step on it. Each open now bumps OB.openGen and a
settle drops out once its generation is stale.

Found by onboarding-mouse.mjs on the merged round-2 build, solo: the import
preview had no action bar because the flow had already been closed under
it. 56/58 before, 61/61 after.
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