Skip to content

[codex] Track workspace transaction state#4740

Merged
saddlepaddle merged 3 commits into
mainfrom
fix-tanstack-loading-stat
May 20, 2026
Merged

[codex] Track workspace transaction state#4740
saddlepaddle merged 3 commits into
mainfrom
fix-tanstack-loading-stat

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented May 19, 2026

Summary

  • Track workspace TanStack DB transaction projections by workspace id, including mutation type and state.
  • Augment dashboard sidebar workspace rows with pendingTransaction instead of deriving create loading from ``.
  • Show workspace creation loading only for pending insert transactions, so rename/task-link updates no longer show the create state.
  • Clear transaction projections when persistence settles or when Electric confirms the row as synced.

Root Cause

`` is a row-level optimistic-state flag. It becomes false for any pending optimistic mutation, including updates, so using it as “workspace is being created” made normal workspace edits look like creates.

Validation

  • bun run lint
  • bun run --cwd apps/desktop typecheck

Open in Stage

Summary by cubic

Track per-workspace transaction state to show “creating” only for inserts and keep update transactions until they finish. Insert transactions auto-clear on persistence or when $synced === true; updates are preserved until persistence settles and no longer block workspace usage.

  • New Features

    • Added useWorkspaceTransactionsStore to snapshot per-workspace transactions (id, type, state, timestamps) and clear them on settle.
    • Exposed pendingTransaction on sidebar workspace data; insert transactions clear on $synced === true, updates are not cleared by sync.
    • Insert, update, and rename mutations register with the store; layout and sidebar use this to gate host status, “ensure in sidebar,” and creation state.
  • Bug Fixes

    • Replaced !isSynced checks with isCreatePending (only when type is insert), so edits no longer show the create spinner.
    • Workspace view, host status, and shortcuts are blocked only during creates; spinner shows for creates or when workspaceStatus === "working".

Written for commit c0b29d1. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Refactor
    • Sidebar now tracks workspace operations via transaction-based pending state instead of sync flags.
  • New Features
    • Workspaces being created show a distinct "creating" state (spinner/icon) and are excluded from hover/shortcut lists.
  • Bug Fixes
    • Pending create state is automatically cleared once a workspace finishes syncing, improving sidebar consistency.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4a7d1e66-0711-4908-955f-e3bd67b65426

📥 Commits

Reviewing files that changed from the base of the PR and between 89772cb and c0b29d1.

📒 Files selected for processing (4)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useOptimisticCollectionActions/useOptimisticCollectionActions.ts
  • apps/desktop/src/renderer/stores/workspace-creates/index.ts
  • apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx

📝 Walkthrough

Walkthrough

Replace sync-based "pending" logic with a per-workspace transaction store and derive create-pending state from active insert transactions; wire the store into creation hooks, optimistic actions, sidebar data, UI components, shortcuts, and the v2 workspace layout.

Changes

Workspace Transaction Tracking

Layer / File(s) Summary
Transaction store implementation
apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts, apps/desktop/src/renderer/stores/workspace-creates/index.ts
Adds WorkspaceTransactionType, WorkspaceTransactionState, WorkspaceTransactionSnapshot and useWorkspaceTransactionsStore; store writes per-workspace snapshots, awaits transaction.isPersisted.promise, and clears on terminal states; re-exported from the barrel.
Track transactions in creation & updates
apps/desktop/src/renderer/stores/workspace-creates/useWorkspaceCreates.ts, apps/desktop/src/renderer/routes/_authenticated/hooks/useOptimisticCollectionActions/useOptimisticCollectionActions.ts
useWorkspaceCreates and optimistic actions capture optimistic transactions and call trackWorkspaceTransaction(workspaceId, transaction); PersistableTransaction shape extended and hooks' dependency lists updated.
Sidebar types & data integration
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts, apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts
DashboardSidebarWorkspace adds pendingTransaction; sidebar data hook reads byWorkspaceId and clear from the store, augments workspaces with pendingTransaction, and clears insert transactions when workspace .$synced === true.
Sidebar UI components: pending-state wiring
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/...
Sidebar components switch from isSynced to pendingTransaction?.type === "insert" for create-pending: DashboardSidebarWorkspaceItem derives isPending and passes isCreatePending; collapsed button and icon props updated; expanded row and end-of-row controls gated by !isPending.
Sidebar shortcuts & workspace layout
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts, apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx
Shortcuts filter excludes pending-insert workspaces. V2 layout derives isCreatePending from the store, gates ensureWorkspaceInSidebar with canUseWorkspace, passes null to useRemoteHostStatus while creating, clears insert transactions when synced, and shows WorkspaceCreatingState when create-pending.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • superset-sh/superset#4707: Both PRs modify the DashboardSidebar workspace UI to change how "creating/pending" state is derived.

