refactor: move presentation shells to _reference/, shrink workspace
Move nuncio-tui, nuncio-gui (+src-tauri, ui), and nuncio-mcp out of the Cargo workspace into _reference/ (git renames; history preserved), retained for the Phase 5 native client-repo extraction. Remove the unused nuncio-mcp dev-dep from nunciod and rework daemon_e2e_test to drive the real nuncio-cli HeadlessRunner (more coverage, no archived-shell dependency). Workspace is now engine + daemon + reference CLI (8 members); build/clippy/tests green. Refs #145
This commit is contained in:
60 files changed
+154
-3495
No files matched your search
Generated
+34
-3457
File diff suppressed because it is too large.
Load diff
@@ -5,11 +5,7 @@ members = [
|
||||
"crates/nuncio-mail",
|
||||
"crates/nuncio-cal",
|
||||
"crates/nuncio-store",
|
||||
"crates/nuncio-tui",
|
||||
"crates/nuncio-gui",
|
||||
"crates/nuncio-gui/src-tauri",
|
||||
"crates/nuncio-cli",
|
||||
"crates/nuncio-mcp",
|
||||
"crates/nunciod",
|
||||
"crates/nuncio-filter",
|
||||
"crates/nuncio-contacts",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# `_reference/` — archived pre-gRPC presentation shells
|
||||
|
||||
This directory holds three presentation shells that were removed from the
|
||||
Cargo workspace (backlog **0.D.2**, GH-145) as part of shrinking the
|
||||
workspace to just the engine, the daemon, and the reference CLI:
|
||||
|
||||
- `nuncio-tui` — the Ratatui terminal UI shell
|
||||
- `nuncio-gui` — the Rust GUI core plus its `src-tauri` Tauri desktop shell
|
||||
and its `ui/` React/Vite frontend
|
||||
- `nuncio-mcp` — the MCP (Model Context Protocol) server shell for LLM tool
|
||||
access
|
||||
|
||||
They were built directly against the in-process `nuncio-core`/`nuncio-mail`/
|
||||
`nuncio-cal`/`nuncio-store`/`nuncio-filter`/`nuncio-contacts` library APIs,
|
||||
from the pre-gRPC phase of the project. Per the target architecture in
|
||||
[`docs/ROADMAP.md`](../docs/ROADMAP.md), `nunciod` is moving to publish a
|
||||
versioned gRPC API over loopback, and every presentation shell other than
|
||||
the in-repo `nuncio-cli` reference client is planned to live in its own
|
||||
separate native client repository (**Phase 5 — Client projects**):
|
||||
`nuncio-tui`, `nuncio-gui-macos`, `nuncio-gui-windows`, `nuncio-mcp`, etc.
|
||||
|
||||
**This code is retained intact, not deleted**, so it can be mined for UI/UX
|
||||
ideas, keybindings, view layout, and MCP tool-surface design when those
|
||||
Phase 5 client repos are built against the new gRPC API. It is **not**
|
||||
built, checked, or tested by the root Cargo workspace — none of these
|
||||
directories are members of the workspace `Cargo.toml`, so
|
||||
`cargo build --workspace`, `cargo check-all`, and `cargo test --workspace`
|
||||
never touch them.
|
||||
|
||||
Each crate's internal `path = "../..."` dependencies on the engine crates
|
||||
have been updated to point at `../../crates/<name>` (e.g.
|
||||
`_reference/nuncio-tui/Cargo.toml` now points at `../../crates/nuncio-core`)
|
||||
so the crate sources still resolve correctly relative to their new location.
|
||||
They are **not guaranteed to build standalone** as-is: they still declare
|
||||
`*.workspace = true` fields (`version`, `edition`, `lints`, and workspace
|
||||
`[dependencies]` aliases) that only resolve inside a Cargo workspace, and
|
||||
they are not their own workspace root. Restoring a standalone build (for
|
||||
mining or resurrection) will require either vendoring those workspace
|
||||
values directly into each `Cargo.toml`, or giving `_reference/` its own
|
||||
`[workspace]` root.
|
||||
@@ -10,10 +10,10 @@ repository.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nuncio-core = { path = "../nuncio-core" }
|
||||
nuncio-mail = { path = "../nuncio-mail" }
|
||||
nuncio-cal = { path = "../nuncio-cal" }
|
||||
nuncio-store = { path = "../nuncio-store" }
|
||||
nuncio-core = { path = "../../crates/nuncio-core" }
|
||||
nuncio-mail = { path = "../../crates/nuncio-mail" }
|
||||
nuncio-cal = { path = "../../crates/nuncio-cal" }
|
||||
nuncio-store = { path = "../../crates/nuncio-store" }
|
||||
tokio.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
@@ -10,7 +10,7 @@ repository.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nuncio-core = { path = "../../nuncio-core" }
|
||||
nuncio-core = { path = "../../../crates/nuncio-core" }
|
||||
nuncio-gui = { path = ".." }
|
||||
tauri = { version = "2.0", features = [] }
|
||||
tauri-plugin-updater = "2.0"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -10,12 +10,12 @@ repository.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nuncio-core = { path = "../nuncio-core" }
|
||||
nuncio-mail = { path = "../nuncio-mail" }
|
||||
nuncio-cal = { path = "../nuncio-cal" }
|
||||
nuncio-store = { path = "../nuncio-store" }
|
||||
nuncio-filter = { path = "../nuncio-filter" }
|
||||
nuncio-contacts = { path = "../nuncio-contacts" }
|
||||
nuncio-core = { path = "../../crates/nuncio-core" }
|
||||
nuncio-mail = { path = "../../crates/nuncio-mail" }
|
||||
nuncio-cal = { path = "../../crates/nuncio-cal" }
|
||||
nuncio-store = { path = "../../crates/nuncio-store" }
|
||||
nuncio-filter = { path = "../../crates/nuncio-filter" }
|
||||
nuncio-contacts = { path = "../../crates/nuncio-contacts" }
|
||||
|
||||
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -10,11 +10,11 @@ repository.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nuncio-core = { path = "../nuncio-core" }
|
||||
nuncio-mail = { path = "../nuncio-mail" }
|
||||
nuncio-cal = { path = "../nuncio-cal" }
|
||||
nuncio-store = { path = "../nuncio-store" }
|
||||
nuncio-filter = { path = "../nuncio-filter" }
|
||||
nuncio-core = { path = "../../crates/nuncio-core" }
|
||||
nuncio-mail = { path = "../../crates/nuncio-mail" }
|
||||
nuncio-cal = { path = "../../crates/nuncio-cal" }
|
||||
nuncio-store = { path = "../../crates/nuncio-store" }
|
||||
nuncio-filter = { path = "../../crates/nuncio-filter" }
|
||||
|
||||
tokio.workspace = true
|
||||
ratatui.workspace = true
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -28,4 +28,3 @@ tempfile.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
nuncio-cli = { path = "../nuncio-cli" }
|
||||
nuncio-mcp = { path = "../nuncio-mcp" }
|
||||
@@ -1,11 +1,29 @@
|
||||
//! End-to-End multi-interface daemon integration test suite.
|
||||
//! End-to-End multi-shell daemon integration test suite.
|
||||
//!
|
||||
//! Exercises the `nunciod` daemon end-to-end over the real IPC socket using
|
||||
//! `nuncio-core`'s `IpcClient`/`IpcDaemonServer`, and independently exercises
|
||||
//! the in-workspace `nuncio-cli` presentation shell (`HeadlessRunner`) to
|
||||
//! confirm a real reference client shell continues to function alongside
|
||||
//! the daemon. This suite intentionally has no dependency on the archived
|
||||
//! presentation shells that were moved to `_reference/` (nuncio-tui,
|
||||
//! nuncio-gui, nuncio-mcp) as part of shrinking the workspace to the
|
||||
//! engine + daemon + reference CLI (backlog 0.D.2 / GH-145).
|
||||
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
||||
|
||||
use nuncio_cli::{Commands, HeadlessRunner, MailSubcommand, SystemSubcommand};
|
||||
use nuncio_core::ipc::{IpcClient, IpcDaemonServer};
|
||||
use nuncio_core::{CoreCommand, EventBus};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Boots a real `nunciod` `IpcDaemonServer` and drives it concurrently from
|
||||
/// three independent `IpcClient` socket connections (standing in for any
|
||||
/// number of simultaneous thin presentation shells talking JSON-RPC over
|
||||
/// TCP), then separately drives the real `nuncio-cli` `HeadlessRunner`
|
||||
/// reference shell to confirm it still executes full noun+verb commands
|
||||
/// correctly. This preserves the daemon-boot + real-client-round-trip
|
||||
/// coverage the previous multi-shell test provided, without requiring the
|
||||
/// archived `nuncio-mcp` crate.
|
||||
#[tokio::test]
|
||||
async fn e2e_multi_shell_daemon_concurrency_test() {
|
||||
let event_bus = Arc::new(EventBus::new());
|
||||
@@ -16,16 +34,17 @@ async fn e2e_multi_shell_daemon_concurrency_test() {
|
||||
let _ = server.run_server().await;
|
||||
});
|
||||
|
||||
// Simulate 3 concurrent shells connecting to nunciod daemon
|
||||
let client_cli = IpcClient::new(addr);
|
||||
let client_tui = IpcClient::new(addr);
|
||||
let client_mcp = IpcClient::new(addr);
|
||||
// Simulate 3 concurrent thin-shell connections to the nunciod daemon
|
||||
// over the real IPC socket.
|
||||
let client_a = IpcClient::new(addr);
|
||||
let client_b = IpcClient::new(addr);
|
||||
let client_c = IpcClient::new(addr);
|
||||
|
||||
// Give server time to bind TCP socket
|
||||
// Give server time to bind TCP socket.
|
||||
let mut ping_res = false;
|
||||
for _ in 0..15 {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
||||
if let Ok(res) = client_cli.ping().await {
|
||||
if let Ok(res) = client_a.ping().await {
|
||||
ping_res = res;
|
||||
if ping_res {
|
||||
break;
|
||||
@@ -33,27 +52,55 @@ async fn e2e_multi_shell_daemon_concurrency_test() {
|
||||
}
|
||||
}
|
||||
assert!(ping_res);
|
||||
assert!(client_tui.ping().await.expect("tui ping"));
|
||||
assert!(client_mcp.ping().await.expect("mcp ping"));
|
||||
assert!(client_b.ping().await.expect("shell b ping"));
|
||||
assert!(client_c.ping().await.expect("shell c ping"));
|
||||
|
||||
// 2. MCP shell issues sync command
|
||||
let sync_res = client_mcp
|
||||
// 2. Shell B issues a sync command over its own concurrent connection.
|
||||
let sync_res = client_b
|
||||
.send_command(CoreCommand::SyncAll)
|
||||
.await
|
||||
.expect("mcp sync command");
|
||||
.expect("shell b sync command");
|
||||
assert_eq!(sync_res["status"], "dispatched");
|
||||
|
||||
// 3. CLI shell fetches state and verifies status is Syncing
|
||||
let state_res = client_cli.get_state().await.expect("cli get state");
|
||||
// 3. Shell A fetches state and verifies status is Syncing.
|
||||
let state_res = client_a.get_state().await.expect("shell a get state");
|
||||
assert_eq!(state_res["status"].as_str().unwrap(), "Syncing");
|
||||
|
||||
// 4. TUI shell marks message read
|
||||
let mark_res = client_tui
|
||||
// 4. Shell C marks a message read over its own concurrent connection.
|
||||
let mark_res = client_c
|
||||
.send_command(CoreCommand::MarkRead {
|
||||
message_id: "msg-1".to_string(),
|
||||
read: true,
|
||||
})
|
||||
.await
|
||||
.expect("tui mark read");
|
||||
.expect("shell c mark read");
|
||||
assert_eq!(mark_res["status"], "marked");
|
||||
|
||||
// 5. Independently, drive the real in-workspace `nuncio-cli` reference
|
||||
// shell (its own ephemeral local engine, per its documented headless
|
||||
// design) to confirm a genuine presentation-shell client still
|
||||
// round-trips full commands correctly end-to-end.
|
||||
let cli_runner = HeadlessRunner::ephemeral()
|
||||
.await
|
||||
.expect("cli headless runner initializes");
|
||||
|
||||
let cli_sync = cli_runner
|
||||
.execute_command(
|
||||
&Commands::Mail {
|
||||
action: MailSubcommand::Sync,
|
||||
},
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
assert!(cli_sync.contains(r#""status":"sync_started""#));
|
||||
|
||||
let cli_status = cli_runner
|
||||
.execute_command(
|
||||
&Commands::System {
|
||||
action: SystemSubcommand::Status,
|
||||
},
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
assert!(cli_status.contains(r#""engine_status":"Syncing""#));
|
||||
}
|
||||
Reference in new issue
Block a user