mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 08:03:22 +00:00
Fix pinned host and inbox placement
This commit is contained in:
@@ -403,6 +403,47 @@ describe('addHostSectionRows', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('keeps a pinned row with its explicit worktree host', () => {
|
||||
const local = repo('local')
|
||||
const pinned = pinnedItem('ssh-pinned', local, PINNED_GROUP_KEY)
|
||||
pinned.worktree.hostId = 'ssh:ssh-1'
|
||||
const rows = [
|
||||
pinnedHeader(new Map([['ssh:ssh-1', 1]]), new Map([['ssh:ssh-1', ['ssh-pinned']]])),
|
||||
pinned,
|
||||
repoHeader(local),
|
||||
item('local-wt', local)
|
||||
]
|
||||
|
||||
const sectioned = addHostSectionRows({
|
||||
rows,
|
||||
hostOptions: [
|
||||
{
|
||||
id: 'local',
|
||||
kind: 'local',
|
||||
label: 'Local Mac',
|
||||
detail: 'This computer',
|
||||
health: 'local'
|
||||
},
|
||||
{ id: 'ssh:ssh-1', kind: 'ssh', label: 'Builder', detail: 'SSH', health: 'available' }
|
||||
],
|
||||
workspaceHostScope: 'all',
|
||||
defaultHostId: 'local'
|
||||
})
|
||||
|
||||
expect(sectioned.map(rowKey)).toEqual([
|
||||
'host:local',
|
||||
'repo:local',
|
||||
'local-wt',
|
||||
'host:ssh:ssh-1',
|
||||
PINNED_GROUP_KEY,
|
||||
'ssh-pinned'
|
||||
])
|
||||
expect(sectioned.filter((row) => row.type === 'host-header')).toMatchObject([
|
||||
{ hostId: 'local', count: 1 },
|
||||
{ hostId: 'ssh:ssh-1', count: 1 }
|
||||
])
|
||||
})
|
||||
|
||||
it('does not double-count a collapsed pinned header and its natural duplicate row', () => {
|
||||
const local = repo('local')
|
||||
const ssh = repo('ssh', 'ssh-1')
|
||||
|
||||
@@ -69,7 +69,9 @@ function getFolderWorkspaceHostId(
|
||||
function getRowHostId(row: Row, defaultHostId: ExecutionHostId): ExecutionHostId | null {
|
||||
switch (row.type) {
|
||||
case 'item':
|
||||
return getRepoHostId(row.repo, defaultHostId)
|
||||
// Why: runtime and SSH snapshots can carry a more precise owner than the
|
||||
// repo fallback; header localization already uses this worktree identity.
|
||||
return row.worktree.hostId ?? getRepoHostId(row.repo, defaultHostId)
|
||||
case 'pending-creation':
|
||||
case 'imported-worktrees-card':
|
||||
case 'new-external-worktrees-inbox':
|
||||
|
||||
@@ -1569,6 +1569,51 @@ describe('buildRows with pinned worktrees', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('keeps the inbox group when the repo only has a pinned worktree', () => {
|
||||
const pinnedWorktree = { ...worktree, id: 'wt-pinned', isPinned: true }
|
||||
const rows = buildRows(
|
||||
'repo',
|
||||
[pinnedWorktree],
|
||||
repoMap,
|
||||
null,
|
||||
new Set(),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{},
|
||||
new Map([[pinnedWorktree.id, pinnedWorktree]]),
|
||||
false,
|
||||
undefined,
|
||||
[],
|
||||
new Set(),
|
||||
new Map(),
|
||||
new Map([[repo.id, { repo, inboxWorktrees: [makeDetectedWorktree()] }]])
|
||||
)
|
||||
|
||||
expect(rows).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
type: 'item',
|
||||
sectionKey: PINNED_GROUP_KEY,
|
||||
worktree: expect.objectContaining({ id: pinnedWorktree.id })
|
||||
}),
|
||||
expect.objectContaining({ type: 'header', key: `repo:${repo.id}` }),
|
||||
expect.objectContaining({
|
||||
type: 'new-external-worktrees-inbox',
|
||||
key: `new-external-worktrees-inbox:${repo.id}`
|
||||
})
|
||||
])
|
||||
)
|
||||
expect(
|
||||
rows.some(
|
||||
(row) =>
|
||||
row.type === 'item' &&
|
||||
row.sectionKey === `repo:${repo.id}` &&
|
||||
row.worktree.id === pinnedWorktree.id
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('does not emit new external worktrees inbox rows outside repo grouping', () => {
|
||||
const rows = buildRows(
|
||||
'workspace-status',
|
||||
|
||||
@@ -1043,11 +1043,6 @@ export function buildRows(
|
||||
settings,
|
||||
projectGrouping
|
||||
})
|
||||
// Repos whose only visible worktrees are pinned are surfaced via the pinned
|
||||
// section, so the repo-grouped inbox loop below must not re-create a group for them.
|
||||
const visiblePinnedRepoIds = new Set(
|
||||
worktrees.filter((worktree) => worktree.isPinned).map((worktree) => worktree.repoId)
|
||||
)
|
||||
emitPinnedGroup(
|
||||
worktrees,
|
||||
repoMap,
|
||||
@@ -1151,7 +1146,9 @@ export function buildRows(
|
||||
for (const [repoId, candidate] of newExternalWorktreesInboxByRepo) {
|
||||
const grouping = getProjectGroupingForRepo(repoId, repoMap, projectIndex)
|
||||
const key = grouping.key
|
||||
if (!grouped.has(key) && !visiblePinnedRepoIds.has(repoId)) {
|
||||
if (!grouped.has(key)) {
|
||||
// Why: the default policy removes pinned worktrees from natural groups,
|
||||
// but actionable inbox rows still need a project section to render in.
|
||||
grouped.set(key, {
|
||||
label: grouping.label,
|
||||
items: [],
|
||||
|
||||
Reference in New Issue
Block a user