mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-17 13:13:35 +08:00
fix: prefer native worktree identity for session badges
CLI transcripts persist native worktree-state entries for resume, so the desktop git-info endpoint should treat that state as authoritative for worktree identity. Desktop launch metadata can be stale after placeholder cleanup or reopen, and should only fill gaps. The displayed business branch still prefers the desktop launch branch because CLI originalBranch means the source checkout before worktree creation, not necessarily the selected base ref. Constraint: CLI worktree-state carries runtime identity; Desktop repository metadata carries launch intent. Rejected: Let desktop repository metadata override worktree-state | stale placeholder metadata can resurrect the wrong slug, path, or source cwd after reload. Confidence: high Scope-risk: narrow Directive: Worktree identity fields should prefer CLI worktree-state; only branch display may prefer desktop launch intent. Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern worktree-state|worktree identity|git-info Tested: cd desktop && bun run lint Tested: git diff --check
This commit is contained in:
parent
f46b0c80cd
commit
f92083ac0c
@ -1677,6 +1677,58 @@ describe('Sessions API', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('GET /api/sessions/:id/git-info should prefer CLI worktree-state identity over desktop metadata', async () => {
|
||||
const workDir = await createCleanGitRepo(tmpDir)
|
||||
const sessionId = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
const activeWorktree = path.join(workDir, '.claude', 'worktrees', 'desktop-main-12345678')
|
||||
git(workDir, 'worktree', 'add', '-b', 'worktree-desktop-main-12345678', activeWorktree, 'main')
|
||||
await writeSessionFile(sanitizePath(activeWorktree), sessionId, [
|
||||
makeSnapshotEntry(),
|
||||
{
|
||||
type: 'session-meta',
|
||||
isMeta: true,
|
||||
workDir: activeWorktree,
|
||||
repository: {
|
||||
requestedWorkDir: '/stale/source',
|
||||
repoRoot: '/stale/source',
|
||||
branch: 'main',
|
||||
worktree: true,
|
||||
baseRef: 'main',
|
||||
worktreePath: '/stale/source/.claude/worktrees/stale',
|
||||
worktreeBranch: 'worktree-stale',
|
||||
worktreeSlug: 'stale',
|
||||
},
|
||||
timestamp: '2026-01-01T00:00:00.000Z',
|
||||
},
|
||||
makeWorktreeStateEntry(sessionId, activeWorktree, {
|
||||
originalCwd: await fs.realpath(workDir),
|
||||
}),
|
||||
makeUserEntry('Hello from persisted worktree state'),
|
||||
])
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/sessions/${sessionId}/git-info`)
|
||||
expect(res.status).toBe(200)
|
||||
|
||||
const body = (await res.json()) as {
|
||||
branch: string | null
|
||||
worktree: {
|
||||
path: string | null
|
||||
plannedPath: string | null
|
||||
sourceWorkDir: string | null
|
||||
slug: string | null
|
||||
branch: string | null
|
||||
} | null
|
||||
}
|
||||
expect(body.branch).toBe('main')
|
||||
expect(body.worktree).toMatchObject({
|
||||
path: activeWorktree,
|
||||
plannedPath: activeWorktree,
|
||||
sourceWorkDir: await fs.realpath(workDir),
|
||||
slug: 'desktop-main-12345678',
|
||||
branch: 'worktree-desktop-main-12345678',
|
||||
})
|
||||
})
|
||||
|
||||
it('DELETE /api/sessions/:id should delete the session', async () => {
|
||||
const sessionId = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
await writeSessionFile('-tmp-api-test', sessionId, [makeSnapshotEntry()])
|
||||
|
||||
@ -541,15 +541,18 @@ async function getGitInfo(sessionId: string): Promise<Response> {
|
||||
const launchInfo = await sessionService.getSessionLaunchInfo(sessionId).catch(() => null)
|
||||
const repository = launchInfo?.repository
|
||||
const worktreeSession = launchInfo?.worktreeSession
|
||||
// The visible business branch comes from Desktop's launch choice when present.
|
||||
// CLI originalBranch is the source checkout before creating the worktree, which
|
||||
// can differ from the selected base ref.
|
||||
const sessionBranch = repository?.branch || worktreeSession?.originalBranch || null
|
||||
const worktree = repository?.worktree || worktreeSession
|
||||
? {
|
||||
enabled: true,
|
||||
path: worktreeSession?.worktreePath || workDir,
|
||||
plannedPath: repository?.worktreePath || worktreeSession?.worktreePath || null,
|
||||
sourceWorkDir: repository?.requestedWorkDir || repository?.repoRoot || worktreeSession?.originalCwd || null,
|
||||
slug: repository?.worktreeSlug || worktreeSession?.worktreeName || null,
|
||||
branch: repository?.worktreeBranch || worktreeSession?.worktreeBranch || null,
|
||||
plannedPath: worktreeSession?.worktreePath || repository?.worktreePath || null,
|
||||
sourceWorkDir: worktreeSession?.originalCwd || repository?.requestedWorkDir || repository?.repoRoot || null,
|
||||
slug: worktreeSession?.worktreeName || repository?.worktreeSlug || null,
|
||||
branch: worktreeSession?.worktreeBranch || repository?.worktreeBranch || null,
|
||||
}
|
||||
: null
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user