Poem

🐰 I hop to track each hopeful start,

transactions noted, never apart.
Pending inserts in tidy rows,
Cleared when synced — how the pipeline grows! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: implementing transaction state tracking for workspaces, which aligns with the comprehensive refactoring across multiple sidebar and workspace components.
Description check ✅ Passed The description includes a clear summary of changes, root cause analysis, and validation steps, though the linked issues section is absent and some template sections are not fully completed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-tanstack-loading-stat

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@stage-review
Copy link
Copy Markdown

stage-review Bot commented May 19, 2026

Ready to review this PR? Stage has broken it down into 5 individual chapters for you:

Title
1 Create workspace transaction state store
2 Track transactions in optimistic actions
3 Expose pending transactions in sidebar data
4 Update sidebar UI to use transaction state
5 Refine workspace layout loading states
Open in Stage

Chapters generated by Stage for commit c0b29d1 on May 19, 2026 11:55pm UTC.

@saddlepaddle saddlepaddle marked this pull request as ready for review May 19, 2026 23:44
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR fixes a bug where workspace edits (rename, task-link update) incorrectly showed the "Creating workspace" spinner by replacing the row-level isSynced / $synced flag with a new Zustand store (useWorkspaceTransactionsStore) that tracks per-workspace transaction snapshots keyed by type (insert | update | delete). The creation spinner is now gated on pendingTransaction?.type === "insert" rather than !isSynced.

  • New workspaceTransactions store snapshots each mutation's id, type, and state; clears on isPersisted.promise settlement; insert transactions are also cleared when $synced === true via useEffect hooks in layout.tsx and useDashboardSidebarData.
  • Sidebar, icon, and shortcuts propagate pendingTransaction from the store instead of deriving from isSynced, and filter/render accordingly.
  • useOptimisticCollectionActions now calls trackWorkspaceTransaction for both updateWorkspace and renameWorkspace so update transactions are recorded and their lifecycle is observable.

Confidence Score: 3/5

The core logic is sound, but the double-write in workspaceTransactions.ts introduces a window where a stale snapshot can be observed, and the "completed"/"failed" state values exported from the store are never reliably visible to consumers.

The queueMicrotask re-write in workspaceTransactions.ts has a real ordering hazard: if two track() calls for the same workspace fire synchronously (e.g. an updateWorkspace + renameWorkspace chain in one event handler), the first call's microtask runs after the second call's synchronous write and temporarily installs the stale tx1 snapshot. Any subscriber rendering between the two microtasks would show the wrong transaction type — potentially re-displaying the "Creating workspace" spinner on a workspace that already exists. The self-correction happens one microtask later, but the intermediate render is observable. The rest of the change — sidebar propagation, hook wiring, dependency arrays — is clean.

workspaceTransactions.ts is the file that needs the most attention; layout.tsx deserves a second look for the changed guard semantics around ensureWorkspaceInSidebar and useRemoteHostStatus.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts New Zustand store tracking per-workspace transaction snapshots; the synchronous write + queueMicrotask double-write pattern can briefly resurrect a stale snapshot when two track() calls for the same workspaceId happen in the same synchronous run, and the "completed"/"failed" state values are immediately cleared and effectively unobservable.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx Replaces isSynced ($synced) guard with isCreatePending (transaction store check); ensureWorkspaceInSidebar and useRemoteHostStatus now fire sooner for cached-but-not-yet-synced pre-existing workspaces.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts Injects pendingTransaction from the new store into sidebar workspace data and adds a useEffect to clear insert transactions on isSynced; logic is sound and dependencies look correct.
apps/desktop/src/renderer/routes/_authenticated/hooks/useOptimisticCollectionActions/useOptimisticCollectionActions.ts Wires update/rename mutations through trackWorkspaceTransaction; the new fields added to PersistableTransaction are all required, and trackWorkspaceTransaction is correctly added to the useMemo dependency array.
apps/desktop/src/renderer/stores/workspace-creates/useWorkspaceCreates.ts Tracks insert transactions in the new store; trackWorkspaceTransaction is added to the useCallback dependency array and called immediately after the insert transaction is created.

