<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slosh.git/vendor, branch master</title>
<subtitle>an opinionated terminal multiplexer in C with programmable pane chrome</subtitle>
<id>https://git.sl0p.foo/slosh.git/atom/vendor?h=master</id>
<link rel='self' href='https://git.sl0p.foo/slosh.git/atom/vendor?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/'/>
<updated>2026-09-12T14:05:54Z</updated>
<entry>
<title>vendor: the wuffs calloc stub was hijacking the demo's allocator</title>
<updated>2026-09-12T14:05:54Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-12T14:05:54Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=7617cf20d908386ab3052d53e0c909b4159b7280'/>
<id>urn:sha1:7617cf20d908386ab3052d53e0c909b4159b7280</id>
<content type='text'>
The browser demo came up with `slosh: cannot start session main` and
nothing else. The session server was segfaulting before its socket
existed, on the first calloc() of the config parse -- because in that
binary calloc() returned NULL, always.

pkg/wuffs/src/main.zig exports weak `calloc`/`free` stubs whenever
`!builtin.link_libc`, and callocStub returns null unconditionally. They
are there because wuffs' generated `..._alloc()` helpers are the only
code referencing libc's allocator, we never call them, and linker GC
usually strips them; the stubs cover the case where it does not. The
comment reasons that weak linkage means "any real definition wins".

That holds for a shared libc and not for a static archive. Once the
linker pulls this member in for another symbol, the weak calloc here
*satisfies* the reference, so it never searches libc.a for musl's
strong one -- and every allocation in the consuming program returns
NULL while free becomes a no-op.

Only the demo could hit it. It is the one build that must pass
-Dsimd=false (highway emits RVV intrinsics that do not compile for
rv64gc), GhosttyZig.zig sets `link_libc = if (cfg.simd) true else
null`, and the guest links the result statically against musl. The host
build links libc, never exported the stubs, and passed everything --
which is why the whole test suite was green over a demo that could not
start a session.

Patch 0002 adds `and builtin.output_mode == .Exe`. The stubs still do
their job in a final link with no libc; a library stops interposing on
the allocator of the binary that owns that choice. Worth sending
upstream: the assumption is upstream's, not ours.
</content>
</entry>
<entry>
<title>vendor: libghostty-vt bedb6f2 -&gt; 3c1ef5b3 (2026-09-01)</title>
<updated>2026-09-02T13:45:32Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-02T13:45:32Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=311979f10132697b990a670c6c99b19c1c33d623'/>
<id>urn:sha1:311979f10132697b990a670c6c99b19c1c33d623</id>
<content type='text'>
Three weeks of upstream: 504 commits, 120 touching the terminal core
-- OSC 5522, kitty relative placements, C0 fixes, the wuffs pixel
path. Rebuilt from ghostty's own dist step (zig build dist
-Demit-lib-vt=true), zig floor unchanged at 0.16.0, and slosh's C
usage compiled unmodified.

