Adds .loom/cart/current/wal.md as staging for the event log, so conversion moves entries rather than rewriting them. published check is declined on the registry argument rather than on not needing it yet: the command simulates a consumer and a registry with named consumers has real ones, so an observed fetch beats a synthetic probe and building the probe first builds a worse version of what is coming. Two falsifiers recorded — registry never materialising, or registry recording declared consumers rather than observed fetches, since who says they depend on us is not who can actually read us. Dropping it also removes the only thing complicating the credential story, because --as existed almost entirely to serve it. The insight is kept separately because it outlives the command: a check performed with your own credential proves nothing, and whoever builds registry's consumer view needs that before they design it, since the tempting implementation is for the publisher to verify their own publication. Go, for a single static binary with no runtime, on a tool that gets installed on other people's machines and run casually by humans and in loops by agents. Recorded with its own falsifier: if it only ever runs in one or two places, the choice was made on a cost nobody pays. And the consequence — list shells out to git, so git must be on PATH, which makes list the seam if that ever bites. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
4.4 KiB
Write-ahead log — cart marmalade
Staging for .loom/event-log.md. Things decided mid-round that must survive
conversion, written in the shape an entry wants so that converting is a move and
not a rewrite.
This file is not a daily and is not annotated. If something here is wrong, say so in your daily and I will change it.
Declined: published check
Decided: not built. The published noun does not ship; loomctl has
external and, later, beads.
Believed to advance: published check simulates a consumer. A registry
with named consumers has real ones, and an observed fetch beats a synthetic
probe — the probe says a stranger could have fetched it, the registry says
somebody did. Building the probe first is building a worse version of the
thing that is coming.
And it removes the only thing complicating the credential story. --as <context> existed almost entirely to serve this command; without it the config
is one read credential per host, which is where we wanted to land anyway.
Belief that could be shown wrong, two ways:
registrynever materialises. Then nothing ever asks this question, and the failure it catches goes on being invisible.registryrecords declared consumers rather than observed fetches. A declared consumer does not answer the question at all — "who says they depend on us" is not "who can actually read us" — and then this comes back.
What it cost to decide: the command found three real problems in one
afternoon, one of which turned out to be a false positive it would produce
forever. The workaround is one curl. A real need with a cheap workaround is
a gap, not a missing feature.
Keep, even though nothing implements it
The insight outlives the command and belongs in the log on its own:
A check performed with your own credential proves nothing. It helps you complete alone an act that, by definition, you cannot — and then tells you it was fine.
Believed to advance: whoever builds registry's consumer view needs this
before they design it, because the tempting implementation is for the publisher
to verify their own publication, which is the same mistake with a database
behind it.
Measured, and worth keeping with it: /api/v1/user gives the acting login and
the repository gives its owner, so "am I checking as myself" is one request and
not a hard problem. It is a cheap check that nobody thinks to make.
Decided: Go
Decided: loomctl is written in Go.
Believed to advance: this is a tool that gets installed on other people's
machines — a laptop, a cluster node, a CI runner — and a single static binary
with no runtime is the difference between "download it" and "first install a
runtime". The work is HTTP with precise header control, shelling out to git,
and reading files; Go's standard library does the first and third with no
dependencies at all.
Considered: TypeScript on npm. npm i -g is a real distribution channel and
the familiar one. Not chosen because it puts a runtime between the user and a
tool whose whole job is to be run casually and often, including by agents in
loops where start-up cost is paid every time.
Belief that could be shown wrong: that distribution is the deciding
constraint. If loomctl ends up only ever running in one or two places, the
binary advantage is worth little and the choice was made on a cost nobody pays.
Consequence: git must be on PATH
external list shells out to git — clone --filter=blob:none --depth=1 --no-checkout, then ls-tree — rather than using a git library.
Believed to advance: the behaviour we measured across gitea, GitHub and GitLab
is git's behaviour, including --filter support, the silent fallback when a
server refuses it, and the user's existing credential helpers. A library
reimplements all of that and would have to be re-measured.
So the tool has a runtime dependency after all, just not a language one.
list is the only command that needs it — everything else is HTTP — which
makes list the seam if git-on-PATH ever becomes a problem.
Belief that could be shown wrong: that shelling out stays simple. The first
time we need to parse git's output for something it does not print stably, the
library trade looks different.