Skip to content

refactor(web): address current-platform-assistant store PR feedback (LUM-1718)#31435

Merged
ashleeradka merged 2 commits into
mainfrom
claude/refactor-platform-assistant-hook-DRjFS-followup
May 21, 2026
Merged

refactor(web): address current-platform-assistant store PR feedback (LUM-1718)#31435
ashleeradka merged 2 commits into
mainfrom
claude/refactor-platform-assistant-hook-DRjFS-followup

Conversation

@ashleeradka
Copy link
Copy Markdown
Contributor

Follow-up to #31433. Addresses all three review comments:

Changes

1. Fix multi-tab clobbering of other-org keys (codex P1)

The previous writeByOrgToLocalStorage treated the in-memory byOrg snapshot as authoritative and removed every prefixed localStorage key not present in it. The snapshot is only as fresh as the last rehydrate(), so a stale tab could delete selections that another tab had just written for unrelated orgs.

The storage adapter now writes per-org keys additively — only when the in-memory value differs from what's already in localStorage — and never removes keys absent from the snapshot. Deletions (setAssistantId(orgId, null)) are issued imperatively by the action against the specific affected key, so they don't get conflated with the additive write path.

2. Call store action via .getState() inside effects/callbacks (devin)

Per docs/STATE_MANAGEMENT.md, actions are stable references and should be called via useStore.getState().action() from event handlers, callbacks, and effects — not subscribed via .use.action(). The hook now does that, dropping the unnecessary subscription and the dep-array entry.

3. Drop unused getAssistantId action (devin)

getAssistantId was unused — the hook reads byOrg directly and there are no other callers. Removed per the repo's dead-code rule.

Linear: https://linear.app/vellum/issue/LUM-1718

Test plan

  • bunx tsc --noEmit passes
  • bun run lint passes (no new warnings)
  • Settings → Switch Assistant: selection persists across reload
  • Two-tab scenario: switching assistant in tab A for org1 does not clear the stored selection for org2 in tab B
  • Setting setAssistantId(orgId, null) removes only that org's localStorage key

Generated by Claude Code

- Stop deleting other-org localStorage keys on persist write. The
  in-memory `byOrg` snapshot is only as fresh as the last rehydrate,
  so a stale tab could clobber selections written by other tabs for
  unrelated orgs. The storage adapter now writes per-org keys
  additively, and `setAssistantId(orgId, null)` removes only its
  own key directly.
- Call `setAssistantId` via `useCurrentPlatformAssistantStore.getState()`
  inside `useEffect` / `useCallback` per `STATE_MANAGEMENT.md` —
  drops the unnecessary subscription and the dep-array entry.
- Drop the unused `getAssistantId` action; the hook reads `byOrg`
  directly and no other caller exists.
@linear
Copy link
Copy Markdown

linear Bot commented May 21, 2026

LUM-1718

@ashleeradka ashleeradka marked this pull request as ready for review May 21, 2026 02:44
@ashleeradka
Copy link
Copy Markdown
Contributor Author

@codex

Copy link
Copy Markdown
Contributor

@vex-assistant-bot vex-assistant-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE

All three follow-up items are correctly resolved.


Fix 1 — Multi-tab additive writes (Codex P1)

The root cause was real: writeByOrgToLocalStorage(byOrg) deleted every prefixed key absent from the in-memory snapshot, but that snapshot is only as fresh as the last rehydrate(). A stale tab could clobber live writes from another tab for unrelated orgs.

New setItem writes additively — only when the stored value differs from the incoming value — and never deletes:

if (window.localStorage.getItem(key) !== id) {
  window.localStorage.setItem(key, id);
}

The if-differs guard also suppresses spurious storage events, which is a nice side-effect.

Deletions for setAssistantId(orgId, null) are issued imperatively in the action via removeStoredAssistantId(orgId) — which fires a storage event in other tabs → they call persist.rehydrate()readByOrgFromLocalStorage() no longer sees the deleted key → cross-tab propagation is correct. The order in the action (localStorage remove before set()) is right.

removeItem no-op is fine — persist.clearStorage() isn't exposed by this store, so it's never called.

Fix 2 — .getState() for actions in effects/callbacks (Devin)

Per STATE_MANAGEMENT.md, calling store actions via useStore.getState().action() from effects and callbacks is correct — getState() is called at invocation time (not render), so it always resolves the current action. Removing setAssistantIdAction from the subscription and from the dep array is right: subscribing to an action via .use.setAssistantId() was unnecessary overhead (actions are stable refs), and the dep array entry was vestigial.

Fix 3 — getAssistantId dead code (Devin)

No callers inside or outside the hook. The get parameter is correctly dropped from the store factory since nothing calls it anymore.

storageKeyForOrg helper

Good extraction — used in both setItem (write path) and removeStoredAssistantId (imperative delete path), eliminating the inline template literal duplication.

CI — 7/7 green. ✅

@vex-assistant-bot
Copy link
Copy Markdown
Contributor

@codex review
@devin review this PR

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ashleeradka ashleeradka merged commit e9bae6f into main May 21, 2026
7 checks passed
@ashleeradka ashleeradka deleted the claude/refactor-platform-assistant-hook-DRjFS-followup branch May 21, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants