mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
* feat(workspace-cleanup): mark merged and unchanged workspaces from git evidence Squash-merged branches whose remote was deleted were flagged as unpushed and needed a forced delete. The scan now reads what HEAD holds beyond the workspace's base (ancestor, Git's squash proof, or a cached merged PR) and reports merged/unchanged reasons; landed commits no longer count as at risk. A gone upstream no longer hides unpushed commits. Renames idle-clean to inactive and drops the dead tier, selectedByDefault and volatile-local-context. * fix(workspace-cleanup): read HEAD once, skip a reused branch as its own base Merge evidence now compares the cached PR and the base against the HEAD it reads, not the listing's possibly stale one; a workspace opened on an existing branch no longer counts that branch as its base; the proof wrapper settles the WSL route before building its caches; a visit keeps merged/unchanged reasons; landed rows stop sorting as unpushed. * fix(workspace-cleanup): qualify base refs and trust the branch proof only for HEAD Base refs resolve through the worktree base-ref qualifier so a tag cannot shadow them and only the branch's own family is skipped, including the repo default; SHA-256 pinned commits are not bases; the squash proof runs only while the branch ref is the HEAD just read; expanded details stop counting landed commits as unpushed. * test(workspace-cleanup): build the repo fixture without a cast * fix(workspace-cleanup): never take a tag as a workspace's base
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { ORCA_SIDEBAR_INPUTS_IS_MAIN } from './sidebar-inputs-switch'
|
|
import {
|
|
getWorkspaceCleanupInactivityReasons,
|
|
type WorkspaceCleanupCandidate
|
|
} from './workspace-cleanup/workspace-cleanup'
|
|
|
|
/** With the switch on, visits count because terminal start/exit no longer advance Recent; plain-shell work must not appear idle. */
|
|
export function getWorkspaceLastActiveAt(
|
|
lastActivityAt: number,
|
|
lastVisitedAt: number | undefined
|
|
): number {
|
|
if (!ORCA_SIDEBAR_INPUTS_IS_MAIN) {
|
|
return lastActivityAt
|
|
}
|
|
const finite = (value: number | undefined): number =>
|
|
value !== undefined && Number.isFinite(value) ? value : 0
|
|
return Math.max(finite(lastActivityAt), finite(lastVisitedAt))
|
|
}
|
|
|
|
/** A cleanup candidate seen with the client's visit; a newer visit can only drop idle reasons. */
|
|
export function withCleanupVisitEvidence(
|
|
candidate: WorkspaceCleanupCandidate,
|
|
lastVisitedAt: number | undefined,
|
|
now: number
|
|
): WorkspaceCleanupCandidate {
|
|
const lastActiveAt = getWorkspaceLastActiveAt(candidate.lastActivityAt, lastVisitedAt)
|
|
if (lastActiveAt <= candidate.lastActivityAt) {
|
|
return candidate
|
|
}
|
|
const idleReasons = getWorkspaceCleanupInactivityReasons(
|
|
{ isArchived: candidate.reasons.includes('archived'), lastActivityAt: lastActiveAt },
|
|
now
|
|
)
|
|
// Merged/unchanged come from Git, not age, so a visit keeps them.
|
|
const reasons = candidate.reasons.filter(
|
|
(reason) => (reason !== 'archived' && reason !== 'inactive') || idleReasons.includes(reason)
|
|
)
|
|
return { ...candidate, lastActivityAt: lastActiveAt, reasons }
|
|
}
|