Files
loom-cli/.loom/event-log.md
T
jeffryandClaude Opus 5 d3701c7722 osprey converts: the design is the log, and the cart is gone
The round is over and its artifact is .loom/event-log.md — fifteen entries, each
carrying the belief that could show it wrong, all tagged osprey so it stays
findable what else was in the room.

No spec is written. A spec flattens everything to equal confidence, which is how
the specimen managed to be wrong with a straight face within a day of being
proposed. The specimen is discarded rather than promoted; the story of its being
wrong is in the log, where it can be found, and the artifact would only mislead
somebody who read it without the round beside it.

Reconciles externals.md, which check flagged as the one drifted document of eight.
The new copy carries the 404 row, so the gap filed against it is closed and
externals.gaps.md is deleted — at reconciliation rather than at repair, because a
facet describes the local pair and the gap stayed true of the copy we held until
we fetched. The entry recording that our 404 behaviour is no longer provisional is
the one that would have been easiest to skip and is the reason the log exists.

No shelf: nothing was unresolved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
2026-09-07 13:50:56 -04:00

266 lines
13 KiB
Markdown

# Event log
**Appended, newest last, never revised.** *A later entry supersedes an earlier one
by saying so.*
*Entries tagged `osprey` were all considered in a single sphere of understanding.*
---
## 2026-09-07 — what this tool is `osprey`
**Decided:** *`loom-cli` is a fetcher and a comparator.* **It fetches a document
you depend on and tells you whether the publisher's copy has moved.** *It reports
and never repairs.*
**Believed to advance:** *every act in the loom model is a file in somebody's
repository — publishing is writing one, adopting is fetching a URL, homing a gap
is an `mv`.* **Almost nothing needs a program**, so the program should be the
part that cannot be done by hand: an HTTP request, repeated.
**Belief that could be shown wrong:** *that reporting is enough.* **If every
report is followed by the same manual act, we have moved the work rather than
removed it**, and the missing command will be obvious.
## 2026-09-07 — the design lives here and not in a spec `osprey`
**Decided:** *this log is the artifact of `osprey`.* **No specification document
is written, and the specimen that opened the round is discarded.**
**Believed to advance:** *every entry here carries a belief that could be shown
wrong, so a reader can see which parts are load-bearing and which were guesses.*
**A spec flattens all of it to equal confidence** — *which is how the specimen
managed to be wrong, with a straight face, within a day of being written.*
**Belief that could be shown wrong:** *that a reader can build from a log.* **It
is ordered by time and not by topic**, so somebody arriving reads chronologically
and holds the corrections in their head. *Fine at fifteen entries and not at
eighty. When a newcomer cannot build from it without a guide, the guide is the
next thing to write — and not before.*
## 2026-09-07 — freshness is a conditional request `osprey`
**Decided:** *the tool records the publisher's `ETag`, verbatim and opaque, and
sends it back as `If-None-Match`.* **It never computes a hash of anything.**
**Believed to advance:** *`externals` requires it, and we now have the empirical
reason as well as the stated one.* **On gitea a raw file's `ETag` is its git blob
hash; on GitHub it is not.** *A design that compares a local hash to a remote
`ETag` works on exactly one host by coincidence.*
**Belief that could be shown wrong:** *that `ETag` is stable enough to lock on.*
**A proxy, a CDN, or a host that regenerates the header per request would produce
a change report where nothing changed.** *Untested against anything but gitea and
GitHub.*
## 2026-09-07 — supersedes nothing: the path is for a person `osprey`
**Decided:** *the origin URL is recorded in the lock, not derived from the stored
path.*
**Believed to advance:** *the path `\.loom/externals/<host>/<path>.md` does not
round-trip.* **Measured:** *the document we hold as
`git.hypertheory-labs.dev/loom/externals/externals.md` is served from
`/loom/externals/raw/branch/main/.loom/published/externals.md`* — **the stored
path has dropped the route, the branch, and `.loom/published/`.**
*The third is not routing.* **`publication.md` makes `.loom/published/` the whole
contract**, and a tree that erases it cannot say whether a copy came from
somebody's published surface or from a file they may rename at will.
**Belief that could be shown wrong:** *that people will still read the path as a
location.* **If anybody writes code that parses it back into a URL, the path
should stop looking like one.**
## 2026-09-07 — the lock, and what it holds `osprey`
**Decided:** *one record per adopted document in `.loom/externals/.locks`: the
**resolved** origin URL, and the `ETag` it came with.*
**Believed to advance:** *the specimen said there would be no lock file, on the
strength of the `ETag`-as-blob-hash claim.* **That claim failed twice**, so the
file exists and is named for what it is. *It was briefly called `.etags`, from
when we believed there would be one field.*
**Resolved, and not the short form.** *Measured: gitea `303`s
`/loom/externals/raw/externals.md` to `/raw/branch/main/…`* — **so a lock holding a
short URL is locked to whatever the default branch is at the time you ask**, and a
branch rename reports as a change in the document.
**Belief that could be shown wrong:** *that one file is cheap.* **Two fetches in
one round conflict inside it, and the conflict is in a file no human can resolve
by reading.** *If that bites, it becomes one record per document and the tree is
mirrored twice.*
## 2026-09-07 — unlocked is a state `osprey`
**Decided:** *a document with no lock is reported as unlocked.* **`check` never
adopts whatever the remote is currently serving as the lock.**
**Believed to advance:** *adopting it would assert the local copy is the one being
served, which is the thing you were about to check.* **It is the hash assumption
in a different coat, and it fails silently in the one case that matters — a copy
somebody edited.**
**Belief that could be shown wrong:** *that anybody will run `pull` again to fix
it.* **If unlocked documents simply accumulate, the report is noise and something
has to lock them.**
## 2026-09-07 — `404` is unresolved, and that is no longer provisional `osprey`
**Decided:** *`check` reports a `404` as unresolvable — the document was withdrawn
or we have lost access — and names both readings without picking one.*
**Believed to advance:** *over HTTP they are the same response, because a host
that distinguished them would leak the existence of things you may not see.*
**This entry exists because the status of the behaviour changed and the code did
not.** *It began as a local workaround recorded in a `.gaps.md` against
`externals`, which listed `410` and not `404`.* **`externals` has since added the
`404` row, so the gap is closed and the facet is deleted at this reconciliation.**
> **The workaround is not retired. It is now the specified behaviour.** *Unchanged
> in the code and entirely changed in status — and this log is the only place that
> says so.* **Somebody inheriting this will find the behaviour and go looking for
> the gap that justified it, and find nothing.**
**Belief that could be shown wrong:** *that reporting both readings is useful.*
**If in practice it is always one of them, the report is a ritual** — *and that is
worth knowing.*
## 2026-09-07 — declined: `check` does not resolve the `404` over ssh `osprey`
**Considered:** *the two readings **are** distinguishable over ssh — permission
denied against repository not found — and `externals` now says so.* **Demonstrated
here by accident:** *`loom/settled` returned `404` over HTTP while an ssh clone of
it succeeded.*
**Not done, because:** *it needs a key, a non-default port, and a second
transport* — **and it would be fixing rather than reporting**, which is the rule
this design held all round.
**Belief that could be shown wrong:** *that a person will do it.* **The ssh
disambiguation is one command and it is in the document; if nobody ever runs it,
the ambiguity was never actionable and reporting it was theatre.**
## 2026-09-07 — declined: `init` `osprey`
**Considered and rejected**, not deferred.
**Because:** *its temptation is to scaffold, and four empty directories assert four
things nobody has decided.* **A file that carries no delta should not exist.**
**Belief that could be shown wrong:** *that starting is easy without it.* **If
people repeatedly fail to start**, *the useful version creates one file and asks
one question* — **and creating the tree is still not the feature.**
## 2026-09-07 — declined: worktree, clone; and where a round lives `osprey`
**Decided:** *the cart lives on the default branch; the work is isolated on a
branch named for the cart.*
**Believed to advance:** *a cart is a venue and the work is an artifact.* **`cart`
says three states are visible in a listing, and a branch makes all three
invisible** — *a venue only visible if you know which branch to check out is not a
venue.* **Both dailies land on the default branch, one commit per exchange.**
**Declined: a worktree, and a separate clone.** *Both isolate concurrent working
directories, and `cart` says there is one live cart, ever.* **They solve a problem
the agreement says cannot exist.**
**Belief that could be shown wrong:** *that the dailies and the work have
different audiences.* **If a daily needs to quote a file that only exists on the
branch, the split makes the daily unreadable from where it lives**, and the answer
collapses to one branch for both.
## 2026-09-07 — `publish` is renamed `reachable`, and it earned its place `osprey`
**Decided:** *the command is `loom reachable <path>` — one anonymous request
against a document in `.loom/published/`.*
**Believed to advance:** *the old name said the tool performs publication, which
is the one thing the model says it never does.* **It performs a fetch with a
different subject**, which keeps it inside a fetcher and a comparator.
**It was nearly cut for being a third kind of thing. Then it was validated three
times in one afternoon**, against loom's own repositories:
```
loom/settled 404 anon the page written to fix "settled is private"
jeffry/homelab-cluster 404 anon and bedrock's public starting page named it
as the better answer
loom/.loom 200 anon fetchable — but not where a reader lands
```
**All three are now fixed.** *The third was not a `reachable` failure and is
recorded as the tool's boundary:* **`reachable` answers *can anybody fetch this*
and does not answer *will anybody find it*.** *The second is not testable by a
fetcher and a comparator, and trying is the first step in the tool becoming
something else.*
**Belief that could be shown wrong:** *that publication failures are common enough
to need a command.* **Three for three is a small sample from one publisher in one
week.**
## 2026-09-07 — the `ETag`/blob coincidence is a migration aid `osprey`
**Recorded so it is not rediscovered as a good idea.**
*With eight adopted documents and no locks, `check` was run by hand by hashing the
local copies and comparing to remote `ETag`s* — **the exact thing the convention
forbids** — **and it worked**, because on gitea the two coincide. *It found
exactly one drifted document, correctly.*
**It is worth doing once, on gitea, to lock what was fetched by hand before the
tool existed. It is not a mechanism.**
> **The coincidence has now been found twice and rejected twice.** *The next person
> to notice it will think they have found the good idea again.*
## 2026-09-07 — annotate to ask; write in your own file to assert `osprey`
**Decided:** *responses between two presences are correspondence — each writes in
their own file — and annotation is reserved for asking or challenging.*
**Believed to advance:** *the freeze is not "you cannot edit", it is "you cannot
edit without resolving what was said".* **An annotation creates an obligation**,
which makes it the blocking form and correspondence the non-blocking one.
*And the cost is practical: **dissolving a multi-pass file is expensive**, so the
cost of annotating rises with the length of the thing annotated.* **Annotate
early, or accept the cost when the question is worth blocking on.**
**Belief that could be shown wrong:** *this rule is in neither `cart` nor
`annotating`.* **It is our reading of their text, and `cart` is loom's** — *they
may say we have it wrong.*
## 2026-09-07 — why this tool exists, in one story `osprey`
**Gitea's ssh is on port `2222`.** *I did not know that. I tried to clone, got
`Permission denied (publickey)`, and spent three tool calls and a guess chasing it
as an authentication problem before finding the port.*
**The fact was published.** *`jeffry/homelab-cluster`, in `.loom/published/gitea.md`,
says:*
> **A clone URL without the port will not work**, and the failure looks like an
> authentication problem rather than a wrong port.
**It named my failure before I had it, and I could not read it** — *the repository
was not fetchable by anybody who is not its owner.*
**This happened inside the round that was designing the fix**, *and it failed for
the reason that round had just spent two passes identifying.* **A document that is
correct, published, and unreachable is worth exactly as much as one that was never
written.**
**Believed to advance:** *nothing in this log is a stronger reason for the tool to
exist.* **`reachable` is why the document can be fetched. `pull` and `check` are
why it is still true when you read it.**
**Belief that could be shown wrong:** *that the tool would have helped.* **I would
have had to already depend on that document to have pulled it** — *and the thing I
needed was the one I did not know I was missing.* **A fetcher does not solve
discovery, and this story is partly a discovery problem wearing a freshness
problem's clothes.**