feat(projects): project settings editor + config-driven composer prefill (Phase 2)#3221
feat(projects): project settings editor + config-driven composer prefill (Phase 2)#3221serena-ruan wants to merge 3 commits into
Conversation
…ill (Phase 2)
Add a "Project settings" dialog to set a project's stored session defaults
(host, working directory, agent, opt-in random worktree) and wire the new-chat
composer to prefill from that stored config, retiring the newest-session
inference so stored config is the single source of truth.
- ProjectSettingsDialog: edit + persist config {host_id, workspace, agent_id,
use_worktree}; worktrees opt-in (default OFF, store true when on). Reuses the
composer's host/agent pickers and filesystem browser.
- projectPrefill: collapse to config-only seeding; unset fields fall through to
the composer's generic defaults. Honor a stored sandbox default via
selectSandbox (gated on managed sandboxes). Remove useNewestProjectSession.
- Extract the nested-dropdown dismiss guard into a dependency-free module shared
by the settings and scheduled-task dialogs.
Co-authored-by: Isaac
|
/review |
Benchmark results (SQLite, PR #3221)Commit: Benchmark comparisonRegression threshold: 100% on avg P50 or avg P95.
PASS — no regressions detected. |
|
…nference e2e - Add useProjectConfig/useUpdateProjectConfig to all 10 Sidebar test mocks (Sidebar now mounts ProjectSettingsDialog, which calls them). - Rewrite the settings-dialog e2e to create the project via POST /v1/projects instead of the flaky row-kebab move-to-project flow. - Fix the composer-prefill e2e to stub GET /v1/sessions/projects (bare array), the real endpoint useProjects hits. - Remove test_start_session_project_prefill — it exercised the newest-session inference path this PR retired; config-driven prefill replaces its coverage. Co-authored-by: Isaac
…resh prefill after save
Blocking issues from the PR review:
1. Data loss: saving the settings dialog after a failed config GET sent `{}`,
which the server reads as "clear stored defaults". Now `useProjectConfig`'s
isError is surfaced; a first-class project whose config failed to load blocks
Save (with a notice), the seed effect skips a blank draft, and onSubmit bails.
2. Stale prefill after save: useUpdateProjectConfig only invalidated, so the
composer's one-shot prefill could latch onto a stale cached config (30s
staleTime) and drop just-saved defaults. It now setQueryData's the fresh
config and upserts the projects list (so a promoted label-only folder
resolves to its new id immediately).
Tests: dialog load-error blocks Save; hook seeds config + upserts list on
success; useProjectConfig disabled on null id and surfaces isError.
Co-authored-by: Isaac
Related issue
Part of #863 (Projects epic — Phase 2, project defaults). Not closing the epic.
Summary
Wires up project-level session defaults end to end:
ProjectSettingsDialog, from the project-folder kebab) edits and persists a project'sconfig— host, working directory, default agent, and an opt-in "Random worktree" toggle. Reuses the composer's host/agent pickers and filesystem browser. Worktrees are opt-in: the toggle defaults OFF and only an explicit ON storesuse_worktree: true.?project=visit seeds host / working directory / agent from the project's storedconfig, silently falling back to the composer's generic defaults for any unset field. A stored sandbox default is honored (selects the sandbox, gated on managed sandboxes being enabled). An opt-in worktree generates a freshworktree-<hex>branch once the workspace is in place.projectPrefill.tscollapsed to config-only;useNewestProjectSessionremoved) so stored config is the single source of truth — a project with no config prefills nothing project-specific.dialogDismissGuard.tsshared by the settings and scheduled-task dialogs.Test Plan
projectPrefill.test.ts(config seeding, agent seeding, sandbox sentinel, load-order gates),ProjectSettingsDialog.test.tsx(seed/save round-trips, worktree opt-in, workspace disclosure),dialogDismissGuard.test.ts, updatedNewChatDialog.projectPrefill.test.tsx.tscclean, all suites green.tests/stores/test_project_store.py— config persist / clear / unchanged.tests/e2e_ui):test_project_settings_dialog.py(settings PATCH round-trip + clear),test_project_config_prefill.py(composer prefills host/workspace/agent from config; sandbox-default prefill — the regression the review flagged). All 4 pass against a real server.pre-commit run— passes.Demo
Screen.Recording.2026-07-24.at.5.39.39.PM.mov
Type of change
Test coverage
Coverage notes
Manually verified in the running app: settings dialog persistence, composer prefill (host/workspace/agent/worktree), and the sandbox-default case. The working-directory / worktree prefill path can't be e2e-tested (the e2e_ui runner registers no real host workspace), so it's covered by component tests; everything else has automated unit + e2e coverage.
Changelog
Projects now carry default session settings (host, working directory, agent, optional git worktree) that pre-fill the new-session composer.
This pull request and its description were written by Isaac.