Sequence Diagram

sequenceDiagram
    participant UI as User Action
    participant OCA as useOptimisticCollectionActions
    participant WC as useWorkspaceCreates
    participant Store as workspaceTransactionsStore
    participant Sidebar as useDashboardSidebarData
    participant Layout as V2WorkspaceLayout
    participant Electric as Electric/TanStack DB

    UI->>WC: create workspace
    WC->>Electric: collections.v2Workspaces.insert(...)
    Electric-->>WC: "transaction {id, isPersisted, mutations:[insert]}"
    WC->>Store: track(workspaceId, transaction)
    Store->>Store: writeSnapshot("pending") [sync]
    Store->>Store: writeSnapshot("pending") [queueMicrotask]

    UI->>OCA: updateWorkspace / renameWorkspace
    OCA->>Electric: collections.v2Workspaces.update(...)
    Electric-->>OCA: "transaction {id, isPersisted, mutations:[update]}"
    OCA->>Store: track(workspaceId, transaction)

    Sidebar->>Store: useWorkspaceTransactionsStore(byWorkspaceId)
    Sidebar->>Sidebar: "pendingTransaction = byWorkspaceId[workspace.id]"
    Sidebar->>Sidebar: "isCreatePending = type === "insert""

    Electric-->>Store: isPersisted.promise resolves
    Store->>Store: writeSnapshot("completed") → clear(workspaceId)

    Electric-->>Layout: "workspace.$synced === true"
    Layout->>Store: clearWorkspaceTransaction(workspaceId) [insert only]
    Electric-->>Sidebar: "workspace.isSynced === true"
    Sidebar->>Store: clearWorkspaceTransaction(workspaceId) [insert only]
Loading
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts:61-62
**`queueMicrotask` can resurrect a superseded transaction snapshot**

Line 61 writes the snapshot synchronously, then line 62 re-queues the same write as a microtask. If `track()` is called twice for the same `workspaceId` within a single synchronous run (e.g. `updateWorkspace` + `renameWorkspace` both invoked from the same event handler, or a rapid chain where `useOptimisticCollectionActions` triggers two mutations), the sequence becomes:

1. Sync: tx1 snapshot written for `workspaceId`
2. Sync: tx2 snapshot written for `workspaceId`
3. Microtask A (tx1): overwrites `workspaceId` with tx1 data — stale state is now live
4. Microtask B (tx2): restores correct tx2 data

Between steps 3 and 4, any Zustand subscriber that re-renders (e.g. the sidebar computing `pendingTransaction`) sees the stale tx1 snapshot. For an insert tx1 followed by an update tx2, this would incorrectly show the "Creating workspace" spinner after the user had already successfully navigated to the workspace.

The second `writeSnapshot` on line 62 appears to serve no purpose — if there is a React-batching reason for it, a comment would help; otherwise removing it eliminates the race.

### Issue 2 of 3
apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts:64-77
**`"completed"` and `"failed"` states are immediately cleared and can never be observed**

`writeSnapshot("completed")` (line 67) and `get().clear(workspaceId)` (line 68) are two successive synchronous Zustand `set` calls — each one notifies subscribers before the next runs. A subscriber reading `pendingTransaction?.state` between these two calls will see `"completed"`, but any subscriber that only renders after both calls (i.e. the vast majority of real renders) will see `null` because the entry was cleared.

`WorkspaceTransactionState` exports `"completed"` and `"failed"` as first-class values, so future callers may write code that branches on them, only to find they are never reliably observable. Consider either removing these two values from the type (since clearing is the completion signal), or deferring `clear()` to the next tick so the settled state is visible for one render cycle.

### Issue 3 of 3
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx:62-71
**`ensureWorkspaceInSidebar` now fires before Electric confirms sync for pre-existing workspaces**

Previously the guard was `!isSynced` (`workspace.$synced !== true`), which deferred the sidebar-ensure call until the server had confirmed the row. With `isCreatePending` the guard is only active while an in-flight insert transaction is tracked in the Zustand store. For workspaces that already existed before this session (loaded from cache, `$synced` still false, no transaction in the store), `isCreatePending` is immediately `false`, so `ensureWorkspaceInSidebar` fires before the Electric sync round-trip completes.

