<feed xmlns='http://www.w3.org/2005/Atom'>
<title>pardes.git/src/fuse.zig, branch release-0.24</title>
<subtitle>Pardes</subtitle>
<id>https://git.0x4200.cafe/pardes.git/atom?h=release-0.24</id>
<link rel='self' href='https://git.0x4200.cafe/pardes.git/atom?h=release-0.24'/>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/'/>
<updated>2026-09-07T16:59:12Z</updated>
<entry>
<title>Refactor panes and filesystem; replace FUSE with 9P</title>
<updated>2026-09-07T16:59:12Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-09-06T21:11:36Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=60367d8fe23f6af98ec28e3cf6c2094dfe332df0'/>
<id>urn:sha1:60367d8fe23f6af98ec28e3cf6c2094dfe332df0</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>detached: drop /dev/fuse from the poll set once the connection dies</title>
<updated>2026-08-27T19:15:35Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-08-27T18:32:02Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=f5927a033f0c83753b5cc004e514568eec8c24f8'/>
<id>urn:sha1:f5927a033f0c83753b5cc004e514568eec8c24f8</id>
<content type='text'>
Review fixes to steps 1 and 2, found by an adversarial pass over the committed
chain. One is a real bug and the rest are comments that were false.

THE BUG. `waitInput` put the FUSE descriptor in the poll set whenever the mount
existed, and the `.fuse` arm ignored every revent. Linux's `fuse_dev_poll`
answers EPOLLERR once the connection is gone, and POSIX reports POLLERR whatever
the events mask asked for -- so an external `fusermount3 -u`, a sysfs abort, or
systemd taking /run/user/$UID away at final logout (exactly when a detached
session is supposed to keep running) made poll(2) return instantly, forever. The
daemon then spun the whole pump at 100% of a core for the rest of its life, and
re-offered every parked slot to the core at that rate.

Measured on the unfixed commit: 0 CPU ticks over 10 s idle, then 1000 ticks over
the next 10 s after unmounting its own mount point. Measured after the fix: 0
ticks over 8 s in the same scenario, process alive and in state S.

fuse.zig's own poll thread has carried the equivalent guard all along, which is
why the desktop shells never showed this and the daemon did.

THE COMMENTS, each checkable and each wrong:
  * `Source.fuse` said the drain is not done in `dispatch` to avoid re-entering
    the core. Both `pull_wait_input` and `push_poll_frame` are called from
    inside `pump`, so either re-enters. The real reason is that `dispatch` is
    mid-iteration over a SNAPSHOT of the descriptors, and one `push_spawn`
    replaces a pane's master under it.
  * `fuse.zig`'s new import said "no cycle". There is a cycle: fs_service
    imports fuse.zig back and still names `*Fs` in three signatures.
  * `Transport`'s rationale said tty.zig and gui.zig store one in a struct
    field. Neither does; all four call sites build it inline.
  * `deinit` justified its ordering against "as long as the harvest takes".
    `harvest` is waitpid(WNOHANG) and blocks for nothing. The real reason to go
    first is that aborting the connection wakes a parked reader while its own
    shell is still alive to run its exit path.
  * `harvest` claimed pane shells are the only children this process forks.
    Since step 1 it also forks `fusermount3`, three times over -- reaped by its
    own spawner, so the conclusion holds and the premise did not.
  * docs/detached.md, docs/lsp.md and docs/design.typ still said the daemon
    implements sixteen of twenty-one methods and mounts no /dev/fuse.
</content>
</entry>
<entry>
<title>fs_service: the transport is a ctx and three functions, not a *fuse.Fs</title>
<updated>2026-08-27T18:32:02Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-08-27T18:28:21Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=0a21ea831d6791b406eef70b3e95cfd319d8ed36'/>
<id>urn:sha1:0a21ea831d6791b406eef70b3e95cfd319d8ed36</id>
<content type='text'>
Step 2 of the 9P chain (docs/9p.typ 12.2, docs/registry.typ 9P-2).

`drain` and `step` never asked a `*fuse.Fs` for anything but `retry()`,
`next()` and `reply()`, so the concrete pointer was a coupling that bought
nothing and forbade a second answer. `Transport` names the three; `Fs.transport()`
is the first implementor and the thunks are the entire cost.

No behaviour change. The order contract -- retry() to null, then next() to null --
moves into `drain`'s doc comment, where it belongs: it is the caller's rule and
every implementor inherits it, rather than a fact about FUSE.

`start` and `wake` keep their `*fuse.Fs`: they are about a MOUNT, which is a
FUSE thing, and a 9P listener will bring its own.

Measured unchanged against zig build fs-bench -Doptimize=ReleaseFast: getattr 19 ns,
lookup 40, read body 4K/1M 25/25, read ctl 385, read index 633, readdir 38,
read event (empty) 22, all at zero allocations.
</content>
</entry>
<entry>
<title>acmefs: pardes --fs serves acme's control filesystem over raw Linux FUSE</title>
<updated>2026-08-25T12:42:07Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-08-25T05:07:23Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=6f48508aa08396bcf9dd4da2cab1d221bcc53f78'/>
<id>urn:sha1:6f48508aa08396bcf9dd4da2cab1d221bcc53f78</id>
<content type='text'>
</content>
</entry>
</feed>
