Skip to content

Daily-driver chat UX and fleet control plane - #59

Merged
marcelocantos merged 43 commits into
masterfrom
release/v0.8.0-daily-driver
Aug 2, 2026
Merged

Daily-driver chat UX and fleet control plane#59
marcelocantos merged 43 commits into
masterfrom
release/v0.8.0-daily-driver

Conversation

@marcelocantos

Copy link
Copy Markdown
Owner

Summary

Ships the local week-of-use stack as v0.8.0: daily-driver chat UX (stick-to-bottom, virtualisation, collapse), multi-agent control plane from owner chat, journeys isolation, and related fleet/MCP work. Local master was 43 commits ahead of origin (squash-only → single PR).

Release notes (draft for the GitHub release)

Jevons v0.8.0 — daily-driver chat & fleet control plane

First release cut with the product in real daily use: long-stream chat that
stays readable, multi-agent work from the owner surface, and a clearer path
to keep the fleet honest under fan-out.

Added

  • Fleet control plane (🎯T108): lineage tree, event-driven agent refresh, progress chrome, dead-agent recovery, stuck-turn self-heal, Build-plane standing brief on first worker send
  • Virtualised chat history (🎯T56): off-screen bubbles dematerialise so long transcripts stay light
  • Event push (🎯T34): jevons_event_push into threads with rehydrate / typed failure
  • Image paste (🎯T76): composer paste → /api/images[image:id] on the turn
  • target: filing asides (🎯T93/T95) + jevons_target_file; auto-close on __TARGET_FILED__
  • Continuation routing (🎯T99): cheap term match into matching attention threads
  • Send queue (🎯T113): Enter enqueues while busy; Ctrl+Enter interrupts
  • Self-test packs (🎯T110): orchestrator + probe surface
  • Journey suite isolation (Universe B), fleet kill/lineage, MCP reconnect (T60)
  • Attention threads prefix-first (T65), mermaid (T59), activity strip (T63/T64 plumbing)

Fixed

  • Stick-to-bottom: latched Track/Free (no 120px magnet); hysteresis; stream follow without fighting history scroll
  • Collapse of prior latest rematerialises in-view virtual shells (no blank gap until wheel)
  • Composer growth no longer covers latest reply (T70.1)
  • Height-ratio collapse (not char count); latest stays expanded mid-stream
  • Tool rawInput preserved via claudia pin (T64 path; summariser still thin for nested MCP args)

Changed

  • Journeys = live agent E2E (T107); meta-guards out of journey suite
  • Persona: fleet spawn, local-by-default delivery, target: ceremony, event push
  • Repo description updated for Grok ACP overseer (was Claude-centric)

Install

brew upgrade marcelocantos/tap/jevons
# or first time:
brew install marcelocantos/tap/jevons
brew services restart jevons

Test plan

  • go test -tags "sqlite_preupdate_hook sqlite_fts5" ./... (CI-identical)
  • make test-web
  • stream-scroll + virtual-list hermetic UI tests
  • CI green on this PR
  • After merge: tag v0.8.0, release.yml, brew upgrade, jevonsd --version

marcelocantos and others added 30 commits August 1, 2026 21:10
Boots a throwaway jevonsd on :13715 with temp state_dir and
jevonsmcp-journey so live Grok journeys never hit the daily
stream. make test-journey runs J1–J5; not part of make test.

