Skip to content

feat(web): chat timeline overlay + zero-brain Get Online + unified activity log#565

Merged
blackpc merged 7 commits intomainfrom
feat/chat-timeline-smart-deploy-ux
Apr 20, 2026
Merged

feat(web): chat timeline overlay + zero-brain Get Online + unified activity log#565
blackpc merged 7 commits intomainfrom
feat/chat-timeline-smart-deploy-ux

Conversation

@blackpc
Copy link
Copy Markdown
Contributor

@blackpc blackpc commented Apr 15, 2026

Summary

Two large UX upgrades to the application page, ready to replace the current
chaotic flat thread + the half-working Get Online button.

Three-layer chat timeline (no raw bubbles by default)

  • New `features/chat/CLAUDE.md`
    codifies the strict three-layer model: Raw events → Overlay grouping layer → High-level UI.
    Every rule is spelled out (single chronological column, no direct Layer 1 rendering,
    pure synchronous grouping, default collapsed friendly titles, optimistic rendering,
    extensible raw feed for system/debug events, no competing rendering paths) so future
    edits can't re-introduce chaos.
  • Client-side `computeTurnGroupsFromMessages` folds `rawMessages` into turn groups
    on every render — zero stale-query windows, zero race flicker.
  • Turn cards:
    • Completed (emerald check) collapsed by default, click chevron to expand raw bubbles.
    • In-progress (fuchsia gradient) shows ONLY the user request + a high-level
      `CondensedStreamingIndicator` ("Using tool: Bash", "Thinking…", "Working…"),
      never the raw assistant stream. Chevron expands to full raw history.
    • In-progress demoted to completed as soon as `status.isRunning` goes false, so
      finished conversations don't leave a stale "Working on your request…" card pinned.
  • `useChatRuntime` gains `hideAllMessages` — when true the flat assistant-ui thread
    returns an empty message list and the overlay owns the entire visible surface.
  • `ErrorRecoveryBanner` surfaces `effectiveStatus === Error` with a prominent red
    "Try again" button wired to `onResumeWorkflow`, replacing the silent red pill dead end.
  • Old `InitialRequestBubble` removed — `CurrentTurnCard` is the single anchor for
    every user request, pinned in its chronological position rather than at the top.
  • Server-side `GetChatTurnGroupsUseCase` + API route kept for CLI / TUI / external callers.
  • 8 unit tests cover the grouping use case (empty / step-tagged / live / multi-turn /
    long-message truncation / empty-message fallback / orphan assistant).

Zero-brain Get Online pipeline + unified activity log

  • `handleGetOnline` is one click, all defaults: ensure owners → create GitHub remote
    (slug + private) → pick first connected cloud provider → fire deploy. The ONLY stop
    conditions are missing tokens — GitHub connect goes to `PublishToGitHubModal`,
    missing provider opens `ConnectProviderModal` on the first enabled provider.
    No toasts, no panel side-trips, one click equals one specific next action.
  • Button pins on "Getting online…" throughout via `oneClickRunning` — no intermediate
    flicker as git-create and cloud-deploy trade batons.
  • Rocket gradient icon chip (fuchsia → purple → sky) on the "Get online" tone so it
    visibly pops as the primary call to action.
  • New `SmartDeployLogsDrawer` merges `GitRemoteCreate` + `CloudDeploy` + `RepoSync`
    entries into a single chronological timeline; each row wears a coloured kind chip
    (GitHub sky, Cloud fuchsia, Sync emerald).
  • Drawer hardened:
    • `AbortController` per-request timeouts (6s) so a hung endpoint can't freeze it.
    • `hasLoadedOnce` splits first-fetch from background polling so the spinner never
      flashes back to "Loading logs…" once data is on screen.
    • Manual `Refresh` button, and per-scope error surfaced as a soft banner while
      still rendering entries that did come back.
    • Empty state distinguishes "could not load" from "no activity yet".
  • Log icon button detached from the split button, rendered as a standalone 28×28
    muted icon next to the primary action. Always visible, not welded to the deploy.
  • Top bar buttons and tabs switched from `h-9` inside an `h-12` bar to explicit
    `h-12` so the row sits flush top-to-bottom with no outer padding band.

