Skip to content

New Session launcher + session-management completeness (+ CI quality, deploy fixes)#3

Merged
Neverdecel merged 5 commits into
mainfrom
claude/new-session-launcher
Jul 9, 2026
Merged

New Session launcher + session-management completeness (+ CI quality, deploy fixes)#3
Neverdecel merged 5 commits into
mainfrom
claude/new-session-launcher

Conversation

@Neverdecel

Copy link
Copy Markdown
Owner

Summary

The next slice of work on top of the merged handoff2 (PR #2). Three feature areas plus tooling/infra, as clean per-area commits. Rebased onto main; the leaner CI (see below) passes.

What's in here

1. Session-management completeness (feat(sessions))

Rounds out the session lifecycle so a hub session is a fully manageable "terminal window" (README §6 req #4). One additive DB migration.

  • Session fork (--fork-session): POST /api/sessions/:id/fork copies the parent's config + event log and, on the fork's first turn, resumes the parent transcript under a new engine session id, leaving the parent untouched. Verified keyless (echo) and live (Claude mints a new id and recalls the parent transcript).
  • Archived-sessions view: sidebar "Show archived" toggle, archive/unarchive, archivedAt filter, plus a title search.
  • Approval affordances: the CLI's permission_suggestions surface as informational chips in the approval card (no rule persistence, by design).
  • Replay pagination: bounded initial WS replay (recent N + replay_meta), older history pages backward over REST; forward catch-up unchanged.

2. New Session launcher (feat(web))

Replaces the utilitarian modal with a home launcher screen (shown in the main pane when no session is active), taking OpenHands' launcher as a base and going further with local filesystem/git access.

  • Recent projects (from session history), project picker with browse + live validate + git badge.
  • Git branch + isolated worktree: an "Isolate in a new worktree" toggle creates a fresh hub/<id> branch in a separate worktree, so the agent never touches your working tree. New fs/git.ts + GET /api/git/info + WORKTREE_ROOT config (migration for worktree_path, cleanup on delete).
  • Optional initial task that launches the agent immediately.
  • Engine / permission-mode / model / settings tucked into a collapsible Advanced; the engine picker hides when only one engine is available.

3. Deploy fixes (fix(deploy))

The production image now actually builds and runs (three latent breaks fixed): git installed in the runtime image, @sveltejs/vite-plugin-svelte hoisted so Vite loads its config on a fresh install, pnpm v10 deploy legacy mode, and /data owned by the non-root user. The image boots and serves /api/health with git + claude available.

4. Code-quality tooling + CI (chore(quality))

  • Prettier (house style) + format:check; ESLint flat config (typescript-eslint + eslint-plugin-svelte) + lint. One-time formatting normalization.
  • CI: least-privilege permissions, concurrency cancellation, per-job timeout, and lint + format:check alongside typecheck/test. Kept fast for development: CI builds only @hub/shared (the dist downstream steps need); production artifact builds stay in the deploy image, and there is no Docker image build in CI.

Verification

  • Lean CI sequence green locally: pnpm --filter @hub/shared buildtypechecklintformat:checktest (25 keyless tests, +3 live gated).
  • Live: fork against real Claude 2.1.205 (new engine session id + transcript carried over).
  • Production Docker image builds, boots, and serves /api/health with git 2.39.5 + claude 2.1.205.

Notes

Handoff docs updated (handoff3.md, CLAUDE.md, README.md). Not in scope: persisting allow-rules from suggestion chips, Copilot/Codex adapters, scheduling.

Wit, Floris De (178) added 5 commits July 9, 2026 17:43
…vals, pagination)

Rounds out the session lifecycle so a hub session is a fully manageable
"terminal window" (README §6 req #4: list/resume/fork/archive/search) plus two
UX/scale items. No new engine, no scheduling. One additive DB migration (id:4).

Session fork (--fork-session):
- POST /api/sessions/:id/fork copies the parent's config + event log and, on the
  fork's first turn, resumes the parent transcript under a NEW engine session id
  via --fork-session, leaving the parent untouched. A one-shot fork_pending flag
  (migration 4) is consumed on the first engine_meta. SessionManager.fork,
  EventsRepo.copyEvents, createForked, StartOptions.forkSession, SessionDto.parentId.
  Web: fork button in the sidebar. Verified keyless (echo) + live (Claude mints a
  new id and recalls the parent transcript).

Archived-sessions view (backend already existed):
- Sidebar "Show archived" toggle (lazy api.sessions(true)), archive/unarchive
  row action, render-time archivedAt filter, plus a title search filter.

Approval affordances:
- Surface the CLI's permission_suggestions as informational chips in the approval
  card (defensive rendering; no rule persistence). Threaded adapter -> event ->
  timeline -> ApprovalCard.

Replay pagination:
- Bounded initial WS replay (most recent N + replay_meta{hasMoreBefore}); older
  history pages backward over REST (/events?beforeId&limit). Forward catch-up on
  reconnect is unchanged, preserving the atomic replay-then-live invariant. Web:
  "Load earlier" with scroll anchoring.

Tests: +fork and +pagination e2e (echo, keyless); +live fork test (gated).
…ree + initial task

Replaces the utilitarian New Session modal with a home launcher screen (shown in
the main pane when no session is active), taking OpenHands' launcher as a base and
pushing further with our local filesystem/git access.

Launcher (web/src/components/Launcher.svelte, replaces NewSessionDialog):
- Recent projects (derived from prior sessions' cwds, worktree sessions excluded),
  project directory picker with browse + live validate + git badge.
- Git: shows the repo's current branch; an "Isolate in a new worktree" toggle that,
  when on, reveals a searchable base-branch input (datalist).
- Optional initial-task box that launches the agent immediately (Enter launches,
  Shift+Enter newline).
- Engine / permission-mode / model / settings collapsed into Advanced; the engine
  picker is hidden when only one engine is available.
- App renders it in the empty pane; the sidebar "+ New session" clears the active
  session to reveal it (modal retired).

Git backend (new):
- server/src/fs/git.ts: gitInfo (branches/current/default), addWorktree (new hub/…
  branch, never checks out over the user's tree), removeWorktree (+ prunes the
  hub/ branch). GET /api/git/info?cwd=. WORKTREE_ROOT config (default
  $DATA_DIR/worktrees).

Session create/delete (server):
- CreateSessionRequest gains branch/worktree/initialPrompt; SessionDto.worktreePath
  (migration 5). On create with worktree, the session runs in a hub-managed worktree
  as its cwd (trusted); with initialPrompt the first turn auto-runs. Delete cleans up
  the worktree.

Tests: +git.test.ts (gitInfo/addWorktree/removeWorktree) and +e2e worktree/initial-
prompt test (25 keyless passing). README documents WORKTREE_ROOT.
Three latent breaks surfaced building deploy/Dockerfile under the current
toolchain, plus the new git dependency:

- git is now installed in the runtime image (isolated-worktree sessions shell
  out to it; the Claude CLI also uses it).
- .npmrc hoists @sveltejs/vite-plugin-svelte so Vite can load its TS config from
  the temp dir on a fresh (Docker/CI) install, not just a warm local one.
- pnpm v10 `deploy` needs legacy mode (force-legacy-deploy=true); our shared
  package isn't injected.
- /data is created and chowned to the non-root runtime user so SQLite + worktrees
  are writable (a named volume mounted there inherits the ownership).

The image now boots and serves /api/health with git + claude available.
.env.example documents WORKTREE_ROOT.
- Prettier (house style: width 100, single quotes, trailing commas) + a
  format:check; ESLint flat config (typescript-eslint + eslint-plugin-svelte)
  with a focused ruleset + a lint script. Fixed the few real issues it found
  (keyed {#each}, useless assignment, unused prop).
- CI: least-privilege permissions, concurrency cancellation, per-job timeout,
  and lint + format:check alongside typecheck/test. To keep dev CI fast, CI
  builds only @hub/shared (the dist downstream steps consume); production
  artifact builds (server dist, web Vite bundle) stay in the deploy image, and
  there is no Docker image build in CI.
- One-time Prettier normalization across the codebase (mechanical).
@Neverdecel Neverdecel merged commit cac336d into main Jul 9, 2026
1 check passed
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