Spike native shells and define local-first integrations
CI / rust (push) Successful in 1m40s

This commit is contained in:
2026-08-31 15:42:26 -07:00
parent a703b5a5ee
commit aaa1cb1fa9
28 changed files with 14809 additions and 14 deletions
+57 -6
View File
@@ -8,7 +8,8 @@ Lumbridge should be two cooperating Rust processes:
native desktop UI
| local authenticated IPC
Lumbridge session runtime
|-- PTYs and process trees
|-- local PTYs and process trees
|-- SSH/Tailscale transport to remote Lumbridge runtimes
|-- ACP clients and adapters
|-- repositories and worktrees
|-- usage/event ledger
@@ -30,13 +31,18 @@ messages should be real from the beginning.
- `lumbridge-harness`: manifests, launch profiles, hooks, PTY fallback adapters.
- `lumbridge-provider`: BYOK providers and provider-neutral usage records.
- `lumbridge-storage`: SQLite migrations, event log, snapshots, retention.
- `lumbridge-remote`: OpenSSH/Tailscale command construction, framed stdio,
handshake, reconnect, heartbeat, and remote-runtime discovery.
- `lumbridge-secrets`: Keychain/libsecret adapters and redaction.
- `lumbridge-git`: repositories, worktrees, diffs, status, conflict state.
- `lumbridge-buzz`: credential-free Buzz event/broker preparation and pane-share
safety gates; platform adapters own signing and transport.
- `lumbridge-ui`: native desktop state and rendering.
- `lumbridge`: installable application entry point.
Only `lumbridge-core` and the entry point exist in the scaffold. New crates are
added after their architecture spike passes.
The scaffold currently contains `lumbridge-core`, `lumbridge-storage`,
`lumbridge-buzz`, and the entry point. Larger runtime crates are added after
their architecture spikes pass.
## Terminal path
@@ -57,13 +63,46 @@ Do not lock the project to a webview or to Zed's private implementation details
before a measured spike. Compare:
1. GPUI for a Zed-like native model and excellent text-heavy interaction.
2. Iced/wgpu plus a dedicated terminal renderer for stable Rust portability.
3. Tauri only as a delivery-speed baseline, not the assumed winner.
2. Floem for an independent native Rust model with existing editor primitives.
The winner must render six busy panes smoothly, keep input latency low, support
IME/accessibility, package on macOS and both Linux targets, and avoid a license
or upstream-stability trap.
## Local-first and remote session path
SQLite is device-local. It stores workspace metadata, pane layouts, event and
usage history, remote routing profiles, and small snapshots. It never stores SSH
private keys, Tailscale credentials, provider API keys, or subscription tokens.
Secrets remain in the OS credential store or in the user's existing SSH agent.
A remote pane is not a local PTY wrapped around a long-lived `ssh` process. Its
durable owner is a per-user `lumbridge-runtime` on the destination:
```text
MacBook Lumbridge UI/runtime
|
| ssh host lumbridge remote connect --stdio
| or: tailscale ssh host lumbridge remote connect --stdio
v
remote per-user Lumbridge runtime -- Unix socket -- PTYs, agents, worktrees
|
`-- remote SQLite + chunked scrollback on that machine
```
The SSH child carries a versioned framed protocol over stdio. Normal OpenSSH
remains the default because it honors the user's config, agent, host keys,
ProxyJump, and Tailscale addresses. `tailscale ssh` is an explicit transport for
users who want Tailscale's SSH proxy and host-key path. Lumbridge does not
configure a tailnet, weaken ACLs, copy SSH keys, or require a listening TCP port.
The remote runtime assigns a stable session ID before acknowledging a launch.
On network loss the local pane becomes disconnected, the remote PTY continues,
and reconnect resumes from the last acknowledged output sequence. A second
authorized Lumbridge installation can attach to the same remote session after
the remote runtime arbitrates input ownership. Collaborative simultaneous input
is not part of the first release.
## Harness integration
Each harness is described by a versioned manifest: executable discovery, launch
@@ -88,6 +127,14 @@ usually expose token counts but cost still depends on cached tokens, reasoning,
tool calls, and current pricing. Adapters normalize facts without erasing their
source or uncertainty.
## Buzz collaboration
Buzz channel messages, replies, agents, and attachments use the upstream Rust
SDK's signed Nostr semantics. SQLite stores a public identity and opaque
credential-store handle, never the private identity key. Pane images cross the
network only after local capture, redaction preview, explicit destination, and
confirmation. See `BUZZ_INTEGRATION.md` for the contract and test plan.
## Persistence
SQLite in WAL mode stores metadata, commands/events, normalized usage, and small
@@ -95,6 +142,11 @@ snapshots. Large scrollback chunks and binary attachments use content-addressed
files. A write-ahead event is committed before an external mutation is reported
as accepted. Startup replays incomplete operations and reconciles live children.
Default data roots are `~/Library/Application Support/ai.karti.lumbridge/` on
macOS and `${XDG_DATA_HOME:-~/.local/share}/lumbridge/` on Linux. Backups and
exports are explicit; Lumbridge does not synchronize the database through a
hidden hosted account.
## Security
- macOS secrets: Keychain; Linux secrets: Secret Service/libsecret, with an
@@ -113,4 +165,3 @@ Shared contracts cover PTY, process tree, notifications, secret store, paths,
autostart, updater, and packaging. macOS uses `forkpty`/process groups and native
Keychain. Ubuntu and Omarchy use Unix PTYs, cgroups/systemd scopes when available,
and Secret Service. Omarchy is treated as Arch Linux, not as a separate kernel.
+84
View File
@@ -0,0 +1,84 @@
# Buzz integration
## Product boundary
Buzz is Lumbridge's first-class collaboration surface, not its control plane.
Lumbridge remains useful offline, owns its local workspace state, and never
requires a Buzz account to open a terminal or run an agent.
The initial integration provides:
- connect an existing Buzz identity using an OS credential-store reference;
- bind one or more Buzz channels to a Lumbridge workspace;
- read and post channel messages and replies from a collaboration pane;
- surface Buzz agents attached to a bound channel without pretending they are
local processes;
- share an approved pane image to an explicitly selected channel.
## Protocol shape
The pinned upstream is Block's Apache-2.0 Buzz repository at commit
`cb3144999bebc4939cb15b2200b373281d493b52`. `buzz-sdk` constructs typed Nostr
events and broker actions but deliberately owns neither identity keys nor
network connections. Lumbridge follows that separation:
```text
Lumbridge collaboration pane
| typed local command
lumbridge-buzz
| Buzz SDK event/broker action
identity signer + Buzz transport adapter
| signed WebSocket / HTTPS upload
Buzz relay and attachment storage
```
The exact revision stays pinned until an audited upgrade. We use Buzz's signed
protocol and SDK types rather than a parallel webhook format.
## Identity and local data
SQLite stores the account label, relay URL, public key, and an opaque secret
store handle. The Nostr private key stays in macOS Keychain or Linux Secret
Service. It must never enter SQLite, command arguments, crash reports, pane
history, logs, or Git configuration.
An installed Buzz CLI identity may be imported only through an explicit user
flow that transfers it into the OS credential store. Lumbridge must not search
the filesystem for keys. Buzz's current NIP-AB device-pairing tooling is marked
for interoperability testing upstream, so it is not a production login promise.
## Pane-image sharing
Sharing is a user-visible state machine:
1. Capture the selected pane only, excluding application chrome by default.
2. Detect likely secrets and render a local preview with proposed redactions.
3. Let the user adjust redactions, caption, and destination channel.
4. Require confirmation of that exact preview and destination.
5. Encode PNG or WebP, hash it, upload with the authenticated Buzz attachment
flow, and receive a canonical URL.
6. Build a kind-9 Buzz message with Markdown plus an `imeta` tag, sign it using
the OS-held identity, and publish it.
7. Persist only the resulting event ID, attachment metadata, destination, and
local audit outcome. Never persist the unredacted capture.
Any change to the pixels, caption, or destination invalidates confirmation. A
failed upload or publish is retryable but never reported as sent.
## Agent integration
Buzz agents and Lumbridge harnesses are different entities. A Buzz agent may be
shown in the collaboration pane and may exchange messages through Buzz's broker
contract. A local or remote Lumbridge harness remains owned by the Lumbridge
runtime and communicates through ACP or a supervised PTY. Linking the two later
requires an explicit capability grant, visible identity, and revocation path.
## Test plan
- deterministic unit tests for channel IDs, content limits, media metadata, and
the review/confirmation gate;
- signature tests with generated fixture identities only;
- integration tests against a disposable local Buzz relay and attachment store;
- disconnect, duplicate-delivery, cursor-resume, and publish-retry tests;
- rendered tests proving destination and redactions remain visible at confirm;
- a real-account smoke test only in a manually enabled, non-CI test profile.
+29 -2
View File
@@ -21,6 +21,24 @@ The product should feel faster and calmer as concurrency rises.
5. Review file and Git changes by workspace or worktree.
6. Understand usage, rate-limit windows, burn rate, and likely exhaustion time.
7. Resume the entire workspace after the UI or machine restarts.
8. Work from a laptop while selected panes and agents run durably on a
user-owned machine reached through SSH or Tailscale.
9. Follow a project's Buzz channel and intentionally share a redacted pane image
without leaving the workspace.
## Local and remote workspaces
Every Lumbridge installation is useful on its own and owns its local settings,
history, usage observations, and workspace views. A pane can execute locally or
on a saved remote host. Remote hosts may be normal SSH destinations, entries in
the user's SSH config, Tailscale MagicDNS names, or tailnet IPs.
For durable remote work, a per-user Lumbridge runtime on the destination owns
the PTY and process tree. The desktop app connects to that runtime over an SSH
stdio channel and can later reconnect without moving the process to a cloud
service. The same remote workspace may be opened from another authorized
Lumbridge installation, but local UI state is not silently merged between
devices.
## Initial harnesses
@@ -64,13 +82,23 @@ harness-reported, locally measured, estimated, or unavailable. Lumbridge must
not scrape browser cookies or reverse-engineer private account APIs to manufacture
an exact remaining balance. When only local observations exist, the UI says so.
## Buzz collaboration
Buzz is optional and deeply integrated: an engineer can connect an existing
identity, bind channels to workspaces, read and send messages, see channel
agents, and share a pane image. Sharing always previews the exact capture,
redactions, caption, and destination before upload. Buzz identity secrets stay
in the operating-system credential store.
## Non-goals for the first release
- A new foundation-model training or inference service.
- A hosted account or mandatory Lumbridge cloud.
- Replacing every coding harness with one Lumbridge-owned agent loop.
- Windows support.
- Mobile control, collaborative cloud sessions, or remote execution.
- Mobile control or collaborative hosted sessions.
- Arbitrary third-party remote compute provisioning; the first release connects
only to machines and SSH/Tailscale access the user already controls.
- Bundling third-party subscriptions or reselling model tokens.
## Experience principles
@@ -81,4 +109,3 @@ an exact remaining balance. When only local observations exist, the UI says so.
- Approval and security boundaries stay visible.
- Local and offline workflows remain useful.
- Estimates are useful only when their uncertainty is honest.
+8 -1
View File
@@ -4,9 +4,13 @@
- Capture upstream snapshots, licenses, relevant modules, and architectural notes.
- Benchmark UI candidates with six animated terminal panes.
- Prove OpenSSH and `tailscale ssh` stdio transports against a disposable remote
runtime, including disconnect and replay.
- Spike PTY correctness and process-tree cleanup on macOS, Ubuntu, and Omarchy.
- Connect the official ACP Rust SDK to two contrasting harnesses.
- Audit actual usage/quota surfaces for every launch provider.
- Prove Buzz SDK message, attachment, cursor, reconnect, and duplicate-delivery
behavior against a disposable local relay.
- Decide terminal core, UI stack, IPC transport, and schema evolution policy.
Exit: recorded decisions with working spikes and measured results.
@@ -14,8 +18,12 @@ Exit: recorded decisions with working spikes and measured results.
## Phase 1 — terminal workspace alpha
- Durable runtime, local IPC, workspaces, tabs, splits, shells, scrollback.
- Saved SSH/Tailscale hosts and durable remote panes through a per-user remote
runtime; reconnect from a second Lumbridge installation.
- Session restore, crash recovery, command palette, keybindings, notifications.
- Repository/worktree creation and basic Git status/diff.
- Optional Buzz collaboration pane, workspace channel binding, and confirmed
redacted pane-image sharing.
- macOS, Ubuntu, and Omarchy development packages.
Exit: Lumbridge is worth using as a terminal multiplexer without AI features.
@@ -44,4 +52,3 @@ Exit: usage displays are useful, auditable, and honest about uncertainty.
- Signed/notarized macOS releases, `.deb`, AppImage, and Arch package.
- Delta updater with signed manifests and rollback.
- Accessibility, performance, soak, migration, and recovery qualification.
+26
View File
@@ -0,0 +1,26 @@
# Native UI spike scorecard
The GPUI and Floem programs under `spikes/` consume the same six-pane fixture.
No product framework decision is accepted until both rows contain measurements
from macOS and Linux and the hard gates pass.
| Criterion | Hard gate | GPUI | Floem |
|---|---:|---:|---:|
| Builds on macOS Apple Silicon | yes | pending | pending |
| Builds on Ubuntu | yes | pending | pending |
| Builds on Omarchy/Arch | yes | pending | pending |
| Dependency/license closure permits Apache-2.0 distribution | yes | pending | pending |
| Keyboard navigation + AccessKit tree | yes | pending | pending |
| IME and composed Unicode input | yes | pending | pending |
| Isolated system browser child | yes | pending | pending |
| Cold startup, p50/p95 | record | pending | pending |
| Idle RSS / six-stream RSS | record | pending | pending |
| Key-to-present p50/p95 | record | pending | pending |
| Six-stream frame p95/p99 | record | pending | pending |
| Release binary/package size | record | pending | pending |
| Native menu/window/clipboard/drag-and-drop | review | pending | pending |
| API clarity and maintenance burden | review | pending | pending |
The current programs establish dependency, build, launch, and static layout
baselines. The next iteration adds deterministic streaming, input timestamps,
accessibility identifiers, a native Markdown editor, and one Wry browser child.
@@ -0,0 +1,25 @@
# 0003: Data is local; remote sessions live on the user's remote machine
Status: accepted for implementation.
Each Lumbridge installation owns a local SQLite database and content-addressed
data directory. There is no mandatory Lumbridge account, hosted database, or
silent multi-device synchronization. Credentials remain in platform credential
stores, SSH agents, or upstream harnesses rather than SQLite.
Lumbridge supports local work and user-owned remote machines as equal execution
targets. OpenSSH is the default transport and may reach a Tailscale MagicDNS name
or tailnet address. An explicit `tailscale ssh` transport is also supported.
Lumbridge consumes existing connectivity and authorization; it does not manage
tailnet ACLs or private keys.
Durability belongs where the process runs. A remote per-user Lumbridge runtime
owns remote PTYs, agents, worktrees, event history, and scrollback. Desktop apps
connect over a framed SSH stdio stream and reconnect by stable session ID. This
allows a MacBook to close or change networks without terminating work on metal
or amd-server.
Another authorized Lumbridge installation may discover and attach to that remote
workspace. Its device-local window layout and preferences remain local. The
remote runtime arbitrates a single input owner in the first release; real-time
collaborative editing is a separate future capability.