From 90a16d1d4451ae0a5dbac9976e72d0cd21b69bba Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Mon, 10 Aug 2026 02:15:40 +0300 Subject: [PATCH] fix(chat): refresh work status from git hints --- .../chat/work-status/DOCUMENTATION.md | 7 +++++- .../work-status/WorkStatusPrimaryGroup.tsx | 23 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/components/chat/work-status/DOCUMENTATION.md b/packages/ui/src/components/chat/work-status/DOCUMENTATION.md index cdbe8ca1..9a9cad2e 100644 --- a/packages/ui/src/components/chat/work-status/DOCUMENTATION.md +++ b/packages/ui/src/components/chat/work-status/DOCUMENTATION.md @@ -85,7 +85,7 @@ endpoint and no polling of its own. | Block | Source | Notes | |---|---|---| | Context + cost | `contextUsage.ts` over `useSessionMessages`, `Session.cost` | see below — the store getters cannot serve this | -| Branch, ahead/behind, attention | `useGitStore` directory state | warmed via `runBackgroundNetworkTask(ensureStatus)` | +| Branch, ahead/behind, attention | `useGitStore` directory state | warmed via `runBackgroundNetworkTask(ensureStatus)` and refreshed from Git mutation hints | | Changed files | `useGitStore` status `files` + `diffStats` | working tree, not session-authored edits | | PR + checks | `usePrVisualSummary` | **read-only** | | Subagents | child sessions from `useAllLiveSessions` (`parentID`) + `useAllSessionStatuses` | | @@ -326,6 +326,11 @@ background-network gate, so it cannot compete with chat bootstrap traffic for sockets. A panel that reports a subsystem's state cannot depend on an unrelated component having been mounted or opened. +The repository section follows the same ownership rule. It subscribes directly +to `sessionEvents` Git refresh hints and refreshes its directory's shared Git +cache, rather than relying on the composer's former changed-files row or on the +Git context surface being opened first. + ## Persisted panel state Expanded sections (`workStatusExpandedSections`, keyed by a stable section id) diff --git a/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx b/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx index 559ba05a..e62ae1c0 100644 --- a/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx +++ b/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx @@ -10,6 +10,8 @@ import { useUIStore } from '@/stores/useUIStore'; import { useProjectsStore } from '@/stores/useProjectsStore'; import { normalizeProjectPath } from '@/lib/projectResolution'; import { resolveUsageTone } from '@/lib/quota'; +import { sessionEvents } from '@/lib/sessionEvents'; +import { normalizePath } from '@/lib/pathNormalization'; import { computeContextUsage } from './contextUsage'; import { WorkStatusCallout, @@ -49,6 +51,8 @@ export const WorkStatusPrimaryGroup: React.FC = ({ sessionId, directory, const session = useSession(sessionId ?? '', directory ?? undefined); const { git } = useRuntimeAPIs(); const ensureStatus = useGitStore((state) => state.ensureStatus); + const fetchStatus = useGitStore((state) => state.fetchStatus); + const clearDiffCache = useGitStore((state) => state.clearDiffCache); const gitStatus = useGitStore( React.useCallback( @@ -60,9 +64,24 @@ export const WorkStatusPrimaryGroup: React.FC = ({ sessionId, directory, // Warm the shared git cache through the background-network gate so the panel // never competes with the chat's own bootstrap traffic for sockets. React.useEffect(() => { - if (!directory || !git) return; + if (!showRepository || !directory || !git) return; void runBackgroundNetworkTask(() => ensureStatus(directory, git)); - }, [directory, git, ensureStatus]); + }, [directory, git, ensureStatus, showRepository]); + + // Own the live invalidation for the repository readout. The desktop + // composer's changed-files row no longer renders, so this panel must not + // depend on ChatInput (or an opened Git surface) to refresh the shared cache + // on its behalf. + React.useEffect(() => { + if (!showRepository || !directory || !git) return; + return sessionEvents.onGitRefreshHint((hint) => { + if (normalizePath(hint.directory) !== normalizePath(directory)) return; + if (hint.paths?.length) { + clearDiffCache(directory, hint.paths); + } + void fetchStatus(directory, git, { silent: true }); + }); + }, [clearDiffCache, directory, fetchStatus, git, showRepository]); const branch = gitStatus?.current?.trim() || null;