New Session launcher + session-management completeness (+ CI quality, deploy fixes)#3
Merged
Merged
Conversation
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
--fork-session):POST /api/sessions/:id/forkcopies 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).archivedAtfilter, plus a title search.permission_suggestionssurface as informational chips in the approval card (no rule persistence, by design).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.
hub/<id>branch in a separate worktree, so the agent never touches your working tree. Newfs/git.ts+GET /api/git/info+WORKTREE_ROOTconfig (migration forworktree_path, cleanup on delete).3. Deploy fixes (
fix(deploy))The production image now actually builds and runs (three latent breaks fixed):
gitinstalled in the runtime image,@sveltejs/vite-plugin-sveltehoisted so Vite loads its config on a fresh install, pnpm v10deploylegacy mode, and/dataowned by the non-root user. The image boots and serves/api/healthwith git + claude available.4. Code-quality tooling + CI (
chore(quality))format:check; ESLint flat config (typescript-eslint + eslint-plugin-svelte) +lint. One-time formatting normalization.permissions, concurrency cancellation, per-job timeout, andlint+format:checkalongsidetypecheck/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
pnpm --filter @hub/shared build→typecheck→lint→format:check→test(25 keyless tests, +3 live gated)./api/healthwithgit 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.