Skip to content

Split: backend runtime/session updates + frontend shell refactor#222

Merged
yyovil merged 36 commits into
aoagents:mainfrom
yyovil:split/frontend-ui-clone
Jun 13, 2026
Merged

Split: backend runtime/session updates + frontend shell refactor#222
yyovil merged 36 commits into
aoagents:mainfrom
yyovil:split/frontend-ui-clone

Conversation

@yyovil

@yyovil yyovil commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • feat: align backend session lifecycle with workspace runtime updates
  • refactor: replace spawn modal with shell-native worker controls
  • chore: add shared daemon launch helper and docs updates

yyovil and others added 30 commits June 10, 2026 10:55
Replaces the skeleton Electron frontend with a full React 19 + TypeScript
renderer (Vite, electron-forge, contextBridge preload), plus the backend
additions it needs.

Renderer:
- TanStack Query + EventTransport (CDC SSE on /api/v1/events)
- TanStack Router file-system routing (hash history for the file:// origin)
- Tailwind + shadcn/ui, react-resizable-panels, Zustand UI state
- @xterm/xterm per-session PTY over /mux WebSocket + WebGL addon
- openapi-typescript + openapi-fetch types off openapi.yaml
- electron-forge packaging + update-electron-app auto-updater
- Vitest + RTL · Playwright

Backend:
- cors.go — allowlist-only CORS, handles Private Network Access preflight
  for app:// renderer -> loopback daemon
- session.TerminalHandleID exposed in domain + OpenAPI spec
- project.Path added to OpenAPI spec, service, store, and tests

DESIGN.md documents the emdash-matched dark UI (tokens, blue accent, status
glyph spec, orchestrator-led layout).

Co-authored-by: Ashish Huddar <ashish.hudar@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: b1e334c1e54a
XtermTerminal becomes a self-contained, dependency-free renderer component
(yyork's xterm-terminal.tsx pattern):
- Nothing writes into the buffer at mount — status/empty-state is DOM chrome.
  Fixes the startup crash (xterm Viewport.syncScrollArea reading renderer
  dimensions on a zero-sized panel).
- Multi-trigger fit (rAF + 50/250ms settle + fonts.ready + ResizeObserver):
  FitAddon must re-measure after monospace font metrics settle or it
  over-counts columns. xterm only fires onResize on real grid changes, so
  repeated fits don't spam the PTY.
- Unicode11 width (agent CLIs print emoji/wide glyphs), WCAG-AA minimum
  contrast, WebGL→canvas renderer fallback, full ANSI-16 palette per DESIGN.md.

TerminalPane keeps ONE terminal instance across session switches — the
attachment effect re-points the mux and RIS-resets the screen instead of
remounting (a keyed remount drops the warm GPU surface mid-switch).

useTerminalSession: resize debounced 100ms trailing (one SIGWINCH per pane
drag, not dozens); the "Attaching…" writeln is gone (banner chrome covers it).

Test infra: vitest never loaded vite.renderer.config.ts after the forge split
(it only auto-discovers vite.config.*) so the whole suite ran without jsdom.
Point the test script at the config and type it via vitest/config. Fix
pre-existing type errors (notarytool field, maker-zip config, named
updateElectronApp import). 97/97 passing, typecheck clean.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: eb0f94fcf914
Two bugs found spawning a worker from the modal:

1. "Based on: main" sent branch:"main" in the POST, but git can't add a
   second worktree on a branch already checked out (main lives in the repo
   root) — the daemon returns 409 BRANCH_CHECKED_OUT_ELSEWHERE. The base
   branch must be OMITTED so the daemon mints a fresh ao/<sessionId> off the
   project default. Only a non-default branch (resume an existing session
   branch) is sent through.

2. The daemon's error body is {error,code,message,requestId}; App.createTask
   did String(error) on it → the modal showed "[object Object]". Add
   apiErrorMessage() to unpack message/error from the structured body, with
   Error/string fallbacks.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: d3e718d393cd
The terminal now resolves its fontFamily from the --font-mono CSS token
(styles.css @theme), which leads with the Nerd Font family stack
(JetBrainsMono Nerd Font Mono first). Agent TUIs get powerline separators
and file-type icons; box-drawing stays renderer-rasterized.

Mirrors yyork exactly: no font is bundled — the stack names system-installed
Nerd Fonts and the browser picks the first present, falling back to plain
monospace (no icon glyphs) when none are installed.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 28120fa527a7
Prep for the route-parity port: build new screens from shadcn primitives.
- components.json: Tailwind v4, css=styles.css, cssVariables, lucide, "@/" aliases
- "@/" -> src/renderer alias in tsconfig (paths) + vite (resolve.alias)
- fill the shadcn token gaps in @theme (card-foreground, input, destructive,
  destructive-foreground) mapped to existing emdash tokens so `shadcn add`
  components render on-brand without touching the design system
- add Card primitive (first use: Phase 1 board)

Did NOT run `shadcn init` (it would overwrite styles.css and wipe the emdash
tokens); the @theme already maps shadcn semantic names onto emdash raw tokens.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 9b9c8391e52c
…cts vocab)

Phase 0 of the route-parity port. Replaces the single state-driven <App> with
real TanStack Router pages behind a persistent _shell layout, the foundation
every ported screen builds on.

- _shell.tsx: pathless layout owning the Sidebar + shared state (workspace
  query, daemon status, spawn modal, create project/task, theme, shortcuts);
  child routes render into <Outlet>. The daemon-status effect runs once here.
- Router owns selection: ui-store sheds view/selectedSession/selectedWorkspace
  (now route params); keeps only theme/sidebar/workbenchTab. Sidebar/SideRail
  navigate via router and read active state from useParams.
- Routes (projects vocabulary): / -> SessionsBoard (new board home, replacing
  the orchestrator-terminal home), /projects/$projectId -> scoped board,
  /projects/$projectId/sessions/$sessionId and /sessions/$sessionId ->
  SessionView (Topbar + terminal + git rail).
- Terminal persistence: it lives on the session route, so session->session is
  a param change (TanStack keeps the route mounted -> mux re-points, no
  remount); leaving for the board unmounts it and the server ring replays on
  return.
- shell-context.ts hands daemonStatus/openSpawn/create* to route content.

Removed the monolithic App.tsx (+ App.test.tsx, whose create/spawn coverage
moves to route/hook-level tests in Phase 5) and the old workspaces.* routes.
shadcn Card used for the board cards. typecheck clean, 91 tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: d10b22f0d841
Phase 1: SessionsBoard becomes the real kanban, porting agent-orchestrator's
getAttentionLevel state machine (packages/web/src/lib/types.ts) as a pure
function rebound to reverbcode's SessionStatus.

- attentionZone() buckets a session into urgency-ordered zones — merge (one
  click to clear, leftmost) → action (needs-you: needs_input/ci_failed/
  changes_requested, the collapsed respond+review) → pending (waiting on
  reviewer/CI) → working → done (archive).
- Board renders a horizontal column per non-empty zone; cards navigate into
  the session route. shadcn Card for cards. Styled to DESIGN.md (emdash
  hairlines, status dots, accent), not agent-orchestrator's tokens.
- 13 zone-mapping unit tests. typecheck clean, 104 tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: d315acacf784
/projects/$projectId/settings — a settings page on reverbcode's own
ProjectConfig shape (not agent-orchestrator's agent/runtime/tracker/scm,
which the Go daemon doesn't have). Reuses agent-orchestrator's form structure:
read-only identity card + editable config.

- Reads GET /api/v1/projects/{id} (config + identity), saves via
  PUT /api/v1/projects/{id}/config. The PUT replaces the whole config, so the
  form merges edited fields over what loaded (keeps env/symlinks/postCreate
  it doesn't expose).
- Editable: defaultBranch, sessionPrefix, default worker/orchestrator agent,
  model override. React Query for load + mutation with inline save state.
- shadcn select + label added; settings gear in the project board header.

typecheck clean, 104 tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 0633ebde603b
Ports agent-orchestrator's SessionInspector onto reverbcode's SessionPRFacts
(GET /api/v1/sessions/{id}/pr -> {prs: SessionPRFacts[]}). Mounts above the
git rail on the session route; renders nothing when the session has no PR.

- Shows PR number + state badge, and CI / mergeability / review facts with
  tone derived from the fact string (pass/fail/pending), plus an unresolved
  review-comments flag.
- React Query, fetched only when the session has a PR.

Completes Phase 2 (project board reuse + settings + inspector).
typecheck clean, 104 tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: c75dadfd45b8
/prs — a PR board ported from agent-orchestrator's PullRequestsPage. The Go
daemon has no PR-list endpoint, so rows are derived from session PR fields
(every session carries pullRequest), sorted open/draft above merged/closed.

- Per-row Merge (POST /prs/{number}/merge) and Resolve comments
  (POST /prs/{number}/resolve-comments) mutations with inline result; clicking
  a row opens the session (whose inspector has the full CI/review facts).
- shadcn Table; "Pull requests" + "Review" nav added to the sidebar footer.
- /review + /reviews routes added as placeholders (the reviews board needs a
  daemon backend — Phase 4); /reviews redirects to /review.

typecheck clean, 104 tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 3526d847c568
The long pole: the Go daemon had no reviews surface, so /review needed a
backend. Adds one, mirroring agent-orchestrator's reviews feature.

Backend:
- internal/service/review: in-memory reviews Manager (Run + Finding types,
  List/Execute/Send). Execution is not yet wired to a real review agent —
  Execute records a pending run so the surface is live; agent-backed findings
  + persistence are a follow-up (documented in the package).
- ReviewsController (GET /reviews, POST /reviews/execute, POST /reviews/{id}/send),
  wired through api.go + daemon.go (constructed, not nil — actually serves).
- genspec: reviewOperations() + tag + schemaNames; openapi.yaml + schema.ts
  regenerated. apispec parity/drift tests pass, go build + go test green.

Frontend:
- ReviewDashboard reads GET /reviews, lists runs with status + findings, lets
  you pick a worker and Run review (execute) and Send a run. Replaces the
  placeholder /review route. shadcn Card/Badge/Select.

Verified live: GET /reviews -> 200, POST /reviews/execute -> created run.
typecheck clean, 104 frontend tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: ce16c62dfdb0
…erage

- Route loader: _shell prefetches the workspace list via
  queryClient.ensureQueryData (parent loader runs before children), pairing
  with defaultPreload: "intent" so a hovered nav target is warm on click.
  workspaceQueryOptions exported so the loader and hook share one cache.
- Restored the spawn coverage dropped with App.test.tsx as a focused
  SpawnWorkerModal test: the base-branch-omission regression guard (the 409
  fix) + the empty-prompt gate.

Full parity surface green: 106 frontend tests, typecheck clean, backend
build + vet clean, all daemon endpoints 200.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 284ae668ffea
Per explicit request to mirror agent-orchestrator's app exactly (overriding
DESIGN.md/emdash for this screen). Rebuilds SessionsBoard from its actual
source (Dashboard + AttentionZone + SessionCard + mc-board.css), using its
exact tokens and values:

- 4 equal-width columns (grid 1fr), left->right flow: Working -> Needs you ->
  In review -> Ready to merge (SIMPLE_KANBAN_LEVELS), always rendered; "done"
  archived to a separate strip, not a column.
- Per-column vertical glow gradient (status-tinted top fading at 130px) +
  glow dots + uppercase tinted column titles; #0a0b0d base, #15171b cards.
- Topbar: project crumb + Coding/Reviews tabs + breathing "N working" pill +
  bell + blue "New worker" primary. "Board" subhead + subtitle.
- Card: status badge (dot + label) · mono id, 2-line title, mono branch line,
  hairline-topped PR footer ("no PR yet").

typecheck clean, 106 tests pass.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 3569e49ba7d6
Per the verbatim-clone directive (supersedes DESIGN.md/emdash). Remaps the
:root tokens to agent-orchestrator's exact values — #0a0b0d base, #15171b
card, #f4f5f7/#9ba1aa/#646a73 text, hairline white-alpha borders, #4d8dff
accent, orange/amber/green/red status — so every screen's base shifts at once.
Adds --color-working (orange) for the working status.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: d70096d7f30d
Rebuild the sidebar to match agent-orchestrator's ProjectSidebar: #08090b
rail, "Reverb / Code" brand with dimmed separator + collapse button,
uppercase PROJECTS label, project disclosure rows (rotating chevron +
hover-revealed New worker action + session count), nested session rows
with a 6px breathing working-dot and mono session id, and a single
Settings menu footer (Pull requests / Reviews / Search / Project
settings) plus a daemon-health dot.

Adds a shadcn dropdown-menu primitive (radix-ui unified package, matching
the existing select/label convention) for the footer menu.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: c4e1827b6142
Restyle the session header to match agent-orchestrator's SessionDetailHeader:
a "Kanban" back-to-board button + hairline divider, a stacked identity
(project / title over a mono branch line with a git-branch icon), and a
StatusBadge --pill (tinted bordered pill with a 6px dot that breathes while
the agent is working). Wire onOpenBoard from SessionView to navigate back to
the project board (or home).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: dcd3e4880af5
Extract the mc-board dashboard header (project crumb · Coding/Reviews tabs ·
"N working" breathing pill · bell · settings · New worker) and the 21px
subhead into a shared DashboardTopbar/DashboardSubhead, then apply it to the
review, PR, and settings screens so every dashboard surface shares one stable
agent-orchestrator top strip. SessionsBoard now consumes the shared chrome
instead of its inline copy; review/PR/settings drop their minimal h-11 headers
for the crumb+tabs+subhead treatment on the #0a0b0d base.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: 2801a9c5c0ba
Per explicit user decision (2026-06-10), the renderer clones the
agent-orchestrator web app verbatim, superseding the older "match emdash"
direction. Add a prominent banner at the top of DESIGN.md (reference files,
live palette, the cloned surfaces, shadcn-primitive guidance), mark the
Aesthetic Direction section as superseded, and retarget CLAUDE.md's QA rule so
future review flags divergence from agent-orchestrator instead of emdash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: fe028f97d5d5
Finish the agent-orchestrator-style renderer pass with shadcn sidebar chrome, titlebar navigation, resizable session inspector, orchestrator spawn affordances, and matching design tokens.

Co-authored-by: Cursor <cursoragent@cursor.com>
…lone

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	CLAUDE.md
#	DESIGN.md
#	backend/internal/httpd/apispec/openapi.yaml
#	backend/internal/service/project/service.go
#	backend/internal/service/project/types.go
#	backend/internal/service/session/service.go
#	frontend/e2e/workbench.spec.ts
#	frontend/forge.config.ts
#	frontend/index.html
#	frontend/package-lock.json
#	frontend/package.json
#	frontend/playwright.config.ts
#	frontend/pnpm-lock.yaml
#	frontend/src/main.ts
#	frontend/src/preload.ts
#	frontend/src/renderer/components/CenterPane.tsx
#	frontend/src/renderer/components/Sidebar.tsx
#	frontend/src/renderer/components/SpawnWorkerModal.tsx
#	frontend/src/renderer/components/TerminalPane.tsx
#	frontend/src/renderer/components/Topbar.tsx
#	frontend/src/renderer/components/ui/badge.tsx
#	frontend/src/renderer/components/ui/button.tsx
#	frontend/src/renderer/components/ui/input.tsx
#	frontend/src/renderer/components/ui/tabs.tsx
#	frontend/src/renderer/components/ui/tooltip.tsx
#	frontend/src/renderer/global.d.ts
#	frontend/src/renderer/hooks/useDaemonStatus.test.tsx
#	frontend/src/renderer/hooks/useDaemonStatus.ts
#	frontend/src/renderer/hooks/useEventsConnection.ts
#	frontend/src/renderer/hooks/useTerminalSession.test.tsx
#	frontend/src/renderer/hooks/useTerminalSession.ts
#	frontend/src/renderer/hooks/useWorkspaceQuery.test.tsx
#	frontend/src/renderer/hooks/useWorkspaceQuery.ts
#	frontend/src/renderer/lib/api-client.test.ts
#	frontend/src/renderer/lib/api-client.ts
#	frontend/src/renderer/lib/bridge.ts
#	frontend/src/renderer/lib/event-transport.test.ts
#	frontend/src/renderer/lib/event-transport.ts
#	frontend/src/renderer/lib/events-connection.ts
#	frontend/src/renderer/lib/mock-data.ts
#	frontend/src/renderer/lib/query-client.ts
#	frontend/src/renderer/lib/terminal-mux.test.ts
#	frontend/src/renderer/lib/terminal-mux.ts
#	frontend/src/renderer/lib/utils.ts
#	frontend/src/renderer/routeTree.gen.ts
#	frontend/src/renderer/stores/ui-store.ts
#	frontend/src/renderer/styles.css
#	frontend/src/renderer/test/setup.ts
#	frontend/src/renderer/types/workspace.test.ts
#	frontend/src/renderer/types/workspace.ts
#	frontend/src/shared/daemon-discovery.test.ts
#	frontend/src/shared/daemon-discovery.ts
#	frontend/src/shared/daemon-status.ts
#	frontend/tsconfig.json
#	frontend/vite.renderer.config.ts
Co-authored-by: Cursor <cursoragent@cursor.com>
…lone

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	frontend/src/renderer/components/SpawnWorkerModal.test.tsx
#	frontend/src/renderer/components/TerminalPane.tsx
#	frontend/src/renderer/hooks/useTerminalSession.ts
…play ring

Each WebSocket client that opens a pane now gets its own `zellij attach`
PTY (attachment.go) instead of sharing one PTY whose output was replayed
from a bounded byte ring. Zellij answers every fresh attach with its full
init handshake (alt screen, SGR mouse tracking, bracketed paste) and a
faithful repaint — the ring replay lost exactly that handshake, leaving
late subscribers without mouse reporting (dead wheel scroll). The cost is
one zellij client process per open pane per connection, which the zellij
server is built for (yyork ships the same model).

ring.go and session.go (fan-out, replay buffer) are deleted; manager.go
now tracks per-client attachments with liveness gating, and pty_unix.go
answers every resize frame with an explicit SIGWINCH.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-client attach

After each debounced resize settles, send one follow-up resize frame with
the same grid (RESIZE_REASSERT_MS). xterm only fires onResize on actual
grid changes, so a resize update the zellij client loses (raced mid-attach
or coalesced during a drag) would otherwise desync the session layout from
the pane until the next real change. The backend answers every resize
frame with an explicit SIGWINCH, so the re-assert is a no-op when already
in sync.

Comments in the terminal hook/components now describe the per-client
attach model (fresh server-side `zellij attach` per open, no replay ring).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…review dashboard

The shell now owns a single full-width ShellTopbar (status pill, history
arrows, notifications, kanban/inspector toggles) with the sidebar pinned
below it, replacing the per-view Topbar/DashboardTopbar pair; board pages
get a lightweight DashboardSubhead. The standalone review dashboard and
its /review(s) routes are removed — review state lives on the PR board.
Approved divergence from the AO reference (full-height sidebar) recorded
in DESIGN.md; macOS traffic lights re-centered on the 56px header row.

Also hardens the session view around rrp v4:
- inspector defaultSize re-derived per panel mount (orchestrator → worker
  navigation kept SessionView mounted while the panel remounted), and the
  imperative expand/collapse effect no longer races panel registration
- onResize writes gated on data-separator="active" so flex-grow
  transition frames can't bounce the store (dead-looking toggle button)
- findProjectOrchestrator skips terminated orchestrators so the topbar
  offers Spawn instead of attaching to a dead zellij session
- inspector resize handle gets a visible 1px divider at rest
- playwright specs for history arrows + inspector toggle; test-results/
  gitignored

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add an "Electron app (dev)" section: npm install + npm run dev under
frontend/, with the explicit heads-up that the app does not start the
daemon — it attaches over loopback to a daemon started via `ao start`
(plus npm run dev:web for renderer-only work in a browser).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fork-only ignore entries (.entire/.claude/.gstack) — must not be included
in upstream PRs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lone

Adopts upstream's permission-mode select in ProjectSettingsForm (aoagents#190),
the session_manager/config/gitworktree evolution (aoagents#187, aoagents#189, aoagents#191), and
the notification-stub removal (aoagents#190) — ported into ShellTopbar since the
per-view topbars it removed it from are retired on this branch. Files
deleted here that upstream still carries (DashboardTopbar, ReviewDashboard,
review routes, Topbar) stay deleted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@yyovil yyovil force-pushed the split/frontend-ui-clone branch from ff1a009 to d7e5ab0 Compare June 13, 2026 06:47

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@yyovil yyovil merged commit f7df36b into aoagents:main Jun 13, 2026
harshitsinghbhandari added a commit that referenced this pull request Jun 13, 2026
PR #222 was merged with its frontend CI red, shipping a cluster of
half-applied refactors. This finishes the cleanup:

- Sidebar remove-project: #222 squashed in a half-built version of the
  green feat/sidebar-remove-project work. ProjectItem called
  setRemoveError/setIsRemoving/onRemoveProject with none declared, the
  handler was never rendered (no kebab menu), SidebarProps lacked the
  prop, and the row was missing the hover-padding/opacity classes the
  test asserts — so Sidebar.tsx did not compile and its tests failed.
  Restore the wiring end to end: add onRemoveProject to SidebarProps,
  thread it to ProjectItem, add the state hooks, render the "Project
  actions" kebab + "Remove project" item, and re-add the row classes.
  _shell.tsx regains its removeProject handler (DELETE the project +
  drop it from the workspace cache) and passes it down.

- SessionsBoard: drop the dead boardTitle local (#222 leftover; the
  per-view title was retired in #195, the computed value never used).

- CI: re-enable `npm run typecheck` in frontend.yml. It was disabled for
  pre-existing forge.config.ts/update-electron-app type errors that are
  now gone; the gate would have caught the #222 "openSpawn is not
  defined" crash (Vite strips types without checking them) before merge.

Full renderer suite green (127 tests) and tsc --noEmit clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
harshitsinghbhandari added a commit that referenced this pull request Jun 13, 2026
#224 deleted the per-project "remove project" feature (and its tests)
instead of completing the wiring #222 left half-applied. Restore it:

- Sidebar: add onRemoveProject to SidebarProps, thread it to
  ProjectItem, re-add the removeError/isRemoving state and the confirm
  handler, render the "Project actions" kebab (MoreHorizontal) with a
  destructive "Remove project" item (Trash2), and re-add the row
  hover/focus/open padding + count-fade classes.
- _shell: re-add the removeProject handler (DELETE /api/v1/projects/{id}
  + drop the project from the workspace cache) and pass it to Sidebar.
- Sidebar.test: restore the confirm-before-remove and cancel-aborts
  coverage alongside the existing class assertions.

Rebuilt on top of #224. Full renderer suite green (127 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
harshitsinghbhandari added a commit that referenced this pull request Jun 13, 2026
* feat(sidebar): restore remove-project functionality

#224 deleted the per-project "remove project" feature (and its tests)
instead of completing the wiring #222 left half-applied. Restore it:

- Sidebar: add onRemoveProject to SidebarProps, thread it to
  ProjectItem, re-add the removeError/isRemoving state and the confirm
  handler, render the "Project actions" kebab (MoreHorizontal) with a
  destructive "Remove project" item (Trash2), and re-add the row
  hover/focus/open padding + count-fade classes.
- _shell: re-add the removeProject handler (DELETE /api/v1/projects/{id}
  + drop the project from the workspace cache) and pass it to Sidebar.
- Sidebar.test: restore the confirm-before-remove and cancel-aborts
  coverage alongside the existing class assertions.

Rebuilt on top of #224. Full renderer suite green (127 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: format with prettier [skip ci]

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
harshitsinghbhandari added a commit that referenced this pull request Jun 13, 2026
Restore re-derives the standing system prompt but only handed it to the
fresh-launch fallback, not the native GetRestoreCommand path, so a resumed
orchestrator/worker lost its role instructions. Pass SystemPrompt through to
the restore command too, matching adapters that re-append it on resume.

Also fix the recordingAgent test double to return ok=false when there is no
agent-session id, mirroring every real adapter, so the fallback-launch path is
actually exercised. These three TestRestore_* cases were red on main since #222.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
harshitsinghbhandari added a commit that referenced this pull request Jun 13, 2026
* fix(session): remove orchestrator kickoff auto-prompt on spawn

Spawning a session without an explicit prompt injected a "Get oriented..."
kickoff turn for orchestrators, which surfaced as an unsolicited message to
the orchestrator. Drop the auto-prompt so a promptless spawn delivers nothing
to the agent, leaving it idle at an empty input box.

Closes #226

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(session): re-apply derived system prompt on agent resume

Restore re-derives the standing system prompt but only handed it to the
fresh-launch fallback, not the native GetRestoreCommand path, so a resumed
orchestrator/worker lost its role instructions. Pass SystemPrompt through to
the restore command too, matching adapters that re-append it on resume.

Also fix the recordingAgent test double to return ok=false when there is no
agent-session id, mirroring every real adapter, so the fallback-launch path is
actually exercised. These three TestRestore_* cases were red on main since #222.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.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