Patch 0001 is re-implemented, not retired: upstream rewrote the area
into ImageStorage.clearScreen but kept the behaviour we patch out --
a terminal clear still reclaims transmitted-but-unplaced images,
which breaks the upload-once place-per-frame pattern the protocol's
two verbs exist for. The patch now removes just that sweep; the
placement clearing and orphan reaping stay upstream's. Their recent
'preserve data on unmatched delete' fixes the same class of bug, so
sending ours upstream remains the way to actually retire it.
</content>
</entry>
<entry>
<title>contrib/vendor-check: watching upstream is one command now</title>
<updated>2026-09-02T13:38:38Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-02T13:38:38Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=8c1553801a9812bf4e8541872eb720470ce89a0b'/>
<id>urn:sha1:8c1553801a9812bf4e8541872eb720470ce89a0b</id>
<content type='text'>
Vendoring by pinned commit stays (D12) -- the package channels build
from source archives where submodules are empty, the arch build is
offline-clean because the core is in the tarball, and upstream has no
stable release channel to depend on anyway. What was missing is the
watching: vendor-check reads the pin from vendor.json, asks the
GitHub API what happened since, and lists the commits touching the
terminal core. First run found 120 relevant commits in three weeks,
including upstream fixing the same class of kitty-graphics bug our
patch 0001 fixes -- which is the argument for finally sending it.
</content>
</entry>
<entry>
<title>vendor: an unanchored build/ ignore was eating libghostty-vt's build tooling</title>
<updated>2026-08-24T08:01:26Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-24T08:01:26Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=75774b64ecfdbbfc6df78e34fb489ed21e401386'/>
<id>urn:sha1:75774b64ecfdbbfc6df78e34fb489ed21e401386</id>
<content type='text'>
The build/ pattern matched every directory of that name, not just our
build output at the root -- so vendor/libghostty-vt/src/build/ (the
library's own build.zig helpers) never made it into git, and make
vendor broke on fresh clones. Anchor the ignore to /build/ and restore
the 284 files it had silently dropped.
</content>
</entry>
<entry>
<title>slosh: rename the project from sl0ppty</title>
<updated>2026-08-18T19:26:00Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-18T19:26:00Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=b9e53cace4eb75263077df8623b011e66f5f2241'/>
<id>urn:sha1:b9e53cace4eb75263077df8623b011e66f5f2241</id>
<content type='text'>
sl0p + pty was error-prone to type and the zero made it worse; slosh
(slop + sh) is one syllable, impossible to typo, and slosh.foo is ours.

Mechanical rename everywhere it appears: binary, env vars (SLOSH,
SLOSH_SESSION, SLOSH_BIN, SLOSH_CONFIG), socket dir (/tmp/slosh-&lt;uid&gt;,
$XDG_RUNTIME_DIR/slosh), config path (~/.config/slosh), header guards,
src/sl0ppty.h -&gt; src/slosh.h, contrib/sl0ppty-dev -&gt; contrib/slosh-dev,
the driving-slosh skill, docs and tests. The sl0ppi fork references and
the sl0p theme stay: one is history, the other is the brand.

The rename surfaced a latent bug in test_osc5577: the hello-reply
answer always appeared on screen twice (ECHOCTL echo plus cat -v), but
a seven-character implementation name happened to wrap the second copy
across the 60-column boundary, so counting substrings in wrapped text
found one and passed for the wrong reason. A five-character name moved
the wrap and exposed it. The loop guard itself is correct -- with echo
off before the request there is exactly one reply -- so the test now
counts on de-wrapped text and tolerates the pane's own echo.
</content>
</entry>
<entry>
<title>vendor: keep kitty images across a screen clear</title>
<updated>2026-08-14T21:13:56Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-14T21:13:56Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=d1442bc9550b00080c2f5671fa93eaad67fb0299'/>
<id>urn:sha1:d1442bc9550b00080c2f5671fa93eaad67fb0299</id>
<content type='text'>
libghostty-vt's eraseDisplay called kitty_images.delete(.{ .all = true }) for
ED 2 and ED 3, where the `true` also frees the image *data* of anything no
longer placed. A full-screen program that clears and redraws therefore loses
every image it uploaded, and every later placement of that id draws nothing.

That breaks the half of the protocol worth having. Kitty separates
transmitting an image (`a=t`, stored under an id) from placing it (`a=p`,
put on screen) precisely so a program can upload once and place many times --
which is also why the delete command distinguishes `d=a` (placements) from
`d=A` (placements and data). A screen clear should be the former.

The patch removes only the freeing: placements on the cleared screen still
go, and the image store still bounds itself with its 320MB limit and LRU
eviction on insert -- the mechanism that makes keeping them safe, and that
would be pointless if a clear dropped everything anyway.

Found with a bouncing-DVD screensaver that uploads ten frames up front and
places one per frame. It works in kitty; under us it drew nothing.

D12 said "with a patches file if we ever need one". vendor/patches is that
file, with the reasoning and what a re-vendor has to re-apply; the vendor
json lists it. Worth sending upstream.
</content>
</entry>
<entry>
<title>sl0ptty: M0 — libghostty-vt vendored, one pane, compositor, diff renderer</title>
<updated>2026-08-13T20:00:03Z</updated>
<author>
<name>sl0p</name>
<email>sl0p@sl0p.foo</email>
</author>
<published>2026-08-13T20:00:03Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8'/>
<id>urn:sha1:2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8</id>
<content type='text'>
Design contract in DESIGN.md. libghostty-vt vendored fresh from ghostty
main@bedb6f2 (zig 0.16), built to a 14MB static lib.

M0: pty spawn (no libutil), a lib-vt terminal per pane, a screen cell buffer,
a diff emitter that repaints only what changed, raw mode, SIGWINCH, and a
~120Hz frame cap that coalesces pty reads.

Also the seed of the headless harness: --headless dumps the composited screen
without a tty, so composition is testable in milliseconds.

tests/live_m0.py covers what headless cannot: raw mode, the diff emitter,
resize propagation, and the quit path. 6/6 green.
</content>
</entry>
</feed>
