fix: report project removal teardown blockers#2783
Conversation
Nyrokume
left a comment
There was a problem hiding this comment.
Verdict: changes requested
Right direction (aggregate teardown outcomes, return PROJECT_REMOVE_BLOCKED instead of 500), but the blocker policy conflicts with #2598's main requirement: stale/non-dirty local state must not block unregister.
Must fix
- Non-dirty cleanup skips become blockers ??? every
cleanup.Skippedis appended, includingworkspace teardown failed. #2598 says missing/prunable/stale worktree metadata should be best-effort and allow unregister; only preserved user work should conflict. Mirror #2599'sUserWorkPreserved(or equivalent) gate. - Kill failures block removal ???
session teardown failedblockers prevent delete on the exact stale-runtime cases the issue wants to tolerate. Prefer best-effort continue (log the cause) unless you can prove the failure protects user data. - Happy-path test does not assert empty blockers ??? default
fakeCommander.Cleanupstill returns a dirty skip former-2, soTeardownProjectreturns blockers while the test only checkserr == nil. Assertlen(out.Blockers)==0(and override cleanup result) so Remove cannot silently conflict on the "success" fixture. - OpenAPI/frontend schema omit 409 for
DELETE /projects??? wire the conflict inspecgen+ regenerate like #2599, or clients keep treating this as an unexpected status.
Notes
| SessionID: skip.SessionID, | ||
| Phase: "cleanup", | ||
| Reason: skip.Reason, | ||
| }) |
There was a problem hiding this comment.
Product mismatch with #2598: promoting every cleanup skip to a blocker means non-dirty workspace teardown failed prevents project unregister. Stale/prunable/missing worktree metadata must be best-effort. Only treat skips that preserve user work (e.g. ErrWorkspaceDirty / a UserWorkPreserved flag) as blockers.
| SessionID: rec.ID, | ||
| Phase: "kill", | ||
| Reason: "session teardown failed", | ||
| }) |
There was a problem hiding this comment.
Turning all Kill errors into blockers re-blocks delete on stale runtime/workspace failures ??? the primary #2598 failure mode. Prefer best-effort continue + Warn log (and only conflict when user work is preserved).
| svc := &Service{manager: fc, store: st} | ||
|
|
||
| if err := svc.TeardownProject(context.Background(), "mer"); err != nil { | ||
| if _, err := svc.TeardownProject(context.Background(), "mer"); err != nil { |
There was a problem hiding this comment.
This test ignores the outcome's blockers while the default fake cleanup still skips mer-2 as dirty. Assert len(out.Blockers) == 0 and pass an empty cleanupResult, otherwise Remove would 409 on the supposed happy path.
Summary
Fixes #2598
Tests
Risks