Repository navigation
fix(platform): keep an assignee handoff on the task it was asked for - #4393
yannickmonney wants to merge 1 commit into
Conversation
|
Independent review for TALE-911 / TALE-331 / TALE-359 (Codex #11, not implementer #6). Exact head: Verdict: no blocking code finding in this change. CI and complete local type/consumer validation remain outstanding; this is not a green-CI or merge authorization verdict. The key is on both possible state-owning picker subtrees. Switching task identities unmounts the old list/confirmation and prevents a late guarded response from installing state on the next task. The asynchronous direct-assignment and confirmed-cancellation continuations retain the original task's callbacks and IDs. The modal's actual assignment closures capture Validation with existing dependencies and
CI still has queued scope/commitlint checks and skipped candidate-source checks, with no failed result to attribute. Main's compact-age test repair is confirmed as Posting here as the requested fallback for TALE-331 and TALE-359 ( |
d46b926 to
235f128
Compare
11b635b to
7c1d251
Compare
7c1d251 to
cdaa93e
Compare
What changed
The task modal keeps one Assign picker while a parent link or a subtask opens another task; it is not keyed by task id (unlike the title and description editors next to it). The picker's handoff guard did three things on task A: it ran the live-run reads, stored the picked change (not scoped to a task) once they answered, and later cancelled and reassigned with the picker's current props. If the reads answered after the modal had moved to task B, Reassign this task? opened over B. Confirming it cancelled B's run and handed B to the person picked for A (#3915).
AssigneePickernow keys its trigger/list bytaskId. Each task gets its own picker instance, so a task switch drops the old instance's live-run verdict, open confirm, busy state and open list:onAssignclosure (the task modal bindstask._idthere). B'sonAssignis never called.I chose the key over storing the task id in the pending state. With the key, every closure the handoff uses (reads, the cancel,
onAssign) belongs to one task. The cancel is never bound to A while the assign goes through B's callback. The fix lives in the picker, so the board card and the list row are covered too; those already mount one picker per task.No new copy, so there are no locale changes. The register line is in
services/platform/tests/manual/reference/automation.md, as a new paragraph right after the "Automation-owned tasks retain their workflow name…(#3849)" paragraph.Backend
No change is needed.
assignTaskalready refuses a reassign while a live run holds the task (TASK_HAS_LIVE_RUN,backend/domains/tasks/service.ts), which is why the picker cancels first. The wrong-target requests were well-formed and authorized writes for B, so the server cannot tell they were meant for A. The defect was client state crossing task identities.How I verified it
New
app/features/tasks/components/assignee-picker.handoff.test.tsx(jsdom) has 5 tests. Each live-run read is held per task, and the test re-renders the same picker element with the next task's props, the way the task modal does:New
app/features/tasks/components/task-modal.assignee-handoff.test.tsx(jsdom, with the access suite's seams) runs the issue's path through the realTaskModal,EditTaskBody,TaskParentLink,AssigneePickerandConfirmDialog. It opens subtask A (automation-assigned, live run), picks Alex, clicks the real Part of TEST-2 link, waits for B's heading, then answers A's held read. No Reassign this task? opens over B, and nothing is written. The same-task control confirms and writes exactly the cancel{organizationId:'org-1',taskId:'task-a'}, thenassignTask {taskId:'task-a',assigneeType:'user',assigneeId:'user-1'}.Red on main (
assignee-picker.tsxfromorigin/main):user-1, A's pick.Green on this branch, one worker: the 3 handoff files (21 tests). Earlier, on the fix commit: the 5 new picker tests,
assignee-picker.test.tsxand the jsdom suites that render the picker's consumers (task-modal access/attachments/draft/limits/repeat, task-card, tasks-list, tasks-workspace, board dnd). That is 13 files and 115 tests passing.oxlintandoxfmt --checkon the changed files are clean, andbun run lint:manualpasses.Scoped
tsc(changed and new files, consumers andapp/router.tsx): exit 0.Register anchor, checked with
git merge-treeagainst the head of each of the 41 open PRs that editautomation.md:assignee-picker.tsx(fix(platform): cut the per-card mount cost of large task boards #4083, fix(platform): hide unavailable managed standard agents #4168) already conflict with main. This branch adds no conflict hunk to either.Real Chromium: I ran both new suites unchanged in headless Chromium 1194 through a review-only vitest browser config kept outside the repo (
define: { global: 'globalThis' }fortests/setup-ui.ts,server.fs.allowfor the workspace). With the fix, 7/7 pass. With main's picker, 4/7 fail: the same cases as in jsdom.Not covered: the full app against a live backend, and a live run's cancellation. The tests observe the request arguments at the client boundary.
Closes #3915
Current-main rebase
Replayed the previously accepted source
11b635b6f5e2d11b63fc0ed78ec2ebd2e979d0b1onto maind1373d84cd56972501403f62145ec52e6f65d44a, including the merged shared CI repair in #4625. The accepted feature payload and all current-main changes are preserved in one atomic commit. Configured commit and conflict checks pass; earlier behavioral proof remains recorded above. All seven native required checks and full merge-group validation remain required for this new source.Maintenance replay: preserves the accepted feature payload on main fd277c4, including merged #4649, #4650 and #4655. Retains the exact independently accepted one-line shared CLI inventory repair from #4654 (252f0df), pending native merge on main. The #4282 task-register union, where applicable, retains the accepted feature row and current-main rows. Existing behavioral evidence remains recorded above; no fresh full-feature/full-workspace or hosted-green claim. All seven native required contexts and full merge-group validation remain mandatory.