Co-Authored-By: Grok <noreply@x.ai>
Bump claudia to de7e55e (name-keyed EnsureAgent — no workdir session
steal). agent_list/start use sessionDisplay so concurrent UUID-v7
peers no longer look identical. Hermetic regressions for same-workdir
two-name isolation and same-name idempotency (🎯T86).
Tallness is full offsetHeight > 1.5 × collapsed-preview height after
layout (tables/markdown no longer miss the gate). Measure only when the
bubble is in the DOM. Latest user and assistant still auto-expand (T66);
prior tall messages collapse (T77).
Master tip still had de7e55e; chat.go uses Parent. Pin 58cb7f5 so
make bullseye builds again.
Reconcile diverged master: base on origin (PR #54#58), restore
journeys (J6–J10), T104 persona, T96–T106 bullseye ledger, height-ratio
collapse already cherry-picked, Parent wire for fleet list.
Re-apply jevons_agent_kill and lineage helpers after origin rebase.
AGENTS.md and journey README state preferred E2E net, distinct from
make test, journey-or-exception, and Universe B port refusal. Hermetic
go test ./scripts/journey-suite locks doctrine markers + J1–J10 inventory
+ dailyPort 13705 refusal. Achieve T101.
Hermetic check calls refuseDailyPort(dailyPort) and expects error —
comment-only markers no longer keep the test green.
Owner: a user journey maps real interaction end-to-end and must talk to
an agent; cache after green is OK. Clarify AGENTS + journey README;
doctrine_test.go is explicitly not a journey. File T107; annotate T101.
Doc/inventory ratchets live in scripts/docratchet (prose ratchet, not
journeys). Daily-port refusal is unit-tested in portguard. journey-suite
has no unit tests — live E2E is make test-journey only.
Collapse measurement was repainting preview into the live body every
stream frame, thrashing scrollHeight and leaving stick-to-bottom pinned
at a stale mid-bubble offset (manual scroll bounced until seal).

Skip collapse while a bubble is streaming; restore pin-guard + 120px
slack + double-rAF; re-pin on seal/mermaid; end-sentinel IntersectionObserver
when follow is armed but bottom left the viewport; overflow-anchor:none.
Hermetic stream-scroll-test covers growth, scroll-up disarm, and free
scroll after seal.
Close the control-plane dependency graph for complex fleet work: RHS
who-started-whom tree with stable sibling sort, full registry list feed,
event-driven agents.json refresh (fsnotify → agents_changed), mid-turn
tool/fleet progress chrome, stuck-turn watchdog, NCA-named cross-tree
kill deny, persona Build/Ship + fleet-spawn + impatience/RSI doctrine.

Oracles: package tests (agents watch, lineage NCA, persona), UI suite
(fleet-tree, attention, stream-scroll, collapse), journey J6b MCP
reconnect + J8–J10 multi-agent paths on Universe B.
- T94: idle-bound stuck-watchdog; progress resets lastWorkingActivity;
  interrupt+status only after pure idle (no false-recover mid multi-agent).
- T85: SweepDeadAgents / deadRecoveryPlan on list+send; rehydrate or clear.
- T104 under fan-out: FleetStandingBrief on first jevons_agent_send;
  package TestEnsureFleetBriefInjectsOnce.
- J8b-po-worker-lineage-fanout: PO+worker parent lineage + brief ack.
- Reopen/re-achieve T108 only with skeptic-hardened evidence matrix.
SweepDeadAgents now runs through fleetSweepReg so tests inject
hasProc&&!Alive without an OS process. Oracles assert Launch (AutoStart
recover) and Stop (ephemeral clear / failed recover). agent_list and
agent_send prepend FormatDeadAgentReport and notify the overseer so
outage/recovery is not log-only.
Close T109 leaves without owner gates: journey step library (T102),
journey doctrine/cache notes (T107), thread integrity on status (T33),
tool-arg wire detail (T64), composer layout (T69/T70/T70.1), remove
TMUX panel (T73), highlight.js (T74), user quotes (T75), dictation tidy
(T80), GitHub path icon (T84), history redo Enter (T88), timestamp
tooltips (T91). Hermetic batch-t109-test + package/journey oracles.
claudia 20464ce passes ACP session/update params through as Event.Raw
so rawInput is not dropped by a narrow re-marshal. Bump go.mod and add
TestToolCallDetailFromClaudiaPreservedParams (product-shaped params +
regression guard that stripped re-marshal loses args). Re-achieve T64/T109.
Mid-stream freeze/bounce was still possible: flex-shrink let tall bubbles
under-report scrollHeight, collapse measurement still painted through the
live body on seal/expand, and end-sentinel IO only re-fires on transitions.

- flex-shrink:0 on #messages children so scrollHeight tracks content
- probe-based measureCollapse (no intermediate preview in live body)
- expanded/latest paints full once; stream bubble ResizeObserver re-pins
- pin-guard window + immediate post-paint pin on each stream frame
- stronger hermetic stream-scroll oracle (working chrome + tables)
End-sentinel IntersectionObserver re-pinned whenever the bottom left the
viewport while autoScroll was still true (within 120px slack). Wheel-up
moved a few pixels then snapped back.

Remove IO re-pin; growth follow stays on post-paint pin + stream
ResizeObserver. Disarm on wheel/touch scroll-up. Hermetic wheel-up
oracle asserts no snap-back.
- T34: Butler.PushEvent + jevons_event_push MCP (rehydrate, no silent fail)
- T56: virtualise off-screen chat bodies (virt-shell + content-visibility)
- T76: paste images → POST /api/images → [image:id] on the agent turn
- T93/T95: target: filing aside + jevons_target_file + __TARGET_FILED__ auto-close
- T99: cheap ThreadRoute continuation matcher on main send
- T40: design note only (needs claudia connect-mode) — left open
- Oracles: Go push/image/target-file tests; UI virtual-list + image-paste
Follow mode is sticky policy above the DOM, not nearBottom(120px):
- Track: growth pins to true bottom (re-check before each pin)
- Free: user owns scroll; stream growth never re-arms
- Enter: send/boot/arrive at bottom (16px entry ε only)
- Leave: wheel/touch/PageUp/scrollbar up (not layout clamps)
- Bookkeeping ignores pin, virtualise, and history-prepend scroll noise

Hermetic stream-scroll-test covers small leave mid-stream + re-enter.
marcelocantos and others added 13 commits August 2, 2026 16:58
After leave, geometry may re-enter Track only once the user has moved
clear of ENTER_BOTTOM_EPS (~16px). Removes the residual mid-stream snag
from leave → still-at-bottom scroll sensor → re-pin, without new policy
layers. Explicit enter (send/boot) still arms immediately.
leaveTrackBottom only blocks geometry re-arm while still inside the
entry band; a leave that already cleared it (e.g. jump to top) can
re-enter on the next arrival. Amends the hysteresis so hermetic
arrive-at-bottom still works.
When a prior latest reply collapses on a new request, height shrinks and
Track re-pins; off-screen virt-shells that enter the viewport were not
refreshed until the next user wheel (blank gap above the collapsed bubble).

- scheduleVirtualize after latest-expansion height changes
- virtualise on pin/bookkeeping scroll events too
- rematerialise shell before collapsing a dematerialised prior latest
- re-entrancy guard; keep expand toggle on dematerialise
- hermetic: virtual-list collapse gap; collapse-test stubs virt for DOM asserts
When the textarea auto-grows, the flex messages viewport shrinks but
scrollTop stayed fixed, so the bottom of the transcript slid under the
composer. Bump messages.scrollTop by the growth delta (pure policy in
composer_layout.js) and cover growth-without-cover with a hermetic unit
test — no Playwright.

Co-Authored-By: Grok <noreply@x.ai>
Add the thin vertical self-test slice: shared report schema, pack runner
(HTTP + MCP), layout probe (JevonsProbe.snapshot), and three gradable packs
(health-L1, composer-growth-L2, agents-parent-L1) for sites live|drill|ci.
Drill site documented as docs-only ensure-isolate path (T110.4).

Co-Authored-By: Grok <noreply@x.ai>
While an overseer turn is in flight, plain Enter enqueues the draft as a
follow-up instead of interrupting. Only Control+Enter interjects. Queued
items render above the composer with send-now/cancel; FIFO auto-drains on
turn seal. Alt+Up/Down cycles queue before request history.

Pure policy in web/scripts/send_queue.js + hermetic tests; wired into
make test-web.
closeTargetAside and dismiss set status=done (not parked); stack() is
open+parked only; archive()/archivedStack() keep completed asides
discoverable. Manual park still shows as intentional chips.

Hermetic: after file/close, stack excludes filing asides; archive lists
them. Re-attests T95 auto-close as dismiss-from-chrome + focus main.

Co-Authored-By: Grok jv-t95 <noreply@x.ai>
Pre-T95.1 auto-close used park(), so completed filing asides stayed in
localStorage as parked chips after refresh. On deserialize/load, map
purpose=file-target && status=parked → done; intentional manual parks
unchanged.
@marcelocantos
marcelocantos merged commit da81cac into master Aug 2, 2026
1 check passed
@marcelocantos
marcelocantos deleted the release/v0.8.0-daily-driver branch August 2, 2026 10:09
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