From 60367d8fe23f6af98ec28e3cf6c2094dfe332df0 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Sun, 6 Sep 2026 18:11:36 -0300 Subject: Refactor panes and filesystem; replace FUSE with 9P Consolidate pane, layout, memory and host code. Serve 9P by default over Unix sockets, with runtime mounts and optional TCP/QUIC transports. Remove FUSE and obsolete proof-of-concept examples. Fix highlighting and terminal-history performance, expand differential and stress-test infrastructure, sort navigation results while preserving the next occurrence, add syntax-colored Braille minimaps, remove SPC-k, and document 9P interaction as a repository skill. --- docs/fs.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/fs.md (limited to 'docs/fs.md') diff --git a/docs/fs.md b/docs/fs.md new file mode 100644 index 00000000..8805ffde --- /dev/null +++ b/docs/fs.md @@ -0,0 +1,89 @@ +# Filesystem + +Every native session serves 9P2000 on a Unix socket. Pane shells receive +`PARDES_9P` (socket path) and `PARDES_PANE` (pane serial). The socket is +`$XDG_RUNTIME_DIR/pardes-9p-.sock`, or lives under +`~/.local/state/pardes` when XDG_RUNTIME_DIR is unset. Detached sessions use +their session name; `--9p=` overrides it. + +A `pardes ` launched from a pane forwards Look to that pane over 9P. +`--nested` opens a separate editor and disables forwarding from its pane shells; +its 9P service stays available. + +Look resolves the OS filesystem first, then the editor's virtual filesystem. +Explicit paths bypass that search: + +| Editor path | Meaning | 9P server path | +|---|---|---| +| `/n/os/proc/self` | OS filesystem | `/os/proc/self` | +| `/n/self/pane/2/body` | pane 2's text | `/self/pane/2/body` | +| `/virtual/src/pardes.zig` | source embedded in this build | `/self/src/pardes.zig` | +| `/n/peer/self/pane/2/body` | another session's text | peer's `/self/pane/2/body` | + +`--mount=peer=work` mounts the named session `work`; the dial can also be an +absolute socket path, `unix!/path`, `tcp!IP!port`, or `quic!IP!port`. +At runtime, use `Mount peer dial` and +`Unmount peer`. There are eight named mounts; `os` and `self` are reserved. +Unmount refuses mounts still used by a pane, its working directory, or a +pending Save. Mounts are saved in dumps. Save uses the file's original mount. + +`pardes --9p-tcp='tcp!127.0.0.1!5640'` adds a TCP listener alongside the Unix +socket. Build with `-Dquic=true` and system OpenSSL 3.6+ to enable QUIC; +`--9p-quic='quic!127.0.0.1!5641'` adds its listener. Both accept numeric +IPv4/IPv6 addresses, not DNS names. Listener port zero chooses a free port; +`/self/listeners` reports all active dial addresses. + +All connections have session access, including `os`. TCP is unencrypted. +QUIC uses an ephemeral TLS identity without peer verification or login. +It carries 9P2000 on one bidirectional stream with ALPN `pardes-9p`. +The four application connection slots are shared across transports; +OpenSSL's internal buffers are separate, dynamically allocated memory. + +[Plan9port's client](https://9fans.github.io/plan9port/man/man1/9p.html) can +drive Unix or TCP without a kernel mount: + +```sh +9p -n -a "unix!$PARDES_9P" read self/index +9p -n -a 'tcp!127.0.0.1!5640' read self/index +``` + +For [Linux v9fs](https://www.kernel.org/doc/html/latest/filesystems/9p.html), +use `version=9p2000,cache=none,access=any` and `trans=unix`, or `trans=tcp` +with `port=5640`. Set `uname`, `dfltuid`, and `dfltgid` for the local user. +Leave `aname` empty: the mount root contains `os` and `self`. Kernel mounts +are not part of the test suite. Neither 9P2000.u nor 9P2000.L is implemented. +Existing Plan9port/v9fs clients need a userspace bridge for QUIC. + +The server root contains `os` and `self`. Under `self`, `index` lists panes, +`new/ctl` creates a pane and returns its serial, and `pane/` contains +`body`, `tag`, `ctl`, `addr`, `data`, `event`, and selection files. Terminal +panes additionally have `pty/{ctl,status,data}`. + +`EffectCode ` lists the current backend's embedded implementation +files under `/virtual`; Look opens their full source. + +`self/screen` returns JSON with `cols`, `rows`, `cursor`, a `styles` table, +and row-major `cells` of `[grapheme, style_index]`. Each open freezes one +frame until close, including across multiple reads. The independent client +can inspect it directly with `Client(socket_path).screen()`. + +A terminal `body` freezes its history on the first read of each open handle; +later reads use the same bytes while output continues. Close and reopen for +newer history, or read `pty/data` for the live stream. Screen and terminal-body +snapshots share 32 handle slots, released on close or disconnect. + +Writing `body` appends; opening it with truncation replaces its contents. +`addr` selects a range and `data` replaces that range. `ctl` accepts `name`, +`look `, `get`, `put`, `del`, and `delete`. Look resolves from that pane +without editing its body or tag. Holding `event` open redirects the pane's Look +and Exec clicks to that client; writing a record back performs the action. + +This is a control filesystem, not a complete POSIX export. Native filenames +may contain up to 255 bytes. Existing regular OS files support read, write, +and truncation to zero; protocol create, remove, rename, and other metadata +changes are refused. Ownership, permissions, and timestamps are synthetic. + +`zig build fs-test` drives real sessions using the independent Python client +in `test/ninep.py`. `zig build 9p-test` checks the freestanding wire protocol; +`zig build fs-bench` measures filesystem transactions in the core. +`zig build fs-test quic-test -Dquic=true` also exercises QUIC mounts and I/O. -- cgit v1.3