This is likely benign if `ensureWorkspaceInSidebar` is idempotent, but the same logic applies to `useRemoteHostStatus` on line 73 — it now receives a potentially stale cached workspace object and begins polling the host before the row is confirmed as current. Worth verifying the host-status hook tolerates a briefly-unsynced workspace gracefully.

Reviews (1): Last reviewed commit: "Preserve workspace update transaction st..." | Re-trigger Greptile

Comment on lines +61 to +62
writeSnapshot(transaction.state);
queueMicrotask(() => writeSnapshot(transaction.state));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 queueMicrotask can resurrect a superseded transaction snapshot

Line 61 writes the snapshot synchronously, then line 62 re-queues the same write as a microtask. If track() is called twice for the same workspaceId within a single synchronous run (e.g. updateWorkspace + renameWorkspace both invoked from the same event handler, or a rapid chain where useOptimisticCollectionActions triggers two mutations), the sequence becomes:

  1. Sync: tx1 snapshot written for workspaceId
  2. Sync: tx2 snapshot written for workspaceId
  3. Microtask A (tx1): overwrites workspaceId with tx1 data — stale state is now live
  4. Microtask B (tx2): restores correct tx2 data

Between steps 3 and 4, any Zustand subscriber that re-renders (e.g. the sidebar computing pendingTransaction) sees the stale tx1 snapshot. For an insert tx1 followed by an update tx2, this would incorrectly show the "Creating workspace" spinner after the user had already successfully navigated to the workspace.

The second writeSnapshot on line 62 appears to serve no purpose — if there is a React-batching reason for it, a comment would help; otherwise removing it eliminates the race.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts
Line: 61-62

Comment:
**`queueMicrotask` can resurrect a superseded transaction snapshot**

Line 61 writes the snapshot synchronously, then line 62 re-queues the same write as a microtask. If `track()` is called twice for the same `workspaceId` within a single synchronous run (e.g. `updateWorkspace` + `renameWorkspace` both invoked from the same event handler, or a rapid chain where `useOptimisticCollectionActions` triggers two mutations), the sequence becomes:

1. Sync: tx1 snapshot written for `workspaceId`
2. Sync: tx2 snapshot written for `workspaceId`
3. Microtask A (tx1): overwrites `workspaceId` with tx1 data — stale state is now live
4. Microtask B (tx2): restores correct tx2 data

Between steps 3 and 4, any Zustand subscriber that re-renders (e.g. the sidebar computing `pendingTransaction`) sees the stale tx1 snapshot. For an insert tx1 followed by an update tx2, this would incorrectly show the "Creating workspace" spinner after the user had already successfully navigated to the workspace.

The second `writeSnapshot` on line 62 appears to serve no purpose — if there is a React-batching reason for it, a comment would help; otherwise removing it eliminates the race.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +64 to +77
void transaction.isPersisted.promise.then(
() => {
if (get().byWorkspaceId[workspaceId]?.id === transaction.id) {
writeSnapshot("completed");
get().clear(workspaceId);
}
},
() => {
if (get().byWorkspaceId[workspaceId]?.id === transaction.id) {
writeSnapshot("failed");
get().clear(workspaceId);
}
},
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 "completed" and "failed" states are immediately cleared and can never be observed

writeSnapshot("completed") (line 67) and get().clear(workspaceId) (line 68) are two successive synchronous Zustand set calls — each one notifies subscribers before the next runs. A subscriber reading pendingTransaction?.state between these two calls will see "completed", but any subscriber that only renders after both calls (i.e. the vast majority of real renders) will see null because the entry was cleared.

WorkspaceTransactionState exports "completed" and "failed" as first-class values, so future callers may write code that branches on them, only to find they are never reliably observable. Consider either removing these two values from the type (since clearing is the completion signal), or deferring clear() to the next tick so the settled state is visible for one render cycle.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/stores/workspace-creates/workspaceTransactions.ts
Line: 64-77

Comment:
**`"completed"` and `"failed"` states are immediately cleared and can never be observed**

`writeSnapshot("completed")` (line 67) and `get().clear(workspaceId)` (line 68) are two successive synchronous Zustand `set` calls — each one notifies subscribers before the next runs. A subscriber reading `pendingTransaction?.state` between these two calls will see `"completed"`, but any subscriber that only renders after both calls (i.e. the vast majority of real renders) will see `null` because the entry was cleared.

`WorkspaceTransactionState` exports `"completed"` and `"failed"` as first-class values, so future callers may write code that branches on them, only to find they are never reliably observable. Consider either removing these two values from the type (since clearing is the completion signal), or deferring `clear()` to the next tick so the settled state is visible for one render cycle.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +62 to +71
useEffect(() => {
if (
!workspace ||
!isSynced ||
isCreatePending ||
lastEnsuredWorkspaceIdRef.current === workspace.id
)
return;
lastEnsuredWorkspaceIdRef.current = workspace.id;
ensureWorkspaceInSidebar(workspace.id, workspace.projectId);
}, [ensureWorkspaceInSidebar, workspace, isSynced]);
}, [ensureWorkspaceInSidebar, workspace, isCreatePending]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 ensureWorkspaceInSidebar now fires before Electric confirms sync for pre-existing workspaces