Miscellaneous

  • Monaco semantic validation disabled on `beforeMount` in the IDE tab, so opened
    TypeScript files no longer show "Cannot find module" red squigglies for every
    import. Syntax errors stay visible.
  • Sharper application card corners (`rounded-sm`) on both `ApplicationCard` and the
    "New application" placeholder — matched to the dashboard tile family.

Commits

  1. `fix(web): silence monaco unresolved import squiggles in ide editor`
  2. `feat(web): group chat turns and surface operation activity bubbles`
  3. `feat(web): one-click get online with unified smart deploy activity log`
  4. `feat(web): sharpen application card corners`
  5. `feat(web): three-layer chat timeline overlay with no raw bubbles`
  6. `feat(web): zero-brain get online with unified logs and detached icon`

Test plan

  • `pnpm typecheck` — green (verified locally)
  • `pnpm vitest run tests/unit/application/use-cases/interactive/get-chat-turn-groups.use-case.test.ts` — 8 tests green (verified locally)
  • Create a fresh application from the home page → verify the timeline renders
    as: in-progress turn card (only user request visible) → StepTracker → completed
    setup card, no raw `Thinking`/`Read`/`Output` bubbles leaking into the thread.
  • Send a follow-up iteration → verify the previous turn promotes to a completed
    emerald card and a new in-progress fuchsia card appears chronologically after it.
  • Click the chevron on any turn card → verify raw bubbles reveal without duplicating
    the user message.
  • Click the standalone activity log icon → verify the unified drawer opens and
    shows entries from all three operation scopes (GitHub / Cloud / Sync) merged
    by timestamp with coloured kind chips.
  • Click "Get online" on a fresh app with no GitHub / no cloud provider → verify
    each click opens the right inline connect modal (no panel side-trips).
  • Click "Get online" on a fresh app with both tokens on file → verify the full
    pipeline runs end-to-end with the button pinned on "Getting online…" throughout.
  • Open a `.ts` / `.tsx` file in the IDE tab → verify no red "Cannot find module"
    squigglies on imports, syntax errors still visible.
  • Trigger an application error (e.g. kill dev server mid-run) → verify the red
    error recovery banner appears at the top of the chat with a working "Try again"
    button.

🤖 Generated with Claude Code

shep-ai[bot] and others added 7 commits April 15, 2026 18:29
Disables monaco typescript semantic validation on beforeMount so
files opened in the ide tab no longer render every import as a red
"cannot find module" squiggle — the in-browser tsserver has no
project graph so its semantic diagnostics were pure noise. Syntax
errors are still surfaced; only unresolved-symbol noise is hidden.

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Adds server-derived user-turn grouping to the application chat plus
static publish/deploy activity bubbles, so the thread stays compact
and every long-running operation has a visible home in the
conversation.

- new GetChatTurnGroupsUseCase walks persisted messages server-side,
  returns completed turn groups (collapsed by default) and the
  latest in-flight turn as currentTurn (expanded by default), with
  hiddenMessageIds so the flat thread skips anything the cards own
- unit tests cover empty feed, step-tagged skipping, live turn
  promotion, chronological ordering, long-message truncation, and
  orphan assistant messages
- new /api/interactive/chat/:featureId/turn-groups thin route
  delegates to the use case
- TurnGroupCard renders completed cards with an emerald check and
  an in-progress card with a fuchsia gradient spinner, pinned
  "working on your request..." title, non-collapsible while live
- TurnGroupList hydrates cards from the main chat cache and renders
  the streaming indicator inline inside the in-progress card
- useChatRuntime accepts hiddenMessageIds and suppressStreamingIndicator
  options, exposes rawMessages and streamingState for the host
- ChatTab wires everything through a new applicationId prop so
  application chats get the full experience while repo and global
  chats are untouched
