Skip to content

feat(actions): store Global Actions in gxserver - #79

Merged
maddada merged 3 commits into
maddada:mainfrom
banozz0:feat/global-actions-store
Aug 2, 2026
Merged

feat(actions): store Global Actions in gxserver#79
maddada merged 3 commits into
maddada:mainfrom
banozz0:feat/global-actions-store

Conversation

@banozz0

@banozz0 banozz0 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

First of two PRs for the Global Actions feature you specced. This one is the daemon and contract layer only — nothing is user-visible until the follow-up adds the tab strip. Splitting it so the storage shape gets reviewed before the GPUI work depends on it.

Why a new table

Global Actions apply to every project, so they can't live in projects.customCommandsJson the way Project Actions do. This adds a daemon-owned global_sidebar_commands table (migration 0018), matching your app_user_data / automations / stashed_prompts precedent — so mobile, web and every desktop build read one list instead of mirroring a per-project column.

Per your note: "global actions should be stored in gxserver so they're available for mobile/web/macos/windows/etc."

Notable design points

  • No defaults, so no tombstones. dev/build/test/setup stay project-scoped, so every global action is user-created. That drops the whole default-resurrection and deletedDefaultCommandIds branch — the stored rows are the entire list.
  • read_sidebar_hud stays pure. globalCommands is attached by the server afterwards, the same pattern already used for commandsByProject, so the projection over project rows is untouched.
  • sidebar_command_scope assumed exactly one owner project. That's the assumption that had to give: SidebarHudSettingsMutation grows one optional field, and a global write schedules no projectUpdated delta because it touches no project row.
  • One validator for both lists. Global and Project saves take identical payloads and differ only in ownership, so they share a parser. Splitting it would let the two lists drift into accepting different action shapes.
  • Reorder keeps unlisted actions. A client reordering a stale list can't silently drop an action it hadn't loaded yet.

Verification

  • cargo check clean; cargo test --lib 655 passed
  • bun run typecheck clean; bun test 1279 passed
  • Driven end to end against a real daemon on an isolated HOME: create with zero projects open, reorder (full and partial), edit-keeps-position, delete, and persistence across restart

This commit is verified to build and test green on its own, so it's mergeable independently of the follow-up.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for global sidebar commands alongside project-specific commands.
    • Global commands can be saved, deleted, and reordered.
    • Sidebar HUD responses now include global commands in their stored order.
    • Global commands remain separate from project default actions.
    • Added validation and normalization for global command definitions.
  • Tests

    • Added coverage for empty global actions, ordering, normalization, and exclusion of project defaults.

Global Actions apply to every project instead of one, so they cannot live in
projects.customCommandsJson the way Project Actions do. Add a daemon-owned
global_sidebar_commands table (migration 0018) so mobile, web, and every
desktop build read one list rather than mirroring a per-project column.

The four default actions (dev/build/test/setup) stay project-scoped, so every
global action is user-created. That removes the whole default-resurrection and
tombstone branch: the stored rows are the entire list.

readSidebarHud attaches globalCommands after the fact, the same way it already
handles commandsByProject, so read_sidebar_hud stays a pure projection of
project rows. mutateSidebarHudSettings gains a globalCommand target;
SidebarHudSettingsMutation was project-only, so it grows one optional field and
a global write schedules no projectUpdated delta because it touches no project
row.

Project and Global saves validate through one shared path — the payloads are
identical and only ownership differs, so splitting the validation would let the
two lists drift into accepting different action shapes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 055ee107-c5ce-4e51-8a60-46fc47933346

📥 Commits

Reviewing files that changed from the base of the PR and between f6653d1 and 8115123.

📒 Files selected for processing (6)
  • gxserver-rs/src/domain.rs
  • gxserver-rs/src/server.rs
  • gxserver-rs/src/sidebar_hud.rs
  • shared/gxserver-protocol.ts
  • shared/sidebar-commands.test.ts
  • shared/sidebar-commands.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • shared/sidebar-commands.test.ts
  • shared/gxserver-protocol.ts
  • shared/sidebar-commands.ts
  • gxserver-rs/src/server.rs
  • gxserver-rs/src/domain.rs
  • gxserver-rs/src/sidebar_hud.rs

📝 Walkthrough

Walkthrough

This change adds daemon-owned global sidebar commands. It adds SQLite persistence, CRUD and ordering operations, HUD mutation handling, protocol support, global command projection, and tests for empty, filtered, and ordered command lists.

Changes

Global sidebar commands

