fix(chat): refresh work status from git hints

This commit is contained in:
Bohdan Triapitsyn
2026-08-10 15:10:36 +03:00
parent dfa7b45dd0
commit 90a16d1d44
2 changed files with 27 additions and 3 deletions
@@ -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)
@@ -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<Props> = ({ 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<Props> = ({ 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;