Add worktree control center - #429
Conversation
SergeSerb2
left a comment
There was a problem hiding this comment.
Good foundation for worktree control, but critical correctness issue: new ChatThread fields must be added to displayEquivalent(). The diff adds branch and worktreePath fields to ChatThread and updates the equality operator, but does not show updates to the displayEquivalent(to:) method. Per the project memory (PR #328), missing displayEquivalent changes cause thread upserts to silently drop—any worktree-related metadata changes won't persist to the database. The rest of the implementation is solid: clean separation between UI, AppModel, and backend layers; proper rollback on failures; reasonable error messages.
Could not anchor
- blocking
apps/mac/Sources/SurgeCodeMac/Model/Entities.swift— The newbranchandworktreePathfields were added to ChatThread and included in the==operator, but the diff does not show updates todisplayEquivalent(to:). Per project memory, this causes thread upserts to silently fail when these fields change. Verify thatdisplayEquivalent()includes both new fields, and add any missing memoization tests.
SurgeCode auto-review · model=codex/gpt-5.6-luna · head=021e704a815d
| } | ||
| } | ||
|
|
||
| private func remove(_ snapshot: WorktreeControlSnapshot) { |
There was a problem hiding this comment.
nit: Minor: runOperation() only updates the selected snapshot after reload if it matches the edited thread. Consider also showing an inline success toast or re-selecting the repair result to confirm the action completed.
| : projectOrder == .orderedAscending | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
info: The worktreeSnapshots() loop fetches archived threads one page at a time. On repos with many archived threads, this could be slow. Consider caching or paginating results if performance becomes an issue.
SergeSerb2
left a comment
There was a problem hiding this comment.
Three critical issues block merge:
-
Window lifecycle bug (memory leak):
WorktreeControlCenterWindowControllerholdsisReleasedWhenClosed = false, making the window persist forever and unable to reopen cleanly. -
VCS refresh scope mismatch: Line 1790 refreshes
input.path(worktree subdir) but should refreshinput.cwd(repo root) to matchremoveWorktree's pattern.git statusrequires a working repository root. -
Missing memoization test for
branchfield: Thebranchfield was added todisplayEquivalent()butAppModelRenderMemoizationTests.displayEquivalentComparesAllButUpdatedAtdoes not test it. A branch-only upsert will silently drop (per [[displayEquivalent field trap]]). Add a test case.
Diff compiles and structure is solid otherwise. No test for the new UI itself (that requires approvals).
Could not anchor
- important
apps/mac/Tests/SurgeCodeMacTests/AppModelRenderMemoizationTests.swift:247 — Missing test case forbranchfield changes. The field is now indisplayEquivalent()but this test does not verify it. Add a case after the snooze test (after line 246):
// Branch-only upsert must not be judged equivalent.
b = a
b.branch = "feature/other"
#expect(!a.displayEquivalent(to: b))Without this, a thread that changes branches silently skips sidebar upsert.
SurgeCode auto-review · model=codex/gpt-5.6-luna · head=f4abf694f899
| panel.titlebarAppearsTransparent = true | ||
| panel.title = "Worktree Control Center" | ||
| panel.isReleasedWhenClosed = false | ||
| panel.delegate = self |
There was a problem hiding this comment.
blocking: Window is never released: isReleasedWhenClosed = false and the controller is a static singleton. After first open, the window persists and cannot be closed/reopened cleanly. Change to true:
panel.isReleasedWhenClosed = true| WS_METHODS.vcsRepairWorktree, | ||
| gitWorkflow.repairWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.path))), | ||
| { "rpc.aggregate": "vcs" }, | ||
| ), |
There was a problem hiding this comment.
blocking: VCS refresh uses wrong path scope. repairWorktree refreshes input.path (the worktree subdir) but should refresh input.cwd (the repo root), matching removeWorktree below it. Git status needs the working repository root:
gitWorkflow.repairWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd)))
Summary
vcs.repairWorktreecontract and server implementation; no host-wide inventory or status API is introduced.Area
apps/mac— native macOS appapps/windows— Windows desktop appapps/mobile— iPhone companion appapps/server— backend serverpackages/contracts,packages/shared,packages/client-runtime, …) or relay (infra/relay)Release size
size:XS— tiny internal, documentation, or narrowly scoped fixsize:S— small user-visible fix or contained improvementsize:M— normal feature or meaningful behavior changesize:L— broad feature or substantial cross-package changesize:XL— release-system, architecture, or ecosystem-scale changeVerification
pnpm run verify --allpasses (check + typecheck + tests; addslint:mobileand the Swift suite)pnpm run test:macpasses (required forapps/macchanges)The debug macOS executable launched successfully. Interactive desktop verification was unavailable because the automation host denied screen capture.
Screenshots / Recordings
Not attached: macOS screen recording is unavailable to the automation host (
screencapturereturnedcould not create image from display).Release notes
Manage thread-owned worktrees from a native control center with status, disk use, handoff, repair, creation, and safe removal controls.