<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slosh.git/contrib, branch docs-new</title>
<subtitle>an opinionated terminal multiplexer in C with programmable pane chrome</subtitle>
<id>https://git.sl0p.foo/slosh.git/atom/contrib?h=docs-new</id>
<link rel='self' href='https://git.sl0p.foo/slosh.git/atom/contrib?h=docs-new'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/'/>
<updated>2026-08-29T13:57:54Z</updated>
<entry>
<title>arch: sign the packages and the database, and say whose key</title>
<updated>2026-08-29T13:57:54Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-29T13:57:54Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=05529c90ff835248f599605f356d679b515eae84'/>
<id>urn:sha1:05529c90ff835248f599605f356d679b515eae84</id>
<content type='text'>
An ed25519 key made for exactly this -- slosh package signing
&lt;slosh@slosh.foo&gt;, 0F67C909938CFFA8A76B59FD8D69B55A0E9056B9 -- signs every
package and both indexes. The public half travels two ways that would both
have to lie: contrib/arch/slosh.asc in git, and /arch/slosh.asc on the
website; the READMEs walk through pacman-key --add and --lsign-key, and the
[slosh] stanza loses its SigLevel override because pacman's default demands
signatures and now gets them.

contrib/arch-repo pins the fingerprint, refuses to run without the secret
key (an unsigned update would make every enrolled pacman refuse the repo),
and now regenerates the index from the directory every time: repo-add skips
an entry whose version it already has, so after a same-version rebuild an
incremental add left the db describing the previous bytes -- a checksum
mismatch for every client. An index rebuilt from disk cannot disagree with
disk. Verified end to end with a scratch pacman keyring: enrolled key
syncs and downloads under Required DatabaseRequired, unenrolled key is
refused at the database.
</content>
</entry>
<entry>
<title>arch: a self-hosted pacman repository, since the AUR is shut</title>
<updated>2026-08-29T13:48:25Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-29T13:48:25Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=bf9b27158d9f66d84c0ca0e481714af4cc63e252'/>
<id>urn:sha1:bf9b27158d9f66d84c0ca0e481714af4cc63e252</id>
<content type='text'>
AUR signups are closed while the AUR deals with supply chain attacks, so
the package is published from our own roof -- which is the better offer
anyway: a pacman repository serves built packages where the AUR hands
every user a rebuild. contrib/aur/ becomes contrib/arch/ (the .SRCINFO
goes; it is AUR metadata, regenerated in a minute when signups reopen),
and contrib/arch-repo builds the package and maintains the slosh.db /
slosh.files indexes in dist/arch/&lt;carch&gt;/, which rsyncs to
/opt/slosh/arch/ on the box. The README and the front page carry the
[slosh] stanza; SigLevel is spelled out because the packages are not
signed yet and pacman defaults to demanding it.
</content>
</entry>
<entry>
<title>aur: a PKGBUILD, building offline from the cgit snapshot</title>
<updated>2026-08-28T14:54:56Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-28T14:54:56Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=6f4f6746963400a21942e02ed80f2107b28d4527'/>
<id>urn:sha1:6f4f6746963400a21942e02ed80f2107b28d4527</id>
<content type='text'>
contrib/aur/ is the upstream copy of the AUR package; the AUR repo gets
these files verbatim on a release, and contrib/release now says so in its
checklist. The source is the cgit snapshot of the tag, which carries the
vendored libghostty-vt -- and every zig dependency in its build.zig.zon is
lazy and unused by the VT-only build (verified against a cold
ZIG_GLOBAL_CACHE_DIR), so the build fetches nothing and is clean in an
offline chroot. prepare() writes pkgver into VERSION because the v0.1.1
snapshot predates the release script that keeps the floor bumped; for
later tags the line writes what is already there.
</content>
</entry>
<entry>
<title>release: one command to bump, commit and tag</title>
<updated>2026-08-28T13:44:01Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-28T13:44:01Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=79df05ec1a3c38751956e8f6b122333ed3737efc'/>
<id>urn:sha1:79df05ec1a3c38751956e8f6b122333ed3737efc</id>
<content type='text'>
contrib/release X.Y.Z moves ./VERSION, commits and cuts the annotated tag
together, so the floor and the tag cannot disagree by construction. It
refuses a dirty tree, a detached HEAD, a malformed or non-increasing
version, and an existing tag; notes passed as the second argument land in
the tag message. It prints the push and `make release` commands instead of
running them, because publishing should be deliberate.