- OperationBubble polls existing operation_log_entries endpoints
  and renders a static chronological card per publish or deploy,
  shown after the thread so users see the full history in place

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Turns the "Get online" state into a fully autonomous pipeline and
ships a single chronological log surface for every long-running
operation the button can trigger.

- new SmartDeployLogsDrawer merges GitRemoteCreate, CloudDeploy,
  and RepoSync log entries into one timeline sorted by createdAt,
  each row tagged with a coloured kind chip (github sky, cloud
  fuchsia, sync emerald) so the source of every line stays obvious
- SmartDeployButton gets a persistent scroll-icon segment after the
  chevron that opens the unified drawer, always visible so users
  never have to hunt for a per-op log affordance
- handleGetOnline in SmartDeployCluster runs the full best-effort
  pipeline on a single click: ensure owners, create github remote
  with the default owner plus slugified name, refresh git status,
  auto-select the first connected cloud provider, initiate deploy
- the drawer auto-opens the moment any primary action fires and
  polls every 1.5s while running so the pipeline is never silent;
  toasts surface the exact reason when no github owner or no
  connected provider is available instead of reverting the button
- rocket tone plus gradient icon chip on the "Get online" button
  so it pops as the primary call to action; workingSource gains a
  getOnline variant that pins the label on "Getting online..."
  through the entire pipeline to kill intermediate state flicker
- oneClickRunning flag in useSmartDeployState dominates every other
  branch so the button cannot flash through deploy or save while
  the github create and cloud deploy trade batons
- top-bar buttons and tabs switch from h-9 inside an h-12 bar to an
  explicit h-12 so the row sits flush top-to-bottom with no outer
  padding band; explicit height avoids h-full-in-flex-items-center
  resolution quirks

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Drops the cards from rounded-2xl (16px) and rounded-xl (14px) to
rounded-sm (2px) on both the live ApplicationCard and the new
application placeholder so every tile on the dashboard has the
same sharp vs-code-tab edge. Fixes a visual mismatch where the
placeholder stayed rounded after the main card was tightened.

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Unifies the application chat around a single chronological
timeline driven by the three-layer model documented in
features/chat/CLAUDE.md: raw events (Layer 1) flow through a pure
synchronous grouping layer (Layer 2) that produces high-level
friendly cards (Layer 3). Default view shows only the user
request plus a high-level activity indicator — every raw tool
event is hidden behind a progressive-disclosure chevron.

- new CLAUDE.md in features/chat/ codifies the three-layer rules
  with explicit do/don't guidance, file responsibilities, and
  anti-patterns so future edits cannot break the flow
- client-side computeTurnGroupsFromMessages replaces the stale
  server query for the web view, runs synchronously on every
  render via useTurnGroupsView so the overlay updates in the
  same tick as SSE deltas arrive
- in-progress card is demoted to completed when status.isRunning
  goes false, so finished conversations never leave a permanent
  "Working on your request..." card pretending work is still in
  flight
- useChatRuntime gains hideAllMessages option — when true the
  flat assistant-ui thread returns an empty message list and the
  overlay owns the entire visible surface, closing the last gap
  where raw bubbles could leak
- TurnGroupCard splits into a condensed slot (user request plus
  friendly streaming indicator, default visible) and a details
  slot (raw thinking / read / output bubbles, revealed on
  chevron click); the user message never renders twice
