Add the single domain-event path used to keep desktop, CLI, MCP, TUI, server, and future remote clients synchronized after mutations.
Current state
specs/events.allium defines entity and settings events.
db_notifications exists for CLI-to-desktop synchronization, but there is no in-process event bus.
Desktop state is refreshed through feature-specific message paths.
CLI, MCP, server, and TUI are not implemented.
Required behavior
Define the minimal typed events from specs/events.allium for entity create/update/delete and settings changes, including project scope and identifiers needed by clients.
Publish events from the shared mutation boundary so desktop and future clients observe the same result regardless of caller.
Provide subscribe/unsubscribe behavior and deterministic delivery to active clients.
Refresh affected desktop state from events without feeding the same mutation back into the engine or duplicating notifications.
Preserve the server-selected UI language for server-rendered clients.
Integrate db_notifications as the process boundary for CLI writes: CLI-originated events are persisted, consumed once by the desktop watcher, marked seen, and pruned under cli_sync.allium rules.
Implementation notes
Keep one event enum and one bus implementation. Do not build a broker or event-sourcing layer.
Put emission in shared engine/service mutation paths, not separately in every UI.
Avoid holding database transactions or UI locks while notifying subscribers.
Follow red/green TDD and use specs/events.allium plus specs/cli_sync.allium as normative behavior.
Acceptance criteria
Representative post, media, tag, template, script, project, and settings mutations emit exactly one appropriate event.
Multiple subscribers receive events in order; unsubscribe stops delivery.
A desktop-originated write does not re-enter through db_notifications.
CLI notification consumption, seen marking, and processed/unprocessed pruning are tested.
Existing desktop refresh behavior continues to work through the shared path.
cargo fmt --all -- --check, cargo build --workspace, and cargo test --workspace pass.
## Goal
Add the single domain-event path used to keep desktop, CLI, MCP, TUI, server, and future remote clients synchronized after mutations.
## Current state
- specs/events.allium defines entity and settings events.
- db_notifications exists for CLI-to-desktop synchronization, but there is no in-process event bus.
- Desktop state is refreshed through feature-specific message paths.
- CLI, MCP, server, and TUI are not implemented.
## Required behavior
- Define the minimal typed events from specs/events.allium for entity create/update/delete and settings changes, including project scope and identifiers needed by clients.
- Publish events from the shared mutation boundary so desktop and future clients observe the same result regardless of caller.
- Provide subscribe/unsubscribe behavior and deterministic delivery to active clients.
- Refresh affected desktop state from events without feeding the same mutation back into the engine or duplicating notifications.
- Preserve the server-selected UI language for server-rendered clients.
- Integrate db_notifications as the process boundary for CLI writes: CLI-originated events are persisted, consumed once by the desktop watcher, marked seen, and pruned under cli_sync.allium rules.
## Implementation notes
- Keep one event enum and one bus implementation. Do not build a broker or event-sourcing layer.
- Put emission in shared engine/service mutation paths, not separately in every UI.
- Avoid holding database transactions or UI locks while notifying subscribers.
- Follow red/green TDD and use specs/events.allium plus specs/cli_sync.allium as normative behavior.
## Acceptance criteria
- Representative post, media, tag, template, script, project, and settings mutations emit exactly one appropriate event.
- Multiple subscribers receive events in order; unsubscribe stops delivery.
- A desktop-originated write does not re-enter through db_notifications.
- CLI notification consumption, seen marking, and processed/unprocessed pruning are tested.
- Existing desktop refresh behavior continues to work through the shared path.
- cargo fmt --all -- --check, cargo build --workspace, and cargo test --workspace pass.
Added one typed, project-scoped DomainEvent enum and deterministic in-process EventBus with ordered multi-subscriber delivery and explicit unsubscribe/drop behavior.
Emitted create/update/publish/delete events from shared post, media, tag, template, script, project, search-setting, AI-setting, and UI-setting mutation boundaries after successful work and outside database savepoints.
Added the Diesel-generated project_id migration and notification queries, plus CLI event capture/persistence, atomic consume-once/seen marking, deterministic ordering, legacy-row scope recovery, and 1-hour processed/24-hour unprocessed pruning.
Added a 100 ms desktop watcher that consumes CLI rows and uses the same event path to refresh project-scoped lists/editors, close deleted tabs, preserve dirty buffers, and avoid write-back or duplicate toasts/notification rows.
Persisted ui.language as the server-selected global setting; startup uses it before menu creation and events relocalize active clients without rewriting the setting.
Updated events.allium, cli_sync.allium, README, RUST_PLAN_CORE.md, and RUST_PLAN_EXTENSION.md.
Neutral review:
Compared every broadcast family and desktop handler with bDS2, and checked behavior against events.allium and cli_sync.allium.
The review found and fixed deterministic unsubscribe cutover and compatibility for pre-migration notification rows lacking project scope.
No remaining issue, bDS2, or Allium gaps found.
Verification:
allium check/analyse for both specs: no findings (informational unused-field notices only)
cargo test --workspace: all enabled tests passed; 2 existing keychain tests remained explicitly ignored
Dedicated coverage includes exact event cardinality across all required mutation families, publish/delete mapping, subscriber order/unsubscribe, desktop no-op notifier, CLI capture/consume/seen/prune, legacy migration compatibility, desktop refresh/delete behavior, dirty-buffer preservation, and shared locale behavior.
Implemented in a2abb90 and pushed to origin/main.
Implementation:
- Added one typed, project-scoped DomainEvent enum and deterministic in-process EventBus with ordered multi-subscriber delivery and explicit unsubscribe/drop behavior.
- Emitted create/update/publish/delete events from shared post, media, tag, template, script, project, search-setting, AI-setting, and UI-setting mutation boundaries after successful work and outside database savepoints.
- Added the Diesel-generated project_id migration and notification queries, plus CLI event capture/persistence, atomic consume-once/seen marking, deterministic ordering, legacy-row scope recovery, and 1-hour processed/24-hour unprocessed pruning.
- Added a 100 ms desktop watcher that consumes CLI rows and uses the same event path to refresh project-scoped lists/editors, close deleted tabs, preserve dirty buffers, and avoid write-back or duplicate toasts/notification rows.
- Persisted ui.language as the server-selected global setting; startup uses it before menu creation and events relocalize active clients without rewriting the setting.
- Updated events.allium, cli_sync.allium, README, RUST_PLAN_CORE.md, and RUST_PLAN_EXTENSION.md.
Neutral review:
- Compared every broadcast family and desktop handler with bDS2, and checked behavior against events.allium and cli_sync.allium.
- The review found and fixed deterministic unsubscribe cutover and compatibility for pre-migration notification rows lacking project scope.
- No remaining issue, bDS2, or Allium gaps found.
Verification:
- allium check/analyse for both specs: no findings (informational unused-field notices only)
- cargo fmt --all -- --check
- cargo build --workspace
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace: all enabled tests passed; 2 existing keychain tests remained explicitly ignored
- Dedicated coverage includes exact event cardinality across all required mutation families, publish/delete mapping, subscriber order/unsubscribe, desktop no-op notifier, CLI capture/consume/seen/prune, legacy migration compatibility, desktop refresh/delete behavior, dirty-buffer preservation, and shared locale behavior.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
Add the single domain-event path used to keep desktop, CLI, MCP, TUI, server, and future remote clients synchronized after mutations.
Current state
Required behavior
Implementation notes
Acceptance criteria
Implemented in
a2abb90and pushed to origin/main.Implementation:
Neutral review:
Verification: