mirror of
https://github.com/stablyai/orca.git
synced 2026-10-08 16:02:37 +00:00
fix(status-bar): preserve workspace-space review and agent freshness
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useNow } from '@/hooks/use-now'
|
||||
import { getAgentStatusEpochNow } from '@/lib/agent-status-epoch-clock'
|
||||
import {
|
||||
getWorkspaceDecisionDetails,
|
||||
type WorkspaceDecisionDetails
|
||||
@@ -40,7 +40,6 @@ export function useWorkspaceSpaceDecisionProjection(bindings: WorkspaceSpaceMana
|
||||
} = bindings
|
||||
|
||||
const sourceRows = useMemo(() => analysis?.worktrees ?? [], [analysis?.worktrees])
|
||||
const now = useNow(30_000)
|
||||
const worktreeIdCounts = useMemo(() => {
|
||||
const counts = new Map<string, number>()
|
||||
for (const row of sourceRows) {
|
||||
@@ -49,9 +48,9 @@ export function useWorkspaceSpaceDecisionProjection(bindings: WorkspaceSpaceMana
|
||||
return counts
|
||||
}, [sourceRows])
|
||||
const decisionDetailsByWorktreeId = useMemo(() => {
|
||||
// Why: active-agent freshness is time-based. The epoch bumps when fresh
|
||||
// hook entries cross the stale boundary so delete readiness recomputes.
|
||||
void agentStatusEpoch
|
||||
// Why: the epoch bumps when fresh hook entries cross the stale boundary so
|
||||
// delete readiness recomputes with the same wall-clock sample as the store.
|
||||
const agentStatusNow = getAgentStatusEpochNow(agentStatusEpoch)
|
||||
const details = new Map<string, WorkspaceDecisionDetails>()
|
||||
for (const worktree of sourceRows) {
|
||||
details.set(
|
||||
@@ -78,7 +77,7 @@ export function useWorkspaceSpaceDecisionProjection(bindings: WorkspaceSpaceMana
|
||||
settings,
|
||||
activeWorktreeId,
|
||||
activeWorkspaceExecutionHostId,
|
||||
now
|
||||
now: agentStatusNow
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -106,8 +105,7 @@ export function useWorkspaceSpaceDecisionProjection(bindings: WorkspaceSpaceMana
|
||||
settings,
|
||||
sourceRows,
|
||||
tabsByWorktree,
|
||||
worktreeMap,
|
||||
now
|
||||
worktreeMap
|
||||
])
|
||||
const getDeleteStateForWorktree = useCallback(
|
||||
(worktree: WorkspaceSpaceWorktree) =>
|
||||
|
||||
@@ -3,9 +3,11 @@ import type {
|
||||
MigrationUnsupportedPtyEntry
|
||||
} from '../../../../shared/agent-status-types'
|
||||
import type { ExecutionHostId } from '../../../../shared/execution-host'
|
||||
import type { HostedReviewProvider } from '../../../../shared/hosted-review'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { TerminalTab } from '../../../../shared/terminal-tab-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import { isGitHubPRSuppressed } from '../../../../shared/worktree/github-pr-suppression'
|
||||
import type { WorkspaceSpaceWorktree } from '../../../../shared/workspace-space-types'
|
||||
import { branchDisplayName } from '../sidebar/WorktreeCardHelpers'
|
||||
import { findRepoForHost } from '../../store/slices/repo-host-identity'
|
||||
@@ -50,7 +52,15 @@ export type WorkspaceDecisionInputs = {
|
||||
remoteStatusesByWorktree: Record<string, { hasUpstream: boolean; ahead: number; behind: number }>
|
||||
hostedReviewCache: Record<
|
||||
string,
|
||||
{ data?: { number: number; state: string; status: string; title: string } | null }
|
||||
{
|
||||
data?: {
|
||||
number: number
|
||||
state: string
|
||||
status: string
|
||||
title: string
|
||||
provider?: HostedReviewProvider
|
||||
} | null
|
||||
}
|
||||
>
|
||||
issueCache: Record<string, { data?: { number: number; title: string; state: string } | null }>
|
||||
linearIssueCache: Record<
|
||||
@@ -129,7 +139,13 @@ export function getWorkspaceDecisionDetails(
|
||||
ownerExecutionHostId,
|
||||
repo !== null && repo !== undefined
|
||||
)
|
||||
const hostedReview = inputs.hostedReviewCache[reviewCacheKey]?.data
|
||||
const cachedHostedReview = inputs.hostedReviewCache[reviewCacheKey]?.data
|
||||
const hostedReview =
|
||||
cachedHostedReview?.provider === 'github' &&
|
||||
workspaceRecord &&
|
||||
isGitHubPRSuppressed(workspaceRecord, cachedHostedReview.number)
|
||||
? null
|
||||
: cachedHostedReview
|
||||
const linkedPR = workspaceRecord?.linkedPR ?? null
|
||||
const reviewLabel =
|
||||
hostedReview !== undefined && hostedReview !== null
|
||||
|
||||
@@ -428,6 +428,30 @@ describe('workspace space presentation helpers', () => {
|
||||
expect(details.issueLabel).toBe('#123 open: Local owner issue')
|
||||
})
|
||||
|
||||
it('hides a GitHub review explicitly suppressed after unlinking', () => {
|
||||
const details = getWorkspaceDecisionDetails(
|
||||
row({ branch: 'refs/heads/feature/local' }),
|
||||
decisionInputs({
|
||||
hostedReviewCache: {
|
||||
'local::repo::feature/local': {
|
||||
data: {
|
||||
number: 12,
|
||||
state: 'open',
|
||||
status: 'success',
|
||||
title: 'Suppressed review',
|
||||
provider: 'github'
|
||||
}
|
||||
}
|
||||
},
|
||||
worktreeMap: new Map([
|
||||
['wt', worktreeRecord({ branch: 'refs/heads/feature/local', suppressedGitHubPR: 12 })]
|
||||
])
|
||||
})
|
||||
)
|
||||
|
||||
expect(details.reviewLabel).toBeNull()
|
||||
})
|
||||
|
||||
it('counts migration-unsupported agent entries by worktree id', () => {
|
||||
const count = countWorkspaceSpaceActiveAgents({
|
||||
worktreeId: 'wt',
|
||||
|
||||
Reference in New Issue
Block a user