- new CondensedStreamingIndicator shows only a spinner plus a
  high-level activity line (tool status, "Thinking...", "Working
  ...") — never the raw assistant stream text, so the layer rule
  holds through the whole pipeline
- ErrorRecoveryBanner surfaces effectiveStatus failures at the
  top of the chat pane with a prominent Try again button wired
  to onResumeWorkflow, replacing the silent red pill dead end
- old InitialRequestBubble removed; the CurrentTurnCard is now
  the single anchor for every user request, pinned in its
  chronological position rather than at the top
- chronological ordering enforced: error banner -> StepTracker
  -> completed turn cards (oldest first) -> in-progress turn
  -> operation bubbles -> pending interaction

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Finalises the one-click "Get online" pipeline, detaches the
activity log button from the split, and hardens the unified logs
drawer against hung requests.

- handleGetOnline is fully zero-brain: ensure owners, create the
  github remote with the default owner plus slugified name, pick
  the first connected cloud provider, fire deploy. The ONLY stop
  conditions are missing tokens — github connect goes to the
  PublishToGitHub modal, missing cloud provider opens the
  ConnectProviderModal on the first enabled provider. No toasts,
  no panel side-trips, one click equals one specific next action
- activity log icon button is detached from the SmartDeployButton
  split, rendered as a standalone 28x28 muted icon next to the
  primary action so it reads as a neighbour, not a welded third
  segment
- SmartDeployLogsDrawer gains AbortController per-request timeouts
  (6s), splits hasLoadedOnce from background polling so the
  "Loading logs..." spinner only appears on first fetch, adds a
  manual Refresh button, and surfaces per-scope errors as a soft
  banner while still rendering the entries that did come back —
  no more stuck-on-loading drawer
- Drawer empty state distinguishes "could not load" from "no
  activity yet" so the user knows whether to retry or just wait
- configure state kind removed from use-smart-deploy-state — the
  button stays "Get online" in every pre-live state, the
  pipeline itself handles the token gates inline

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Eliminates the last two client-side polling paths in the application
page (refetchInterval on the loader query, setInterval in the activity
drawer) and replaces them with typed, backend-owned SSE deltas. The
server remains the sole poller; the client patches state in-place as
typed events arrive.

Backend:
- New NotificationEventType values ApplicationUpdated + OperationLogAppended
  with scoped payload models, plumbed through TypeSpec codegen.
- New IOperationLogEventBus port + in-memory adapter. The SQLite
  operation-log repo publishes after each successful INSERT so clients
  see every appended log line within a tick, not on a 2s poll.
- StreamAgentEventsUseCase diffs applications rows per poll and
  re-emits bus publishes as notifications. Per-connection cache seeds
  silently on reconnect.

Client:
- useApplicationUpdate + useOperationLogAppend selector hooks on the
  shared agent-events context.
- ApplicationPageLoader patches the React Query cache in-place on
  event, zero HTTP refetch. Removes the prior invalidate-on-any-event
  hack.
- SmartDeployLogsDrawer appends new entries with dedup by id. Initial
  hydration fetch on open is preserved; setInterval is gone.

Also bundles prior chat-timeline / smart-deploy polish on the branch:
scaffold stdout streaming to operation logs (enables the ApplicationSetup
kind to populate the drawer), bubbled chat-timeline groupings, and
AppTopBar / SmartDeployButton / SmartDeployCluster layout polish.

Spec: specs/090-application-sse-deltas/
Invariants: DB is source of truth; SSE is a hint. Missing an event is
never fatal — next read rehydrates from the row. No client timers.

Tests: 20 new spec-scoped unit tests. Full suite green
(6604 unit + 763 integration). typecheck + lint + tsp + storybook
clean.

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Dev Release Published

Artifact Version Install
npm 1.188.0-pr565.d303bfc npm install -g @shepai/cli@1.188.0-pr565.d303bfc

Published from commit d70fec4 | View CI

@blackpc blackpc merged commit b48e643 into main Apr 20, 2026
20 checks passed
@blackpc blackpc deleted the feat/chat-timeline-smart-deploy-ux branch April 20, 2026 15:48
blackpc pushed a commit that referenced this pull request Apr 20, 2026
# [1.189.0](v1.188.0...v1.189.0) (2026-04-20)

### Features

* **web:** chat timeline overlay + zero-brain Get Online + unified activity log ([#565](#565)) ([b48e643](b48e643)), closes [Hi#level](https://github.com/Hi/issues/level) [hi#level](https://github.com/hi/issues/level)

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
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