Layer / File(s) Summary
Global command storage schema
gxserver-rs/src/constants.rs, gxserver-rs/src/storage.rs
Adds migration 0018_global_sidebar_commands, the global_sidebar_commands table, its ordering index, and updated schema assertions.
Repository CRUD and ordering
gxserver-rs/src/domain.rs
Adds listing, saving, deletion, and deterministic transactional reordering for stored global commands.
Global command mutation handling
gxserver-rs/src/sidebar_hud.rs
Adds global save, delete, and order mutations. Shared validation builds command definitions for both project and global commands.
HUD protocol and command projection
shared/gxserver-protocol.ts, gxserver-rs/src/server.rs, shared/sidebar-commands.ts, shared/sidebar-commands.test.ts
Exposes globalCommands, processes global mutations, returns persisted ordering, and projects stored global commands without project defaults.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant readSidebarHud
  participant DomainRepository
  participant SQLite
  Client->>readSidebarHud: Submit globalCommand mutation
  readSidebarHud->>DomainRepository: Save, delete, or order command
  DomainRepository->>SQLite: Persist global command state
  SQLite-->>DomainRepository: Return stored state
  DomainRepository-->>readSidebarHud: Return refreshed command data
  readSidebarHud-->>Client: Return globalCommands and persisted order
Loading

Possibly related PRs

  • maddada/Ghostex#75: Shares sidebar command handling across the HUD server, protocol, and command projection modules.
  • maddada/Ghostex#80: Overlaps in global-command persistence, HUD mutations, protocol changes, and shared command rendering.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: storing Global Actions in gxserver.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gxserver-rs/src/domain.rs`:
- Around line 521-540: Update list_global_sidebar_commands so serde_json parsing
failures for definitionJson are propagated as DomainResult errors, matching
list_stashed_prompts and similar row-based list methods. Replace the silent
filter_map/.ok() behavior with error-aware collection, preserving the existing
ordering and successful deserialization behavior.
- Around line 594-642: Wrap the per-command UPDATE loop in
order_global_sidebar_commands with a BEGIN IMMEDIATE TRANSACTION and commit only
after every write succeeds; on any failure, roll back and return the error.
Follow the existing transaction pattern from update_session_order, preserving
the current ordering logic and error propagation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a5235d30-a636-4c63-8d18-5fe5a78c1975

📥 Commits

Reviewing files that changed from the base of the PR and between 5640cdb and f6653d1.

📒 Files selected for processing (8)
  • gxserver-rs/src/constants.rs
  • gxserver-rs/src/domain.rs
  • gxserver-rs/src/server.rs
  • gxserver-rs/src/sidebar_hud.rs
  • gxserver-rs/src/storage.rs
  • shared/gxserver-protocol.ts
  • shared/sidebar-commands.test.ts
  • shared/sidebar-commands.ts

Comment thread gxserver-rs/src/domain.rs
Comment thread gxserver-rs/src/domain.rs
banozz0 and others added 2 commits August 2, 2026 08:48
Reorder issued one UPDATE per row with no surrounding transaction, so a failure
partway left some rows on the new sortOrder and others on the old — an
interleaved list that the server would then echo back as the confirmed order.
Wrap it in BEGIN IMMEDIATE / COMMIT / ROLLBACK, mirroring update_session_order,
which guards the identical case. Taking the writer reservation before the read
also closes the read-then-write race against a concurrent save or delete, whose
row would otherwise keep a stale sortOrder.

Deduplicate the requested ids as well: a repeated id consumed two index
positions, because the append guard skipped the duplicate while the write loop
still assigned it twice.

Reject the reserved built-in ids (dev/build/test/setup) for global actions. The
read projection recomputes isDefault from the id, so a stored global action
called "dev" came back marked as a default however it was written. Rejecting at
save is what makes the invariant hold on both paths, and it keeps the global and
project id spaces from colliding on the reserved names.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
maddada#75 landed the showOnProjectRow surface, which touches the same HUD contract.
Both sides are additive, so the resolution keeps each:

- readSidebarHud and mutateSidebarHudSettings call maddada#75's new
  apply_commands_by_project_if_requested helper and still attach globalCommands.
- The shared save validator carries show_on_project_row, so global and project
  saves keep taking the identical action definition.
- The mutation target union widens to "command" | "globalCommand" alongside
  maddada#75's showOnProjectRow field.

Also updates two normalizeStoredSidebarCommands expectations that maddada#75 left
asserting the pre-showOnProjectRow shape; they fail on main as merged,
independently of this branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@maddada
maddada merged commit 5354e72 into maddada:main Aug 2, 2026
1 check passed
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