Previously the guard was !isSynced (workspace.$synced !== true), which deferred the sidebar-ensure call until the server had confirmed the row. With isCreatePending the guard is only active while an in-flight insert transaction is tracked in the Zustand store. For workspaces that already existed before this session (loaded from cache, $synced still false, no transaction in the store), isCreatePending is immediately false, so ensureWorkspaceInSidebar fires before the Electric sync round-trip completes.

This is likely benign if ensureWorkspaceInSidebar is idempotent, but the same logic applies to useRemoteHostStatus on line 73 — it now receives a potentially stale cached workspace object and begins polling the host before the row is confirmed as current. Worth verifying the host-status hook tolerates a briefly-unsynced workspace gracefully.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx
Line: 62-71

Comment:
**`ensureWorkspaceInSidebar` now fires before Electric confirms sync for pre-existing workspaces**

Previously the guard was `!isSynced` (`workspace.$synced !== true`), which deferred the sidebar-ensure call until the server had confirmed the row. With `isCreatePending` the guard is only active while an in-flight insert transaction is tracked in the Zustand store. For workspaces that already existed before this session (loaded from cache, `$synced` still false, no transaction in the store), `isCreatePending` is immediately `false`, so `ensureWorkspaceInSidebar` fires before the Electric sync round-trip completes.

This is likely benign if `ensureWorkspaceInSidebar` is idempotent, but the same logic applies to `useRemoteHostStatus` on line 73 — it now receives a potentially stale cached workspace object and begins polling the host before the row is confirmed as current. Worth verifying the host-status hook tolerates a briefly-unsynced workspace gracefully.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 12 files

Re-trigger cubic

@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 19, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx:56">
P2: The new `canUseWorkspace` condition can lock valid workspaces behind a blank state when `$synced` is false but no in-memory transaction exists (for example after transaction settle or app reload). Gate on create-pending instead of requiring an `update` transaction.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

const isSynced = workspace?.$synced === true;
const canUseWorkspace =
workspace !== null &&
(workspace.$synced === true || pendingTransaction?.type === "update");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The new canUseWorkspace condition can lock valid workspaces behind a blank state when $synced is false but no in-memory transaction exists (for example after transaction settle or app reload). Gate on create-pending instead of requiring an update transaction.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx, line 56:

<comment>The new `canUseWorkspace` condition can lock valid workspaces behind a blank state when `$synced` is false but no in-memory transaction exists (for example after transaction settle or app reload). Gate on create-pending instead of requiring an `update` transaction.</comment>

<file context>
@@ -51,6 +51,9 @@ function V2WorkspaceLayout() {
 	const failedEntry = failedEntries?.[0] ?? null;
+	const canUseWorkspace =
+		workspace !== null &&
+		(workspace.$synced === true || pendingTransaction?.type === "update");
 
 	useEffect(() => {
</file context>
Suggested change
(workspace.$synced === true || pendingTransaction?.type === "update");
pendingTransaction?.type !== "insert";

@saddlepaddle saddlepaddle merged commit 778131d into main May 20, 2026
10 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

sazabi Bot pushed a commit that referenced this pull request May 20, 2026
* Track workspace transaction state

* Preserve workspace update transaction state

* Address workspace transaction review feedback
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request May 25, 2026
* Track workspace transaction state

* Preserve workspace update transaction state

* Address workspace transaction review feedback
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.

1 participant