chat: put the session list cwd in the url, not a panel channel

Which project group you are looking at is addressable state, so /chat?cwd=<dir> has to be a
link anyone can hand out — it survives a refresh and an agent run can point straight at its
own runs directory. Was usePanelChannel('chat:active-cwd'), which per the navigation audit is
for signals and refresh buses only. Row links and New Chat now carry the query string along.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 00:28:44 +00:00
co-authored by Claude Opus 5
parent 47d03de307
commit 6b46d9f1f9
3 changed files with 35 additions and 12 deletions
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useRef } from 'react';
import { useParams, useNavigate } from 'react-router';
import { useParams, useNavigate, useSearchParams } from 'react-router';
import type { LayoutNode, SelectedSession } from 'officerdev';
import { WorkspaceView } from 'officerdev';
import { useIsMobile } from 'hooks/useIsMobile';
@@ -38,7 +38,7 @@ type SessionListPageProps = {
export const SessionListPage = ({ isNew }: SessionListPageProps) => {
const { sessionId } = useParams<{ sessionId: string }>();
const [selected, setSelected] = usePanelChannel<SelectedSession>('chat:selected-session', null);
const [, setActiveCwd] = usePanelChannel<string | null>('chat:active-cwd', null);
const [, setSearchParams] = useSearchParams();
const client = useClient();
const selectedRef = useRef(selected);
selectedRef.current = selected;
@@ -78,7 +78,16 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
try {
const detail = await client.get<ClaudeSessionDetail>(`/chat/sessions/${sessionId}?limit=${CHAT_TAIL}`);
if (cancelled) return;
setActiveCwd(detail.cwd || null);
// replace: resolving a deep link is a canonicalisation, not a navigation the back button owes you.
setSearchParams(
(prev) => {
const next = new URLSearchParams(prev);
if (detail.cwd) next.set('cwd', detail.cwd);
else next.delete('cwd');
return next;
},
{ replace: true },
);
setSelected({
id: sessionId,
model: detail.model,