WHAT THIS IS: a wishlist, in the author's own words. The items below are left exactly as written; this header is the only thing kept in sync with the code, because a list that reports shipped work as pending is worse than no list. 9P (docs/9p.typ is the note, docs/registry.typ the argument). SIX NEW THINGS, each verified against a running program and not assumed: 1. A DETACHED SESSION CAN BE SCRIPTED. `pardes --detach=work --fs` mounts its own /dev/fuse and polls it in the same poll(2) as its frontends and pane shells, so it needs no wake thread — less than the desktop shells pay. The one configuration whose panes outlive every terminal was the one no script could reach. Proof: examples/acmefs/pardesctl panes|new|send|body|del. 2. TERMINALS ARE SCRIPTABLE. Every terminal pane grows `pty/ctl`, `pty/status` and `pty/data`. `winsize 80 24`, `sig INT|TERM|HUP|QUIT|KILL`, `exec`; a write to `pty/data` is input to the process and a read is its RAW output, escape sequences and all. A script could only ever write into a terminal that already existed; now it can start one, resize one and signal one. 3. THE TREE IS SERVED OVER 9P. `--fs9` puts acme's control filesystem on a unix socket as base 9P2000 (src/9p.zig — codec and a sans-io server, no threads, no allocator, builds freestanding). plan9port drives it: `9p -a ls /`, `read /index`, `write /1/body`, `stat`, a walk through `..`. Errors come back as STRINGS Linux's table knows, not numbers. `--fs` and `--fs9` serve the same tree at once: a write over one reads back through the other. 4. A PATHNAME WITHOUT MOUNTING ANYTHING OURSELVES. `9pfuse ` and ordinary tools work — ls -l with the right modes, cat, shell `>>`, permission denied on the write-only files. That is the route macOS and the browser take, neither of which has ever had a control filesystem. 5. ONE PARDES READS ANOTHER. The `9p ` word walks another instance's tree and opens the bytes in a pane. Before this, two instances could shout one line at each other (nested.zig, write-only, no reply) or REPLACE one another (`Attach` deinits the local core); they could not ask a question. Proof: B read A's /1/body byte-identically to plan9port. 6. THE BOARD SERVES ITS OWN TREE. A second ESP32-P4 image where UART0 carries 9P and nothing else — no ANSI, no vaxis, no allocator — 88 KB against the console image's 809 KB. Its GPIO tree comes from a comptime table (src/board9p.zig) that is the single description: one entry fans out to a directory per pin. The console firmware is untouched and still what `-Dplatform=esp32p4` feeds. No board was attached, so only what builds and what the host tests cover is claimed. AND ONE THING THAT WENT AWAY: pardes no longer depends on the ../05-zig-p4 toolchain checkout to build. It used to be a path dependency named in build.zig.zon, and because `@import` in a build script resolves when the SCRIPT compiles rather than when the branch needing it is taken, anyone without that sibling could not build pardes at all — not the firmware, the terminal shell. The object is the seam: `-Dplatform=esp32p4` emits it here with no toolchain, and the toolchain repository links the flashable images, which it already knew how to do. SHIPPED (verified against the tree, not assumed): - "version tracking" -> done. `build.zig` reads `.version` from build.zig.zon via an untyped `@import`, `gitCommit(b)` reads the commit at configure time, both reach `pardes_config`, and `pardes --version` prints them. - "markdown treesitter highlight with nested codeblocks" -> done; markdown is in `src/grammar_manifest.zig`. - builtin `Changelog` -> done; `src/builtins.zig`. - builtin `Newtty` -> done; `src/builtins.zig`. - builtin `Joincol` -> done; `src/builtins.zig`. - "only create a new column if both panes get at least 100 columns" -> done; `pardes.zig` calls `p.columnFitsHalves(from_id, 100)` on the open path. - "in a tty pane if the leaf process is a shell, ESC behaves as SHIFT-ESC" -> done, in c3d0b84. `pardes.zig`: "A shell prompt is a pane you can leave: plain Esc there is Shift-Esc", guarded by `takesCommandLine`, which is `pane.isTerminal() and !p.hostTtyTaken(id)` — exactly "the leaf is a shell and not a full-screen program". I first recorded this as PENDING by reading the Shift-Esc CHORD handling thirty lines above it and concluding from the absence there; the note is kept because the mistake is instructive. STILL PENDING, checked rather than guessed: - `.patch`/`.diff` highlighting: no such grammar or extension in the tree. - the tty escape-scanning `tests:` item, and the tty-colour bug: neither confirmed fixed. The OTHER `tests:` item — "clipboard integration for tty escape codes should work" — has shipped in both directions: `src/tty/tty.zig` mirrors a yank register out via OSC 52 and reads the other way, the reply arriving as an ordinary paste. ("neither" covered three items here until an audit counted them.) meta: - version tracking - special coloring algorithms are aplied based on the title of a pane. implemented as just ifs and else ifs. one of those ifs will be the one that choses the color algorithm for tty panes, other will select the treesitter coloring for sourcode files, and the other one will be the new one to highlight .patch and .diff files - added markdown treesitter highlight with highlighiting of nested codeblocks new builtin: - Changelog - Newtty: Added by default on all pane taglines. It will spawn a new tty pane (at tty mode from the start) on the directory of the pane that called it. The pane struct field for the working directory should be a tagged enum for either .none, .inherited (with a pointer to the pane it inherits) or the dir slice itself. when a pane is deleted in a frame, its allocation will leave until the end of the next. During the next frame the deleted frames will be in a special list of deleted frames. this deleted pane list state will live on a new allocator: the pane allocator which will wrap a regular allocator, and this newly deleted list is passed to the pane tick/update/frame as a pointer so that it can just access it. this new allocator will also have the tick/update function so that it wires de regular allocator dealloc/free to the deleted list and the deferred actual deallocation. the pane struct will have a new function that will visit each kind of field that has a pane pointer in it and decide how to update it based on the field type when the pointer is on the deleted list; it's fine that during the runtime each field visits each pointer O(n*m). - Joincol: added by default on the full window tagline. it deletes the column of the current/last focused pane and moves its panes to the column to the right. if there's no other column it should do nothing keyboard: - in a tty pane if the current/leaf process is a shell, ESC will have the same behaviour as SHIFT-ESC layout behaviour: - When opening a new file, it will only create a new column if both panes affected will have at least 100 columns each. Otherwise will just create a new pane. bug fix: - the tty colors are affected by changes to its normal mode tests: - if tty escape scanning is active (chosen when libvaxis is created) it should always use all the features it detects by default. - clipboard integration for tty escape codes should work.