summaryrefslogtreecommitdiff
path: root/src/limits.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-06 18:11:36 -0300
committerGabriel Schneider <[email protected]>2026-09-07 13:59:12 -0300
commit60367d8fe23f6af98ec28e3cf6c2094dfe332df0 (patch)
tree310fc734173cf771881f4691c71909135fadde97 /src/limits.zig
parentfa82cac885cb4738fe36d1e49b4749b5a3e31a4a (diff)
downloadpardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.tar.gz
pardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.zip
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.
Diffstat (limited to 'src/limits.zig')
-rw-r--r--src/limits.zig237
1 files changed, 0 insertions, 237 deletions
diff --git a/src/limits.zig b/src/limits.zig
deleted file mode 100644
index ee94a4f6..00000000
--- a/src/limits.zig
+++ /dev/null
@@ -1,237 +0,0 @@
-//! Every board-shaped capacity in one table.
-//!
-//! These numbers used to be nine `platform == .esp32p4` tests scattered across
-//! nine files, each one a separate place to forget. They are not nine
-//! decisions: they are ONE decision — how much memory this build is allowed to
-//! spend — taken nine times, in nine files, where no reader could see the
-//! total. Here the whole budget is on one screen and every cap says what it is
-//! measured against.
-//!
-//! Two booleans derive all of it, and nothing outside this file tests the
-//! platform for a capacity again.
-//!
-//! WHAT DOES NOT BELONG HERE: capability switches. `terminal_panes`,
-//! `board_memory.enabled`, `hosted`, `font_picker` and the rest answer "does
-//! this build have the thing at all", which is a question about the platform
-//! and not about a budget — they stay next to the thing they gate. That
-//! division is also why a build option selecting the board's budget on a
-//! desktop does not work; the note on `board` below records the attempt.
-const std = @import("std");
-const builtin = @import("builtin");
-const config = @import("pardes_config");
-
-/// `board` is the ESP32-P4 firmware's budget: a 384 KiB heap and a 240 KiB
-/// chunk of L2MEM shared between `.bss`, `.data` and the stack. `reduced` is
-/// any freestanding target with no OS under it — the browser's wasm linear
-/// memory grown on demand, megabytes rather than tens, but not a desktop's
-/// address space.
-///
-/// TWO BOOLEANS AND NOT A PROFILE ENUM, and a build option was tried and
-/// removed. `-Dmem-profile=board` was meant to let a native test runner
-/// compile the board's capacities and boot the core under them; it does not
-/// work, and cannot. The dominant term in a boot is `@sizeOf(Pane)`, which
-/// carries the ghostty-vt Terminal — 1.1 MiB of it — and what removes that is
-/// `pardes.terminal_panes`, a CAPABILITY keyed on the platform rather than a
-/// capacity in this table. So the option shrank the rings and left the boot
-/// six times over budget, producing a configuration nothing was designed for:
-/// `zig build unit-test -Dmem-profile=board` deadlocked in a futex rather than
-/// failing, because a hosted build with the board's effect ring silently drops
-/// effects a hosted test is waiting on.
-///
-/// What DOES test the board's memory pressure natively is in pardes.zig: the
-/// grid-scaled cost and the allocation-failure sweep, both of which are
-/// platform-independent and run on the ordinary build. See the comment block
-/// above `board_heap_bytes` there.
-const board = config.platform == .esp32p4;
-/// No OS means no address space to reserve megabytes out of, whatever the
-/// platform is called. `.web` is wasm32-freestanding and `.esp32p4` is
-/// riscv32-freestanding, so the target answers this for both.
-const reduced_target = builtin.os.tag == .freestanding;
-const KiB = 1024;
-const MiB = 1024 * KiB;
-
-/// THE NUMBER EVERY OTHER NUMBER HERE IS MEASURED AGAINST: the board's whole
-/// heap, the 384 KiB chunk of L2MEM at 0x4FF40000 (`05-zig-p4`'s linker script
-/// owns the split; the 128 KiB above it measured as L2 cache rather than
-/// memory). Unconditional and not profile-derived, because it is a fact about
-/// the silicon rather than a budget this build chose — a desktop build that
-/// wants to know what the board affords is asking exactly this question, which
-/// is what the memory tests in pardes.zig do with it.
-pub const board_heap_bytes = 384 * KiB;
-
-/// How many effects the ring holds. SHRUNK, not moved to the heap, on the
-/// board: `pump` drains this to empty on every iteration with an
-/// unconditional `while (nextEffect())` — including effects `perform` itself
-/// queues — so no capacity can deadlock the drain, and the only question a
-/// capacity answers is how big a single-pump BURST may be before `emit`
-/// refuses the overflow. The one producer that can burst is `emitWrite`,
-/// which chunks arbitrary bytes into 64-byte `.write` effects for a pty, and
-/// a build with `terminal_panes == false` has no pty to write to. Everything
-/// else queues O(1) effects per event, and `in_q` holds at most 64 events per
-/// pump, so 128 leaves two effects per queued event.
-///
-/// A 1.0625 MiB inline ring cannot live in the board's 384 KiB heap at all;
-/// 128 entries is 34 KiB. NOTE THE BEHAVIOUR CHANGE: `emit` has always
-/// refused (not evicted) once full, so on the board a burst larger than 128 effects
-/// now drops its tail where 4096 would have held it — reachable only through
-/// `emitWrite`, i.e. only if a pty ever appears on this platform.
-pub const effect_cap = if (board) 128 else 4096;
-
-/// Bytes of a pane's pty write that may WAIT in the core when `effect_cap`
-/// chunks are already queued. `emitWrite` splits a burst into fixed 64-byte
-/// effects, so without this a paste larger than `effect_cap * 64` (256 KiB on
-/// a desktop) lost its tail silently — the ring refuses rather than evicts,
-/// which keeps queued bytes in order but cut the new ones off. The remainder
-/// parks here instead and `nextEffect` refills the ring as the host drains it,
-/// so a large paste is DELAYED rather than truncated.
-///
-/// 4 MiB matches `tty.max_paste_bytes`, the largest burst a host can hand the
-/// core in one event, so the bound is the one the producer already enforces.
-/// Zero on the board: no ptys means no `emitWrite`, and the allocation this
-/// would justify cannot live in 384 KiB anyway. A zero cap parks nothing and
-/// restores the old refusal exactly.
-pub const pending_write_cap: usize = if (board) 0 else 4 << 20;
-
-/// Rows the per-pane soft-wrap map covers. `wrapWidth` refuses to wrap a pane
-/// taller than this (it reads the array's own length), so shrinking it cannot
-/// truncate a map — a taller pane renders unwrapped, exactly as documented on
-/// `Pane.wrap_line`. A serial console is not 128 rows tall.
-pub const wrap_rows = if (board) 128 else 256;
-
-/// A shell's reported working directory, owned inline by the pane. Zero-sized
-/// where there are no processes to report one: the `PdfSlot` rule, applied to
-/// a capacity whose sole producer (`Pardes.setCwd`, fed by a pty's prompt
-/// report) does not exist without terminal panes. `setOwnedCwd` clamps, so a
-/// zero cap reads as "no directory known" — which is the truth here.
-///
-/// Keyed on the profile rather than on `pardes.terminal_panes`, which this
-/// file must not import (the core imports the table, not the other way round).
-/// The two agree by construction: the board is the only build with no ptys.
-pub const cwd_buf_cap = if (board) 0 else 1024;
-
-/// EDIT BOUNDARIES REMEMBERED PER FILE PANE. Every entry owns a gpa copy of
-/// the WHOLE file, so this number multiplies heap, not just the pane: 256 of
-/// them is not a bound a 384 KiB board could ever reach anyway. `pushHistory`
-/// evicts and frees the oldest once full, so the smaller ring loses the
-/// deepest undo steps and nothing else — no truncation, no dropped edit.
-pub const undo_max = if (board) 16 else 256;
-
-/// How many message-row lines the session keeps for `Messages`, and one of the
-/// bigger fixed costs on `Pardes`: an entry is 262 bytes, so 128 of them is
-/// 32.75 KiB that is allocated whether or not anybody ever reads it. That is
-/// 8.5% of the board's whole 384 KiB heap and about the size of its effect
-/// ring, so the board takes sixteen — enough that a failure you looked away
-/// from is still there, which is the whole point, and not enough to matter
-/// beside the panes. This belongs here rather than in config.zig for exactly
-/// the reason the file's header gives: it is a board-shaped capacity.
-pub const message_log = if (board) 16 else 128;
-
-/// Bounds the only user-editable, schema-owned tag fragment. It IS the storage
-/// bound: `Pane.tag_tail` is `[max_tag_tail]u8`, and every writer (appendTag,
-/// tagInsert, restoreDumpTail, the acmefs `tag` file) refuses input that does
-/// not fit rather than truncating it, so the schema limit and the buffer can
-/// never disagree — a dump reader can reject data before copying it into a
-/// pane.
-///
-/// 512 on the P4 firmware. A tag is ONE line — a pane's path plus its command
-/// words — and 4 KiB of it is 4 KiB per pane out of a 384 KiB heap. A serial
-/// console is 80 columns; 512 is six of those.
-pub const max_tag_tail: usize = if (board) 512 else 4096;
-
-/// HOW LONG A HOST-SUPPLIED ABSOLUTE PATH MAY BE, and the only reason that
-/// record was ever kilobytes: the shell a native host resolved, the font file
-/// a native picker returned, and (in pardes.zig) the one watched theme file.
-/// All three name something on a FILESYSTEM, and all three are retained
-/// inline because the core has no allocator at the point they arrive.
-///
-/// Fixed at 4095 wherever a filesystem exists — deliberately NOT derived from
-/// std.fs PATH_MAX, which web has no answer for, and 4095 rather than 4096 so
-/// the macOS C bridge's NUL fits without a second, subtly different limit at
-/// that boundary. Zero on the P4 firmware, which has no filesystem, no
-/// processes to spawn a shell for and no font picker: `Text(0)` is a
-/// zero-sized field whose `set` refuses every non-empty path, so the three
-/// producers report failure instead of storing 12 KiB nothing can fill.
-pub const host_path_cap: usize = if (board) 0 else 4095;
-
-/// WHETHER PARDES'S OWN SOURCE IS EMBEDDED — the source_manifest allowlist,
-/// which is a capacity spelled as rodata rather than as a number.
-///
-/// ON THE P4 the allowlist is EMPTY, and that is the whole difference: the
-/// table is ~0.95 MiB of rodata against a 1.5 MiB flash partition, and the
-/// firmware's filesystem is the serial host's, reached through the Host
-/// vtable. The API is unchanged — `all` is a zero-length array and `find`
-/// answers null — so every caller compiles identically and simply finds
-/// nothing embedded.
-pub const embedded_sources = !board;
-
-/// Bytes per dumped row, and it is a different number on the board.
-///
-/// `hexdump -C`'s sixteen is the layout everyone can already read, and it needs 79 columns: ten for
-/// the address, forty-eight for the hex, a gap, and the eighteen-column ASCII gutter. The P4 drives
-/// a 56-column grid of which seven go to the line-number gutter, so a sixteen-byte row wraps onto a
-/// second display line and the columns stop lining up - which is the entire value of the layout.
-///
-/// Eight fits in 46 and keeps every property that matters: address on the left, fixed-width hex
-/// columns, ASCII on the right, and a gap at the halfway mark because the eye counts in fours and
-/// eights rather than in sixteens.
-///
-/// NO `0x` ON WHAT THESE WORDS PRINT, which is where two of those columns came from. It reads no
-/// worse - every number here is hex, there is no other kind, and the words refuse a decimal one - and
-/// it buys something better than the width: an address in a dump can now be typed straight back into
-/// a `Peek` without editing it, because bare hex is exactly what the parser wants. Output that is
-/// valid input is worth more than a prefix restating what the whole file already says.
-pub const hexdump_row_bytes: u32 = if (board) 8 else 16;
-
-/// Three tiers, because the address space differs by four orders of magnitude.
-/// `reduced_target` is the browser: a wasm linear memory it grows on demand, so
-/// the static reservations are megabytes rather than tens.
-///
-/// `board` is ESP32-P4 firmware, and its tier is deliberately ALL FALLBACK. Every
-/// capacity here is a `StackFallbackAllocator`'s buffer, which is a static and
-/// therefore lands in `.bss` — and on the P4 `.bss`, `.data` and the stack all
-/// share ONE 240 KiB chunk of L2MEM at 0x4FF03000, while the heap the fallback
-/// allocator hands out is the separate 384 KiB chunk at 0x4FF40000 - the 128 KiB
-/// above that measured as L2 cache rather than memory. A
-/// megabyte-shaped reservation here would not fit, and every byte that did fit
-/// would be taken from the stack's neighbourhood to duplicate memory the heap
-/// already has. So the buffers exist only because the type requires one: 4 KiB
-/// absorbs the small churn, and everything else spills to the real heap on the
-/// first allocation.
-pub const arena = struct {
- pub const pardes = if (board) 4 * KiB else if (reduced_target) 8 * MiB else 32 * MiB;
- pub const frame = if (board) 4 * KiB else if (reduced_target) 4 * MiB else 16 * MiB;
- // Zero is legal and always spills, which is exactly what an arena for a
- // compiled-out subsystem should do. `StackFallbackAllocator(0).buffer` is
- // `[0]u8`; `get()` inits the FixedBufferAllocator over an empty slice, so
- // `FixedBufferAllocator.alloc` fails every nonzero request and `alloc`
- // falls through to `self.fallback_allocator.rawAlloc`, while `ownsPtr` over
- // an empty range is false for every pointer so `resize`/`remap`/`free`
- // route to the fallback too. See lib/std/heap.zig, StackFallbackAllocator.
- pub const tree_sitter = if (board) 0 else if (reduced_target) 4 * MiB else 16 * MiB;
- pub const image = if (board) 0 else if (reduced_target) 64 * KiB else 32 * MiB;
- pub const pdf = if (board) 0 else if (reduced_target or !config.mupdf) 64 * KiB else 64 * MiB;
-};
-
-// THE REGRESSION GUARD for the refactor that created this file: nine caps
-// moved out of nine files, and the one thing that must not have changed is
-// what a tty/gui/macos build gets. Spelling the historical desktop numbers
-// here as literals is the point — a derivation would agree with itself.
-test "board limits: a desktop build keeps exactly its historical capacities" {
- if (board or reduced_target) return error.SkipZigTest;
- try std.testing.expectEqual(4096, effect_cap);
- try std.testing.expectEqual(256, wrap_rows);
- try std.testing.expectEqual(1024, cwd_buf_cap);
- try std.testing.expectEqual(256, undo_max);
- try std.testing.expectEqual(@as(usize, 4096), max_tag_tail);
- try std.testing.expectEqual(@as(usize, 4095), host_path_cap);
- try std.testing.expect(embedded_sources);
- try std.testing.expectEqual(@as(u32, 16), hexdump_row_bytes);
- // The arena tier a desktop gets is the third one, so it is only the
- // historical desktop tier when the target is not itself reduced.
- if (reduced_target) return;
- try std.testing.expectEqual(32 * MiB, arena.pardes);
- try std.testing.expectEqual(16 * MiB, arena.frame);
- try std.testing.expectEqual(16 * MiB, arena.tree_sitter);
- try std.testing.expectEqual(32 * MiB, arena.image);
- try std.testing.expectEqual(if (config.mupdf) 64 * MiB else 64 * KiB, arena.pdf);
-}