contrib/release --check verifies the invariant (VERSION equals the newest
tag) on its own: `make release` runs it before building anything, and the
new pre-push hook runs the same comparison against the commit a v* tag
points at, so a tag made by hand is caught before it escapes the machine.
</content>
</entry>
<entry>
<title>macos-remote-build: a synced tree must not read as dirty</title>
<updated>2026-08-27T14:40:08Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-27T14:40:08Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=e0abf6b0b98e17cf7cc8e8a81358a6b18ae52f8c'/>
<id>urn:sha1:e0abf6b0b98e17cf7cc8e8a81358a6b18ae52f8c</id>
<content type='text'>
web/ and tests/fuzz/ are excluded from the sync (hundreds of megabytes,
none of it an input to 'make all') but both are tracked, and .git goes
over whole -- so the moment a commit touched web/, the builder's stale
copy read as a local edit and git describe stamped a clean release tree
-dirty. slosh-0.1.1-dirty-macos-arm64.zip was signed, notarized and
correctly labelled as a tree nobody had: the exclusion's debris, not
the release.

After the rsync, restore the excluded tracked paths from the .git that
just went over: no network, no bandwidth lost to the exclusion, and a
tree that is really dirty still says so.
</content>
</entry>
<entry>
<title>slosh(5): the file formats get their manpage; slosh(1) learns shaders</title>
<updated>2026-08-27T13:27:51Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-27T13:27:51Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=b5df6a7b1d73fc9740a077e8eca2d7fc8f6afe60'/>
<id>urn:sha1:b5df6a7b1d73fc9740a077e8eca2d7fc8f6afe60</id>
<content type='text'>
Section 5 is where unix keeps its file formats, and slosh has two
documents sharing one syntax -- the configuration and the layouts -- so
they share a page the way they share a parser. docs/slosh.5 covers the
KDL subset, where the file lives and how reload refuses a broken one,
include and its precedence, every top-level setting grouped the way
config.md groups them, the theme block, the shader vocabulary with the
expression language summarised, the states and their ranking, the keys
block including direct bindings, and the layout schema (tab, pane, and
their properties).

Held to the source like slosh.1 before it: every name in config.c's
KNOWN_TOP -- the list the loader refuses unknown settings against,
itself held to the loader by test_config.py -- must appear in the page,
so a knob cannot be added without this page hearing about it. The pair
must cross-reference each other, and both must be pure ASCII and lint
clean under groff -ww.

slosh(1) grows a SHADERS section -- the one feature a synopsis reader
would never guess a multiplexer had -- and its SEE ALSO now names
slosh(5) and nothing else: the other multiplexers can advertise
themselves.

Install puts the page under share/man/man5, the release tarballs carry
both pages, and the Homebrew formula installs what the commit it is
building has, guarded as before.
</content>
</entry>
<entry>
<title>a manpage: slosh(1), installed, shipped, and held to the source</title>
<updated>2026-08-27T13:17:57Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-27T13:17:57Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=ee5790225261fb3d473a16a365bedc15619f93cc'/>
<id>urn:sha1:ee5790225261fb3d473a16a365bedc15619f93cc</id>
<content type='text'>
The distributables were a bare binary and a directory of Markdown, which
is fine until somebody types 'man slosh' -- the unix-traditional place
to ask. docs/slosh.1 is hand-written man(7), pure ASCII roff, no
toolchain: the synopsis, the options, the session commands, the default
keys, the mouse (including the new drag-past-an-edge scrolling), where
the configuration lives, what SLOSH_* means in a pane's environment,
files, exit status. The prose docs stay the long form; the page says so
and points at them.

'make install' puts it under PREFIX/share/man/man1 (and uninstall takes
it away), the release tarballs carry it beside the LICENSE -- a tarball
is what a packager starts from -- and the Homebrew formula installs it
when the commit it is building has one, guarded because the formula must
be able to build commits older than the page.

