P2 slice 8: the viewer's menu, setup, no confinement (D-32)

No Landlock, no seccomp, no helper: isolation is "same_user
(advisory)". The lease socket keeps two intents (close, format-upgrade
consent). The viewer holds the books open while it runs and gains a
Books menu: New books, Back up now, Restore (preview, then confirm),
Close, Connect Claude Code / Codex. New commands `wanderbooks books
back-up` and `wanderbooks connect claude|codex`. The scaffold
(`new`/`init` and its templates) is gone; install.sh needs no sudo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-20 11:14:22 -06:00
1 parent 019d8d76a3
commit 3cf359a0cd
28 files changed
+1976 -1931

No files matched your search

+2 -11
View File
@@ -50,7 +50,7 @@
use crate::knobs::{FLAG, Knobs};
use crate::lease::{HostMsg, Kind, Reason};
use crate::opener::{Opener, Starter};
use crate::opener::Opener;
use serde_json::{Value, json};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
@@ -1241,15 +1241,7 @@ pub fn run(
let book = ledger_store::root::BookId::parse(&book)
.map_err(|e| e.to_string())?
.to_string();
// The helper first, before any thread (helper.rs INVARIANT 4).
let helper = Arc::new(crate::helper::Client::spawn(root.as_deref(), &knobs)?);
let opener = Opener::new(
root.as_deref(),
knobs,
Starter::Helper(helper.clone()),
Kind::Bridge,
Some(book.clone()),
)?;
let opener = Opener::new(root.as_deref(), knobs, Kind::Bridge, Some(book.clone()))?;
// Kept for the whole session: the client reaches the socket by it.
let socket =
ledger_store::root::SocketPath::new(opener.run_dir(), ledger_mcp::local::MCP_SOCKET)
@@ -1337,7 +1329,6 @@ pub fn run(
Ok::<(), String>(())
});
rt.shutdown_timeout(Duration::from_secs(1));
drop(helper);
result.map_err(Into::into)
}