Jeff's correction breaks published check rather than denting it. homelab-cluster publishes six documents and is private deliberately; publication.md says others, not everyone, and I read one word as the other. The tool as logged would have reported a correct repository as broken, so a superseding entry is added rather than revising the osprey entry. What survives is that bedrock's public page promising a private repository as the better answer was a real defect, and it was never about homelab-cluster. So published check must not report a verdict. It reports the identity it used, and warns when that identity is the repository's own owner — publishing is not an act you can complete alone, and a tool that verifies with your own credential has helped you complete it alone and told you it was fine. Also corrects me: I confirmed the specimen's token claim enthusiastically without testing the case that would show it wrong. A refused write names the token's scopes in the error body, so a token cannot be asked what it may do but can be told by being refused. Verified that no other channel exists — the tokens endpoint rejects token auth, and no scope header comes back on success. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
325 lines
16 KiB
Markdown
325 lines
16 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.**
|
|
|
|
## 2026-09-07 — supersedes the `reachable` entry: publication is not publicness `marmalade`
|
|
|
|
**The entry above records three publication failures found by `reachable` and says
|
|
all three are fixed. One of them was not a failure.**
|
|
|
|
**`jeffry/homelab-cluster` is private on purpose** — *it describes a running
|
|
cluster, and its owner does not want outsiders reading what is on it.* **It
|
|
publishes six documents to an audience that is not the public**, *which
|
|
`publication.md` permits in the word we misread:*
|
|
|
|
> **What a repository has handed over for **others** to depend on.**
|
|
|
|
***Others*, not *everyone*.**
|
|
|
|
**So the tool as logged would have reported a correct repository as broken.** *An
|
|
anonymous fetch returning `404` is the intended outcome there*, **and a check that
|
|
treats anonymous reachability as success produces a false positive on every
|
|
deliberately-private publisher.**
|
|
|
|
**What survives:** *the defect that round found in `bedrock/starting.md` was real,
|
|
and it was never about `homelab-cluster`.* **A public document promised that a
|
|
private repository was the better answer**, *and the promise was the defect.*
|
|
**The link was removed; naming it as private, the way `.loom` names `settled`,
|
|
would also have answered it and would have kept the better document findable.**
|
|
*That call is loom's and it is already made.*
|
|
|
|
**Believed to advance:** *a check that cannot fail teaches nothing, and one that
|
|
fails on correct repositories is worse* — **it trains people to ignore it.**
|
|
|
|
**Belief that could be shown wrong:** *that anonymous is still the right default.*
|
|
**If most publication here is to private audiences, the default is wrong** and the
|
|
command should refuse to run without being told who to ask as.
|
|
|
|
## 2026-09-07 — measured: a read token, and what a host will tell you `marmalade`
|
|
|
|
**A gitea read token was issued for one session and destroyed after.** *Recorded
|
|
because these are facts about the host that nothing else here writes down.*
|
|
|
|
**A read token authenticates raw HTTP on a private repository.** *`404`
|
|
anonymously, `200` with `Authorization: token` or `Bearer`, and `If-None-Match`
|
|
returns `304` authenticated.* **So `add` and `check` work against private
|
|
repositories** — *the assumption the specimen made and nobody had run.*
|
|
|
|
**`/api/v1/repos/{o}/{r}` reports `admin, push, pull: true` for a token that
|
|
cannot write.** *Those are the account's rights.*
|
|
|
|
**But a refused write names the token's scopes in the error body.** *So:*
|
|
|
|
> **A token cannot be asked what it may do. It can only be told, by being
|
|
> refused.**
|
|
|
|
*Supersedes the specimen's "the name is the only record", which was too strong.*
|
|
**For this tool the rule is unchanged and the reason is different:** *`loomctl`
|
|
never writes, so it never provokes the only response that would tell it anything.*
|
|
|
|
**Belief that could be shown wrong:** *that gitea keeps doing this.* **The scope
|
|
list in an error body is not a documented interface** — *it is a message, and
|
|
messages change.*
|