feat(web): unify Specs and Planner into /workspace #562
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!562
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "boss/557"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Replaces
/specsand/plannerwith a single/workspaceroute — sessions list + specs list share one sidebar, the centre column flips between spec editor and chat without a route transition, autosave + status pill replace the explicit Save button, and the breakdown preview moves into a<Drawer>opened by the spec-mode "Create issues" CTA.Closes #557
Test plan
bun x turbo run typecheck test— greenbun x @biomejs/biome@^2 check .— green/workspace(desktop): sidebar + empty state, click Start session and Open spec from CTAs?session=<id>and?spec=<name>deep-link correctly; switching one clears the other@specs/<name>.md< lgviewport: "Browse" button opens sidebar drawer with both lists/specs,/specs/<name>,/specs?name=foo,/planner,/planner?spec=fooall redirect to/workspacewith params preserved/planner/boardstill routes correctlybehavior
workspace.index.tsxlines 2301–2305 —openSession(null)navigates tosession: undefined, which evaluates tomode = "empty"and hides theComposer. Both the + New button in the sessions sidebar (onNewSession: () => openSession(null)) and the Start session CTA in the empty state do this. After clicking either, the user is in empty mode with no composer and no way to type — new foreman chat sessions cannot be started. Fix: use a sentinel value (e.g.?session=new) for new-session mode and strip it on first send, or render theComposer/empty-transcript below the empty-state cards when no spec is selected (matching the old planner whereactiveSessionId === nullstill showed the composer).behavior (minor)
spec-editor.tsxflushSave— if a save is in-flight when the debounce timer fires, the queued content is silently dropped and no retry is scheduled; becausecontenthas not changed, theuseEffectdoes not re-trigger afterinFlightRefclears. The blur handler mitigates this for normal focus loss, but not for tab close. Low-severity for a local API, but a retry pass afterinFlightRef.currentbecomesfalsewould close the gap.dead code (nit)
workspace.index.tsxline 2904 —void sessionRepoaccepts the prop but never renders it. Either wire up the repo chip in the toolbar or removesessionRepofromWorkspaceToolbarPropsand the call site.All three addressed in
0b962f2.openSession(null)): added a?session=newsentinel so "+ New", "Start session", and "Discuss with foreman" all land inmode === "session"with theComposerrendered. TheactiveSessionquery is disabled while the sentinel is in the URL, andsendMutationstrips it before posting; the success handler thenreplaces the URL with the real session id.draftRef. AfterflushSavesettles it checks whether new edits arrived during the in-flight save and, if so, triggers a follow-up flush. Guarded bydraftRef.current !== textso a persistent server failure can't loop.sessionRepo): removed the prop fromWorkspaceToolbarPropsand the call site. The repo is already shown in the banner above the transcript when a persisted session is loaded — no value adding a second chip in the toolbar.All three round-1 findings addressed:
NEW_SESSION_ID = "new"sentinel;openSession(null)replaced at every call site; query disabled for sentinel; sentinel stripped before send;onSuccesspromotes URL to real session id withreplace: true.flushSaveretry loop closed:draftRefmirrors latest content, post-save tail chases forward edits without re-attempting the same text on persistent failures.sessionRepodead prop removed from interface, destructuring, and call site.