Prose about a program drifts unless something holds them together, so
test_docs.py holds the page to the source the way it already holds the
site to docs/nav: every option main.c's parser compares against and
every word command must appear in the page, every SLOSH_* variable the
code reads or sets must be documented, the roff must be pure ASCII (it
travels through implementations that never heard of preconv), and where
groff exists the page must lint clean at CHECKSTYLE=3 with -ww. Adding
a flag without documenting it is now a failing test, which is the only
kind of documentation policy that survives contact with a deadline.
</content>
</entry>
<entry>
<title>macos-remote-build: tolerate notarization ticket propagation lag</title>
<updated>2026-08-27T12:43:02Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-27T12:43:02Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=36dd24325b3a070389d4d45c98dc5822ea9d2c27'/>
<id>urn:sha1:36dd24325b3a070389d4d45c98dc5822ea9d2c27</id>
<content type='text'>
The post-notarization Gatekeeper check ran spctl exactly once, immediately.
A bare CLI binary cannot be stapled (stapler only takes .pkg/.dmg/.app), so
there is nothing on disk to carry the ticket and Gatekeeper must fetch it
online from Apple's CloudKit -- which lags the notary's own 'Accepted' by
seconds to a couple of minutes. The single check raced that propagation and
failed the whole release with 'Unnotarized Developer ID' for a build Apple
had already accepted (status: Accepted), taking the good linux tarballs and
the SHA256SUMS down with it.

Poll spctl instead: pass the instant the ticket appears, and if it still has
not after ~2 min, report it as pending and let the release stand -- the notary
verdict is authoritative and codesign already vouched for the signature. Any
other rejection still fails hard, so a real signing problem is still caught.
The accepted vs pending states are told apart by 'Notarized' vs 'Unnotarized'
so there is no false positive.
</content>
</entry>
<entry>
<title>release: one 'make release' for the three target binaries</title>
<updated>2026-08-26T23:28:45Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-26T23:28:45Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=5ba81343523e7b56a1514f2fc98f47973299b8f4'/>
<id>urn:sha1:5ba81343523e7b56a1514f2fc98f47973299b8f4</id>
<content type='text'>
Streamline the release into a single target that stages all three binaries
in dist/ with a SHA256SUMS:

  linux x86_64  }  cross-built here with 'zig cc -target ... -s', static musl
  linux aarch64 }  (runs on any distro), packaged as a .tar.gz with the binary
                   + README + LICENSE + THIRD-PARTY-LICENSES
  macos arm64      handed to 'macos-dist', which signs/notarizes on the builder

zig is already the compiler, so the two linux cross-builds need no extra
toolchain -- just the vendored libghostty-vt rebuilt per -Dtarget. Verified
both: static, stripped (~2MB), and both run (aarch64 under qemu-user).

Factor the version ladder out of the Makefile into contrib/version, and call
it from both Makefile and Makefile.macos, so the linux tarballs, the signed
zip and the binary's own --version are all named from the same tag instead
of Makefile.macos using its own 'git describe --always' scheme (which would
have named the mac artifact after a bare commit hash while linux used the
tag).

  make release-linux            # just the two linux tarballs
  make release REF=&lt;tag&gt;        # all three + SHA256SUMS
</content>
</entry>
<entry>
<title>version: derive from git tags instead of a hand-bumped constant</title>
<updated>2026-08-26T23:22:34Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-26T23:22:34Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=276ea2610c783bd61789691b910b4be4dbeae890'/>
<id>urn:sha1:276ea2610c783bd61789691b910b4be4dbeae890</id>
<content type='text'>
VERSION was a constant in the Makefile that had to be bumped by hand and
could silently disagree with the git tag a release was cut from. Derive it
instead, with a committed ./VERSION as the floor and no-git fallback:

  on a tag        v0.2.0            -&gt; 0.2.0
  past a tag      v0.2.0-5-gabc123  -&gt; 0.2.0-5-gabc123   (sorts after 0.2.0)
  before any tag  0.1.0-197-g2d1815 -&gt; ./VERSION + commit count + short id
  no .git at all  0.1.0             -&gt; ./VERSION verbatim (cgit snapshot -&gt;
                                       Homebrew source build)
A dirty tree appends -dirty. The commit count keeps 'brew upgrade' ordering
monotonic before the first tag exists.

version.h now bakes just VERSION (dropping the redundant +GITDESC, which the
derived string already carries). contrib/brew-release reads the base from
./VERSION rather than grepping the Makefile's VERSION line, which is now a
$(shell ...) expression it could not parse.
</content>
</entry>
</feed>
