Conversation
A task whose projectId no longer names any visible project scope still got a 'Remove from project' row: both the navigation provider's target builder and the ui list's filter read 'is this task in a project?' as 'is projectId truthy?', so an id orphaned by a deleted or archived project rode the submenu as a lone remove entry on a task that already reads project-less. The provider's target builder (extracted to a pure, tested helper) offers the leave-row only while the pointed-at project is among the visible scopes, and the ui list's filter applies the same visibility check for whatever producer feeds it. Fixes apache#5725 Generated-by: GLM-5.3-Flash (ZCode)
hqhq1025
left a comment
There was a problem hiding this comment.
This change removes the orphaned Remove from project row by deriving menu targets from available, unarchived scopes and checking membership again in the UI. I found one alias-membership regression (inline P2): a task can visibly belong to a project under an alias ID but lose the remove option. No schema migration is involved.
I checked the five-file diff, scope source, project alias resolution, menu/drop consumers, and the added builder tests. The current-head CI test and label checks passed; merge-tree and diff-check were clean against the latest main. I did not run a local Desktop build or manually reproduce the macOS UI case. The new tests cover canonical IDs, orphan IDs, and null IDs but not aliases. Human review is still needed before merging.
Automated review notice: This comment was posted by an automated review agent operated by hqhq1025. It is not an independent human review and does not replace one.
| })); | ||
| if ( | ||
| session.projectId && | ||
| targets.some((target) => target.projectId === session.projectId) |
There was a problem hiding this comment.
[P2] Resolve project aliases before deciding whether this task can leave its project. A relink/merge records the absorbed ID in project.aliases (packages/storage/src/project-catalog.ts:700-704), and the rail explicitly maps that alias to the visible project (session-navigation-groups.ts:99-105). For a visible scope with id='new', aliases=['old'] and a session with projectId='old', the task is displayed inside that project, but this strict-ID check returns false and never supplies the null exit. The UI's separate strict-ID check in packages/ui/src/session-history-list.tsx:1473-1478 would also drop that exit even if the builder supplied it. With no other destination, the Move menu vanishes entirely, so the user cannot remove a task that is visibly in a project. Please use the same canonical/alias membership rule in both guards and add an alias regression.
|
Closing as superseded by #5726, which landed the same orphan guard through a dedicated After merging current |
Fixes #5725
Summary
projectIdno longer names any visible project scope still got a "Remove from project" row: the navigation provider's target builder pushed theprojectId: nullexit wheneversession.projectIdwas truthy, and the ui list's filter kept that exit whenevercurrentProjectIdwas truthy. An id orphaned by a deleted, archived, or relocated project therefore rode the "Move to project" submenu as a lone remove entry on a task that already reads project-less.buildSessionMoveTargetsinsession-navigation-groups.ts) now offers the leave-row only while the pointed-at project is among the visible scopes.inVisibleProject), so the submenu can never render the lone remove-row regardless of the source.Verification
buildSessionMoveTargets: in-project task → visible projects + leave rowbuildSessionMoveTargets: orphanedprojectId→ no leave rowbuildSessionMoveTargets: project-less task → no leave rowsession-navigation-move-to-projectandsession-history-project-dropsuitesbiome formaton touched filesbiome.jsonc; no formatted-path files touchedNot verified locally: full CI on Linux, and the real-app repro (macOS report) — the fix is covered at the builder and filter layers instead.
AI use
Implemented with GLM-5.3-Flash (ZCode): the pure-builder extraction, both visibility guards, and the tests.