summaryrefslogtreecommitdiff
path: root/src/dump.zig
Commit message (Collapse)AuthorAge
* A Dump makes every directory missing on the way to its DumpDir, as a fresh ↵Gabriel Schneider36 hours
| | | | | | | | HOME needs outPath made only the last directory, so on a HOME with no ~/.local/share the default DumpDir failed no such directory. It now makes each missing parent, as mkdir -p; the known-wrong line in docs/divergences.md goes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A dump holds every column a session may, 16, not 6Gabriel Schneider36 hours
| | | | | | Dump of a session with more than 6 columns failed bad dump columns, since dump.zig's max_cols was 6 while a session holds MAX_COLS. It is MAX_COLS now; the limit's lines in docs/fs.md and docs/divergences.md go. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Two Dumps in one second get names of their ownGabriel Schneider36 hours
| | | | | | A dump is named by the second it was written in, so a second Dump within it overwrote the first. A clash now takes -2, -3 and on. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* DumpDir reads back absolute and without a trailing slashGabriel Schneider36 hours
| | | | | | A relative DumpDir read back as written, relative, and a trailing / stayed. It now resolves against the directory pardes started in, as a Dump already did, and is shown cleaned. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The workspace tag's Restore word names the last dump, and the dump a Restore ↵Gabriel Schneider36 hours
| | | | | | | | came from Once the workspace tag was edited, its own text kept the Restore <path> of the dump at that time, stale after the next Dump; and a Restore dropped the path altogether (the new session had no last dump). A new dump now swaps the old path in the tag's own text, and a Restore points the word at the dump it read. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Recent goes on across a Restore, and is kept after itGabriel Schneider36 hours
| | | | | | A Restore makes a new session, which never loaded the kept list, and saveRecent gives up until it has: Recent was empty after a Restore and nothing opened afterwards was kept. The new session now takes the old one's list (a boot from a dump reads the kept file). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Tty takes a directory as long as a path may beGabriel Schneider36 hours
| | | | | | | | | | | A terminal's directory rode inline in the spawn effect, capped at 256 bytes, so Tty in a directory of about 377 bytes said path too long. A directory past the inline buffer now goes out of line (Pardes.spawn_dirs, given to the host when the spawn is performed), up to the host's path limit (4095); past that, Tty says its directory is longer than a path may be. The effect queue stays its size. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A pane restored with unsaved text is asked about before it is thrown awayGabriel Schneider36 hours
| | | | | | | | | Exit, Restore, Del and get warn only about a pane edited since it was opened, which its saved hash says (set at its first edit). A pane a Dump kept dirty came back with no hash, so a restored session quit at once over it. Restoring one dirty now gives it a hash its text does not match. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Merge: 9P rounds 7-8 + layout files + loose ends + G3 cursorGabriel Schneider36 hours
|\
* | Restore keeps each pane's dot, as acme's dump doesGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | | | A restored text pane came back with its caret at its view's top, whatever had been selected. The dump now keeps each text pane's dot, q0 and q1 as acme's keeps a window's, and Restore puts it back without moving the view it kept. Two look-walk tests that restored and walked on now start from the match they were on. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A column has a ctl, an exec and an rmdir over 9P, and Restore maps its serialGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | A script could read and write a column's tag but not act on the column. col/<serial>/ctl takes Delcol, Joincol, New and Tty, each acting on that column as from its tag; col/<serial>/exec runs a word as a middle click in the tag; rmdir col/<serial> closes an empty column and refuses one with panes (ENOTEMPTY, an err record saying why). The root ctl's refusal of Delcol and Joincol points at col/<serial>/ctl. A dump keeps each column's serial and Restore logs restoredcol <old> <new>; the dump golden gains them. Documented: Joincol's survivor, the column on the right, keeps its serial and tag. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A desktop session holds 64 panes, and every route that finds none free says soGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | Sixteen panes was far too few for a real session. MAX_PANES is now 64 on a desktop and stays 16 on the board; the 48 more slots cost about 3.7 KB each in fixed tables (the core 1.33 to 1.45 MB, its surface 19 to 72 KB), and a pane itself (84 KB and its terminal) is allocated only when it opens. At the cap, pane/new fails with `pane/new: no pane slots: 64 max` and an err record rather than a bare ENFILE, a 9P look or exec that would open a pane fails its write with the same words and reads back empty, and New, Tty, Tutor and Alt-n say it on the message row (their ctl writes fail with it). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A dump keeps the settings changed from a fresh session's, and Restore sets themGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | | | | | A session running with Placement pardes came back from Restore as acme: a dump kept the layout and the theme but no setting. It now keeps every setting line that differs from a fresh session's, as the root ctl reads it, and a Restore applies them; the theme stays where it was kept, the font the frontend's, and REPL bindings are still dropped. The dump golden gains the three the snapshot harness sets. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A failed Dump or a Restore of no dump fails its write, before any warningGabriel Schneider36 hours
|/ | | | | | | | | | | | A Dump into a DumpDir it could not write, or a Restore of a file that is not a dump, answered a ctl write with rc 0 and only a message, and the Restore warned about unsaved panes before it ever looked at the file. The hosts' dump write now fails the waiting 9P write with EIO (the late failure a Save uses), naming the path and the reason in the log, and Restore parses the file before its unsaved-panes refusal, failing with `not a pardes dump`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
*-. Merge: 9P round 6 + empty columns + render (acme theme, grips, Lift, Motion)Gabriel Schneider36 hours
|\ \
| * | A column can be empty, as acme's can; new panes go where acme's ↵Gabriel Schneider36 hours
| |/ | | | | | | | | | | | | | | | | | | | | | | | | | | makenewwindow puts them Newcol makes an empty column; closing a column's last pane leaves it empty with the keyboard on its tag; Delcol and Joincol alone take a column away; the session's last pane closing quits. The +New stand-in and replaceStillborn / stillborn_joiner are gone. Every new pane goes through exec.placeNew, which follows acme's makenewwindow (active column, empty column whole, blank space, halving the biggest) or, with Placement pardes, the old rules. ColumnTags is gone: column tags are always shown. A grip drag shows acme's box cursor. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A Restore logs restored <old> <new> for each paneGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | A script holding serials from before a Restore could not find its panes: the replacement numbers them afresh. The dump now keeps each pane's serial (0 in older dumps), and the replacement's log says `restored <old> <new>` for each after its `restore <path>`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A restored command pane comes back finished, not as a live shellGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | After Restore a dogfood agent's command panes were fish shells under a stale `(make) exit 0` tag. The dump's terminal record now keeps a command pane's line and status, and Restore brings it back done: what it printed, its exit, no shell and no rerun. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Restore brings a Tty bash pane back running bashGabriel Schneider36 hours
|/ | | | | | | | | A dogfood agent's `Tty bash` pane came back from Restore running fish: the dump kept its directory but not the shell it was opened on. The dump's terminal record now carries that shell (empty for the configured one, as older dumps read), and Restore starts it again. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A spawn names the pane it was made for, so a pane closed and its slot ↵Gabriel Schneider36 hours
| | | | | | | | | | | | | | retaken spawns nothing The spawn effect carried only a slot, and the host read the command and shell off whatever pane held the slot as it forked: a command pane closed and its slot taken by the next one before the effects ran forked the new pane's command twice. The effect now carries the pane's serial and is dropped when the slot holds another; forkShell checks it again after giving up the turn for its directory's stat, the one moment a 9P client can change the panes under it. Every front end performs spawns with the turn, from its step. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A Restore answers its writer before hanging up, and the log records dumps ↵Gabriel Schneider36 hours
| | | | | | | | | | | | | | | | and restores A client that wrote Restore saw its connection cut with no answer, and could not tell a Restore from a crash. The listener now lets the writer's answer out before the cut, and cuts only the old editor's connections, refusing their requests meanwhile; a client that dials during it is the new editor's and stays. Dump logs 'dump <path>' and the restored editor's log 'restore <path>'. Keeping connections across a Restore was weighed and left: the fids name the old editor's panes and opens, so it would mean carrying serials and open records into the new one, where acme's Load only adds windows. tty's Restore also closed its shells' ptys without reaping them; it retires them now. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* File the tag code into tagline.zig and draw tags beside bodiesGabriel Schneider36 hours
| | | | | | | | | | | With tags reduced to Texts, what is left of them is the computed prefix, the default and saved tails, entering and leaving a tag and the headers: that goes to tagline.zig, as acme keeps the tag half of a window in wind.c. Tag and header drawing moves next to body drawing in body_layer.zig, and the tag hit helpers go to tag_layer.zig with the Hit they read, where sameCell now also tells the lines of a taller tag apart. The docs describe the tag as a Text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Make the column and workspace tags Texts with the pane tag's keysGabriel Schneider36 hours
| | | | | | | | | | | | | The headers had their own one-line editor with its own keys: Enter always executed, h/l and J/K moved between headers and panes, Ctrl-c/x/v cut and pasted, and TagLine refused a newline that 9P accepted. They are now Texts like a pane's tag, with no prefix and a default until edited, so normal and insert mode, undo and the look and execute keys are the body's. Moving between them is the window keys' job: Up from a pane with nothing above it reaches its column's tag and then the workspace's, Down comes back, and Left and Right walk the column tags. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Make a pane's tag a Text edited with the body's own keysGabriel Schneider36 hours
| | | | | | | | | | | | | | The tag was a fixed buffer with its own one-line editor, a cursor measured across the path, and a hijack of the body's mode while it was typed into. It is now the pane's second Text: its own characters after the computed prefix (path, dirty marker, PDF page), which is never stored in it, so a rename or a dirty marker never moves its cursor. Normal and insert mode are the body's, undo included; `:` moves the keyboard between body and tag, the tag remembers its cursor and starts on Save, and executing a word from it hands the keyboard back. The mouse still sees the prefix: a sweep selects across it and a click on the path drafts a new name. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Give a pane's body its own Text holding the cursor, selections, mode and undoGabriel Schneider36 hours
| | | | | | | | | | | acme keeps what edits a text in its Text (dat.h:171-190) and the window holds a body and a tag of that type. The cursor, the selections, the modal state and the edit-buffer undo move off Pane into Text.zig, Pane holds them as its body, and the edit and normal-mode operations take the Text they edit. Nothing changes in behaviour; this is the step that lets the tag become a second Text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Give the pipe its own fields in PipeGabriel Schneider36 hours
| | | | | | | | | | | | | | Not a pure move: state moves. Pardes's `pipe_seq` and `pipe_wait` become Pipe.zig's own fields `seq` and `wait`, and Pardes embeds one as `pipe: Pipe = .{}`. pipeRequest reads only the request in flight, so it now takes `pipe: *const Pipe` and the four shells call `core.pipe.pipeRequest(id)` (their Pipe imports go away again); the other pipe functions still need the panes and keep `p: *Pardes`, writing `p.pipe.seq/wait`. Field reads in dump.zig, the shells' tests and two test files follow (`core.pipe_wait` becomes `core.pipe.wait`). No behaviour change. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Move saving and loading a whole editor out of pardes.zig into dump.zigGabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | | Pure move, no behaviour change (acme keeps dump and load in rows.c): dumpState, restore, initFromDump and initDump go verbatim to the end of dump.zig, after the dump format they read and write. Inside dump.zig the moved code's `dump.` prefix drops, so `Pane` there is the dump record; the one editor pane it names is spelled `pardes.panes.Pane`, and its other `panes.X` references become `pardes.panes.X` because dump.zig's own tests use `panes` as a local name. The methods become free functions taking `p: *Pardes`: `p.dumpState()` becomes `dump.dumpState(p)`, `core.restore(bytes)` becomes `dump.restore(core, bytes)` and `Pardes.initFromDump(..)` becomes `dump.initFromDump(..)`, in pardes.zig, the shells, layout.zig, Terminal.zig, builtins.zig and the tests (38 receiver rewrites plus the initFromDump calls). The tag-tail restore helpers stay with the tag code. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Repaint PDF highlights by row, send rasters by shared memory, and animate ↵Gabriel Schneider36 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | messages PDF highlights (hover preview, search, selection) are baked into page rasters, and any change re-rendered the whole page with MuPDF; the TTY then re-sent it as base64 (4.7 MB a page), the GUI as a new texture. Worse, a pointer motion over a PDF invalidated the page even when no preview was shown, so every motion paid that. Now: - A raster whose baked highlight set equals the wanted one is left alone. - A highlighted page keeps its clean rows (before highlights and tint); a change repaints only the rows of quads that differ, running MuPDF's highlight pass (pardes_pdf_paint_highlights) over those clean rows and tinting them: the operations a full render performs, so the pixels are identical. MuPDF band renders are NOT bit-identical to a whole page (edge rows, resampled images), so they are never used to patch; the comment claiming otherwise is corrected. - ImagePlace.patch hands shells the changed rows; the GUI uploads just those rows into the texture it holds. - The TTY probes kitty shared memory (t=s) with an id vaxis never reaches and sends rasters as a /dev/shm name when the terminal reads it; direct base64 otherwise (ssh). - Shells that take row patches (GUI, TTY with shm) repaint a selection while it is dragged instead of only on release. Latency elsewhere: - TTY: an animating frame no longer sleeps 16 ms blind; a tick thread posts into the input queue, so input inside the frame is handled at once. - TTY and GUI: queued pointer motions coalesce to the last. - GUI: a skipped swapchain image re-arms the frame (3 retries); animations still tick while nothing presents. - Editing: the line index is carried across an edit instead of rebuilt from a scan of the whole file per keystroke. Messages fall into their row (ease-in; the GUI slides the band out from under the tagline, a terminal fades it), stay until the next input as before, linger MessageLinger ms (default 800), and dissolve (ease-out). MessageAnimation toggles it; both are settings, in Config and startup files. The snapshot harness pins the old behaviour. The detached server now ticks animations. A restored terminal comes back live: the old screen and scrollback (dumped as clean VT by ghostty's formatter, replayed at the new size; older dumps fall back to their rendered text), a dim "restored history" marker, then a new shell in the directory it was in. Right-click on a line number in a file pane looks at that line (a sticky context header's number included). Measured with an external pty driver (TTY), an in-process fence trace (GUI, PARDES_TEST_LATENCY), and test/pdf_pointer_bench.zig (pixel identity against the baseline and a whole-page oracle); balanced A/A/B rounds, paired per-round statistics. Messages stack: each event gets its own row and its own fall, linger and dissolve; a line keeps its row until it leaves and a new one fills the first free row. Announcements and statuses are replaced in place, not stacked. MessageFall, MessageDissolve and DumpDir are settings Config reports. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* Default location results to stacked addresses and source previewsGabriel Schneider36 hours
|
* Mute result declaration context and show nesting after locationsGabriel Schneider2026-09-15
|
* Add optional compact tagline styling for source contextGabriel Schneider2026-09-15
|
* Align location results and configure source contextGabriel Schneider2026-09-15
|
* Add optional tree-sitter declaration contextGabriel Schneider2026-09-15
|
* trunk: resume before the Reload experimentGabriel Schneider2026-09-15
| | | | Empty marker on the last pre-Reload change. Keep the Reload experiment on reload (3801914), its first change on reload-start (200a1fc), and the unfinished performance investigation on reload-perf-wip.
* Resolve relative restores in the dump directory and propagate LSP probe errorsGabriel Schneider2026-09-15
|
* Refactor panes and filesystem; replace FUSE with 9PGabriel Schneider2026-09-07
| | | | | | 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.
* One core behind N frontends, the board's own runner moved in, and every ↵Gabriel Schneider2026-08-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | board cap on one screen ## The wire is the effect stream, not a new protocol `pardes --detach` leaves a core running with no terminal; `pardes --attach` is a frontend that owns a terminal and a socket and nothing else. N frontends on one core all look at the same screen — `screen -x`, not N sessions. The codec (`src/detached/wire.zig`) carries exactly one `Event` or one `Host.VTable` call per message. That is not a coincidence and it is why there is no third vocabulary to keep in step: the core's IO seam was already a struct of function pointers with plain-data arguments, so a socket is a legal implementation of it. `nested.zig`'s socket could not be reused — it carries a builtin command line, and a command line cannot carry a frame. ARCHITECTURE-NEUTRAL on purpose, not as decoration. The frontend on the far end may be riscv32-freestanding on the ESP32-P4 while the core is x86_64 Linux, so every field is an explicit little-endian fixed width and no message is a blit of a native struct. A protocol that only works between two builds of the same compiler would have thrown away the one frontend that motivated it. ## The board comes in; its toolchain stays out `src/p4.zig` becomes `src/esp32p4.zig`, and the pardes half of `../05-zig-p4` — the vaxis-over- serial runner, the UART editor terminal, the keystroke rescue ring, the on-die test suite — moves into `src/esp32p4/`. `build.zig.zon` gains `.zig_p4 = .{ .path = "../05-zig-p4" }`, so `zig build -Dplatform=esp32p4 -Desp32p4-firmware` builds, flashes, monitors and self-tests the board from this repo's `build.zig`. The DIVISION is the point. What moved is what only pardes wants: the runner that drives a pardes core over a serial line. What stayed is everything a second project would also want — the HAL, the register/radio/oracle layers, the linker script, `_start`. `zig_p4` declares no dependencies of its own and its `build()` early-returns when it is not the root package, so this costs the package graph exactly zero packages and the editor's own builds nothing at all. ## limits.zig: nine forgettable places become one budget Nine `platform == .esp32p4` capacity tests lived in nine files. They were never nine decisions — they are ONE decision, how much memory this build may spend, taken nine times where no reader could see the total. `src/limits.zig` puts the whole budget on one screen with every cap named against what it is measured against, derived from two booleans. The payoff is testability on a machine that is not the board: the caps are ordinary comptime values, so a host build can be compiled against the board's numbers and the parking, eviction and clamping paths a 240 KiB core takes get exercised by the normal test suite instead of only over a UART. ## A bare `zig build` `zig build` with no arguments now builds the tty and GUI binaries and installs them into `~/.local/bin`, and says so once on stdout with the flag that overrides it. The old default built one binary into `zig-out` — a path nothing on a `PATH` ever looks at, which made "build it" and "use it" two different commands for no reason.
* A fourth platform: pardes as ESP32-P4 firmware, bytes in and bytes outGabriel Schneider2026-08-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `-Dplatform=p4 -Dtarget=riscv32-freestanding` emits a single freestanding OBJECT exporting a seven-function C ABI, not an executable. The board's toolchain (../05-zig-p4) owns `_start`, the linker script and the UART driver and links this in. The seam is bytes rather than types, so neither side can accidentally depend on the other's internals, and a signature that drifts fails at link time. The serial line is the whole of the I/O. `src/p4.zig` drives vaxis unchanged over it: the renderer is a byte writer and `queryTerminalSend` is a byte writer, so the terminal emulator on the host answers the capability handshake and the firmware sees a real terminal. Measured going out over the wire on attach: alt screen, in-band resize, cursor report, kitty keyboard, kitty graphics, DA1. THREE WORDS EXIST ONLY HERE. `src/board_memory.zig` implements `Peek`, `Poke` and `Hexdump`, gated on `builtin.os.tag == .freestanding and !isWasm()` - derived from the TARGET, because they are a property of running with no OS under you rather than a product option, and because wasm is freestanding too and is exactly what must be excluded: in a browser an address is an offset into the linear memory this editor's own heap lives in. Every access goes through `*allowzero volatile`: a peripheral register is not memory, and address 0 is an ordinary unmapped address on this bus. One 4 KiB cap per command, set by the console rather than the memory - an unbounded dump would wedge the only console the board has for eleven hours. Measured on ESP32-P4 rev v1.3 silicon, driven from a host terminal: Peek 0x501101a4 0x0e63ce71, then 0xaeaa6919 on a second read - the RNG register, so the volatile loads are not folded Poke 0x5011002c 0xdeadbeef LP_STORE0; a later Peek returned 0xdeadbeef Hexdump 0x5011002c 32 16 bytes a row, hex columns and an ASCII gutter Peek 0x50110001 `peek: MisalignedAddress` on the message row That last line is the one that matters. A misaligned 32-bit access traps, and a trap in firmware is a watchdog reset that takes the session with it, so the check that turns it into a message is the reason the file is hand-written rather than a generic reader. BARE METAL BOOTS AN EMPTY OUTPUT BUFFER. Every other boot layout in `init` makes a shell, and on this platform that is not a preference but an impossibility: nothing to fork, no pty to give a terminal pane. Booting one anyway produced precisely what that describes - a pane whose tag ends in `Filter`, no gutter, no buffer, and every keystroke vanishing into the Fallback's silent pty. An output buffer is also what the platform's own words want, since Peek, Poke and Hexdump each fill one. Sized for the board rather than for a desktop: * `allocators.zig` gains a p4 tier that is ALL fallback - every capacity is zero, so each arena spills immediately to the 384 KiB heap the firmware hands over, and no megabyte-shaped static reservation lands in `.bss`. * `source_manifest.zig`'s allowlist is EMPTY on p4. The table is ~0.95 MiB of rodata against a 1.5 MiB flash partition; the firmware's filesystem is the serial host's, through the Host vtable. * The grid is clamped and the clamp is measured, not guessed: every cell is paid for four times (vaxis Screen + InternalScreen, pardes Surface + previous_cells), so 40x12 fits and 80x24 exhausts the heap during `Pardes.init`. * `Vaxis.resize` deinits both screens before allocating replacements, so a failed resize leaves vaxis rendering nothing. The p4 shell keeps the previous geometry on failure instead of leaving a half-applied one. Also here: `output_pane_integration_test.zig` had an exhaustive switch over `Platform` that adding `.p4` left unhandled, which broke `zig build unit-test` outright - the native test binary is the one consumer no platform build compiles. 346 tests pass again.
* big slow change: prebuilt shaders (SPIR-V/Metal), core gui reflow, docs, web ↵Gabriel Schneider2026-08-18
| | | | + snapshot refresh
* add vanilla DOM web backendGabriel Schneider2026-08-10
|
* output panes remember the command that opened themGabriel Schneider2026-08-01
| | | | | | | | | | | | | | | | An output buffer was a file pane with a flag, and everything special about it was re-derived from outside by asking the wrong question: the buffer NAME ("+Search", "+Help"), a parallel search_kind field, and f.output predicates sprinkled through kind-agnostic code. Now it carries its Origin — the Builtin, or the lsp.Kind for the five gotos helix binds as motions rather than words — plus that command's argument, and one Traits table answers every question the scattered code used to ask: what it is called, whether n/N steps it, whether it is a doc for layout, whether Esc dismisses it, whether it saves. The name is derived FROM the command instead of being the thing that identifies it. Adding a kind of output pane is adding a row. No golden moved.
* silence library std.log: ghostty-vt's unimplemented-sequence chatter was ↵Gabriel Schneider2026-08-01
| | | | painting over the UI
* adding better search to tty modeGabriel Schneider2026-08-01
|
* dumps: per-user data dir + timestamped names; Restore builtin loads a dump ↵Gabriel Schneider2026-08-01
| | | | into the live session. dump.outPath resolves $PARDES_DUMP verbatim (the snapshot harness pins /tmp/pardes-dump.zon so dump/load/restore goldens stay deterministic), else $XDG_DATA_HOME|~/.local/share /pardes/pardes-YYYYMMDD-HHMMSS.zon (dir mkdir-ed; wall clock via libc clock_gettime — std.time.timestamp is gone in 0.16). After write_dump the shell reports the written path back (core.setLastDump) and the topbar grows "Restore <path>": middle-clicking Restore reloads the last dump, and "Restore <path>" executed anywhere takes the path as its first argument (onSelect prefix match). Core stays sans-IO: the builtin stashes restore_req; each shell consumes takeRestore() after drainEffects and swaps in initFromDump at the current screen size (pre-sized: dump panes never greet), tearing down the live ptys (tty: cancel reader + close + gen bump; gui: SIGKILL, the gen-guarded eof closes the old fds). Web ignores it. New restore.snap golden: KEEPME survives the restore, GONESOON echoed after Dump does not, the topbar word appears then resets. 29/29.
* pardes v2: the rewrite, complete and organized. src/ (core + three shells), ↵Gabriel Schneider2026-08-01
test/ (snapshot parity harness + 18 frozen goldens). One sans-IO core, vaxis tty + SDL3 GPU native + wasm web shells, 18/18 parity with the purged prototype, 7.6k lines vs 12.1k. Fix: gui shell pre-sized the core at init so the greet-releasing resize never fired (blank panes until first interaction); live sessions now init at defaults and get the real grid as a resize event (the shell contract, documented on Options).