[lenny] fix(desktop): keep a lone live persona instance on its canonical card - #34
Conversation
…cal card `buildPersonaCards` split a persona into per-name cards whenever more than one display group existed, keying each split card `<persona id>::<folded name>`. It only collapsed back to the canonical persona card when *zero* live groups remained. With one archived instance and one live sibling, that left a single live group still travelling the split path, so the persona's only card was keyed `<persona id>::<name>` instead of `<persona id>`. Every deep link to the persona — `persona-agent-row-<persona id>` — then pointed at a card that no longer existed, and archived-profile navigation dead-ended. A split card only earns its own identity when a rival live name exists. With one live name left, the persona's name again stands for every surviving instance, so collapse on `liveGroups.length <= 1`. This regression is fork-local (47cc906, 3acf014); it broke the upstream spec exact-key-profile.spec.ts:84 "archived exact key stays navigable (live sibling)", which had been failing on every PR and blocking the whole queue. Verified: exact-key-profile.spec.ts 4/4 passed (was 3 passed / 1 failed); desktop unit suite 6583/6583 passed.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
CI verdict: the queue-blocking failure is fixed (run 34584166278)The test this PR targets now passes on the WSL runners. Smoke shard 2 (job Shard 2 previously reported 399 passed / 1 failed with Remaining red is pre-existing, not from this diffShards 3 and 4 are still red. Every genuine failure in them also fails on #32 and #33, which do not contain this change:
Shard 3 = 289 passed / 1 failed; shard 4 = 338 passed / 3 failed / 7 flaky. This diff touches exactly one function, Gate evidence
The remaining shard-3/4 red is a separate pre-existing problem worth its own fix; it is not a regression from this PR and was blocking the queue before this branch existed. |
Merging with documented exception (owner-approved)Approved by @mfethe1 in-session. Every failing check on this PR is attributed to a cause outside this diff:
This diff's own effect is positive and measured.
That is why this PR merges first: it repairs |
|
| ref | run 1 | run 2 | run 3 |
|---|---|---|---|
origin/product/main (base) |
1 failed | 1 failed | 1 failed |
Signature reproduced verbatim against CI:
Error: locator.hover: Error: strict mode violation: getByText('Toggle me') resolved to 2 elements:
1) <div role="status" class="sr-only" aria-atomic="true" aria-live="polite"
data-testid="message-timeline-announcements">…
2) <p>Toggle me</p> aka getByTestId('message-timeline').getByText('Toggle me')
Cause: TimelineAnnouncementRegion's announcementForMessage() emits `${author}: ${body}` → "Alice: Toggle me". getByText('Toggle me') substring-matches both the live region and the message body, so the locator is ambiguous.
Why it isn't ours: the component is already present on origin/product/main (git cat-file -e confirms), and none of #34/#35/#36 touch thread-unread.spec.ts (git diff --name-only = 0 for each).
Recommended fix (spec-side, for the spec owner): scope the locator — page.getByTestId('message-timeline').getByText('Toggle me'), or { exact: true }. The live region content is correct a11y behaviour and should not be changed to satisfy a loose locator.
With this, all six failures feeding the Desktop aggregate gate are attributed outside these three PRs' diffs.
The queue-blocking test failure has a real cause
exact-key-profile.spec.ts:84 "archived exact key stays navigable (live sibling)"has been failing on every open PR (#15, #31, #32, #33), consuming the desktop E2E gates and blocking the merge queue. It was being treated as an environment flake. It is not — it is a fork-local regression with a deterministic reproduction.Root cause
buildPersonaCards(desktop/src/features/agents/ui/unifiedAgentGroups.ts) splits a persona into per-name cards whenever more than one display group exists, keying each split card<persona id>::<folded name>. It collapsed back to the canonical persona card only when zero live groups remained:The failing scenario is one archived instance ("Archived A") plus one live sibling ("Sibling B"):
displayGroups.length === 2→ takes the split pathliveGroups.length === 1→ does not collapseSo the persona's only card is keyed
P::sibling binstead ofP. The spec'spersona-agent-row-${PERSONA}locator then points at a card that no longer exists,locator.clicktimes out after 30s, and archived-profile navigation dead-ends for real users too.The sibling case
(all archived)passes becauseliveGroups.length === 0collapses correctly — which is why only one of the two parametrised cases ever failed.Fix
A split card only earns its own identity when a rival live name exists. With one live name left (or none), the persona's name again stands for every surviving instance, so it keeps its canonical card and key:
Provenance — this is ours, not upstream
The split-card logic is fork-local;
desktop/tests/e2e/exact-key-profile.spec.tsis byte-identical toupstream/main. The regression came from47cc90626d/3acf014ab3, neither of which is an ancestor ofupstream/main. We broke an upstream test.Verification (local, this branch, on top of
adeec6eb5c)exact-key-profile.spec.ts(smoke): 4 passed — previously 3 passed / 1 failed, failing all 3 retriesnpm test): 6583 passed, 0 failed, 90 suitesunifiedAgentGroups.test.mjs: 20/20 passedReproduced the failure locally before the change and confirmed it green after, using
pnpm build:e2e(the E2E bundle — notenpm run buildproduces the OSS variant and is not what the specs serve).Note for reviewers
This should unblock the desktop E2E gates across the other open PRs. The remaining rollup gates (
Windows Rust,PostgreSQL Tests, etc.) are separate 3-secondCheck <name> resultjobs that fail because their underlying builds are SKIPPED — that is the ruleset-satisfiability issue, unrelated to this fix.