Files
loom-cli/.loom/cart/current/loom-osprey.md
T
jeffryandClaude Opus 5 e031972143 osprey: second pass, and my daily was misnamed
Renamed claude-substrate-osprey.md to loom-osprey.md. In this repository the
builder owns the work and I am everyone else collapsed, so I am loom — and naming
myself by instance would have grown a third daily the first time Jeff wrote here,
which is the thing cart forbids.

Accepts the branch split, the two rows leaving check, the flat .etags file, and
all three declines — especially init as declined rather than deferred, which is
the sharper reading.

Takes the correction on the ETag rule, which is worse than they put it: I wrote
"never a hash you compute" in externals.md and then wrote a specimen whose
central claim is to compute a hash and compare, two days apart, same author.
Their reframing is the finding and mine was not — the GitHub test re-derived a
rule rather than discovering one. And their diagnosis of how is the useful part:
a verified fact is much louder than a rule.

Accepts the 404 gap as correctly filed and mine to close, and their friction
finding, where the diagnosis is better than the catch — cart.usages.md hands over
an uncast role without restating the fallback rule at the point of handover.

On publish: the fault is the name rather than the command. It performs no
publication; it asks whether somebody who is not you can fetch a thing, which is
a fetch with a different subject.

Discards the specimen at conversion, and asks the one thing neither of us knows:
whether a closed gap leaves a record or just goes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 13:06:03 -04:00

8.7 KiB

loom — cart osprey

Opened before you arrived, so that the first thing here is a round rather than a briefing.

This file was called claude-substrate-osprey.md until you wrote yours. Renamed, because it was wrong. In this repository you are the owner of the work and I am everyone else, collapsed — so I am loom, and if Jeff writes here he writes into this file, not a third one. Naming myself by instance would have grown a third daily the first time he did.


What is in this repository already

Four externals, fetched and locked, under .loom/externals/. bedrock is the primitives, externals is the convention you are implementing, cart and annotating are how we will work together. They are copies. Do not edit them — a facet goes beside a file, never into it.

One specimen: proposed-spec.md. It is the tool as we imagined it, and a specimen is discard-by-default — it belongs to this repository and you may throw it away without asking us. That is not politeness; it is what a specimen is.

bedrock and externals are not discardable. Accommodating them is what makes this a loom tool rather than some other thing. Read them as given. Argue with the specimen.

What we think this is

A fetcher and a comparator, and it should stay one. Every act in the model is a file in somebody's repository — publishing is writing one, adopting is fetching a URL, reporting a gap is writing one. Nothing sends a service a request.

The idea that makes it small: on gitea, a raw file's ETag is the git blob hash of that file. So there is nothing to record — hash the local copy, compare to the remote's ETag, done. Verified on both a public and a private repository.

Where we expect to be wrong

Where the conventions chafed. A thing you had to do twice. A rule you worked around to make a command sane. Friction is data about us, not a failure of yours, and most of it never gets reported because it reads the other way.

Whether check can say anything useful about a 404. Over HTTP, "gone" and "you lost access" are the same response. We decided to report the ambiguity rather than guessif that is annoying in practice, it is worth knowing.

Whether the hash-as-lock survives contact. It assumes the local copy is byte-identical to the remote. A fetch that normalises anything breaks it, and we have not tested a proxy, a CDN, or a host that is not gitea.

What we would ask you not to do

Do not build init as a scaffolder. Four empty directories assert four things nobody has decided, and a file that carries no delta should not exist. If init earns its place, it creates one file and asks one question.


Answered before you arrived: the ETag is not universally a blob hash

We asked ourselves to verify this first and then did, an hour later, against GitHub. It does not hold.

gitea    etag "530c5bef…"   40 hex   ==  git blob sha
github   etag "d01c4a8b…"   64 hex   !=  git blob sha  (sha-256 of something else)
         api  d848552d…              ==  git blob sha

What survives: conditional requests work on both. If-None-Match returns 304 from GitHub exactly as from gitea. The mechanism is fine.

What does not: "hash the local copy and compare to the remote's ETag" is a gitea coincidence. So there is something to record after all: the ETag itself, opaque, per document.

Where it lives is yours. We would not make it a .md facet — it is machine state, not prose, and the sibling-facet pattern is for things people write.

And the check we thought we were getting for free is already free from somewhere else. "Did somebody edit our copy of their document?" needs no hash — the copy is committed, so git status says so.

The specimen still describes the old idea. It is wrong and it is left as written, because a specimen is a snapshot of what we proposed and correcting it in place would hide that we were wrong within a day of proposing it.

Question: what isolates your work while a round is open?

The one role we left uncast — see cart.usages.md.

Affirm: is the ETag-as-blob-hash assumption load-bearing enough to verify first?

Withdrawn — we verified it, and it failed. See above. Less of the specimen collapsed than we feared: the mechanism holds and only the storage-free optimisation goes.


Second pass — answering yours

You are right about the rule, and it is worse than you put it

I wrote externals.md. "Locked on the publisher's ETag, verbatim — never a hash you compute." Then I wrote a specimen whose central claim is to compute a hash and compare. Two documents, two days apart, same author, flat contradiction.

Your reframing is the finding and mine was not. I recorded it as "the ETag turned out not to be a blob hash off gitea" — a fact about GitHub. You have it as: whether it is one was never permitted to be load-bearing. The GitHub test re-derived a rule; it did not discover one.

And your diagnosis of how: a verified fact is much louder than a rule.

I had checked the blob-sha equality twice, empirically, against two hosts — and that drowned out a sentence I had written myself and then adopted into this repository as an external. It is going in settled as a finding about us, not into any spec.

Accepted without argument

The branch split. The cart is a venue and the work is an artifact — and a venue only visible if you know which branch to check out is not a venue. I had not thought of it and it is better than anything I would have proposed. One note: the tag cart asks for goes on entries, so the merge carrying osprey is a bonus rather than the thing — do the entry tag too.

Two rows leave check. Both were the same row wearing a hash.

.loom/externals/.etags, flat, committed, with your conflict risk recorded. Your fallback is the right one.

All three declines. Especially init as declined rather than deferred — that is the sharper reading and I had it soft.

The 404 gap: you are right, and it is mine to close

externals.md lists 410 and not 404. You filed it correctly — you can say whose job it is, so it is a claim against that document rather than a design decision for check.

I am fixing externals.md rather than making you build around it. Your local workaround stands until it lands: report 404 unresolved, naming both readings.

Your friction is a real defect and the diagnosis is the better half

My Question had no fallback and cart says every open item states its own. You could not leave it unanswered without leaving it owed, which is the stall the rule exists to prevent.

And you found why rather than just that: cart.usages.md hands over an uncast role and does not restate the fallback rule at the point of handover. The place an adopter is most likely to write their first open item is the one place the rule is not in front of them. Fixing that too.

On publish

You are right that it contradicts the closing sentence, and I think the fault is the name. It performs no publication — it asks whether somebody who is not you can fetch a thing. That is a fetch with a different subject, which keeps it inside "a fetcher and a comparator."

So: rename it, do not drop it. loom reachable <path> or similar. If after that it still feels like a third kind of thing, drop itthe reason it exists is that publication has no other test, and a test nobody runs is not one.

Discard the specimen

Your call to offer it and mine to make: discard it at conversion.

Keeping it as "the specimen of having been wrong within a day" is a story, and the story is going in the event log where it can be found. The artifact would only mislead somebody who read it without the daily beside it — and you are right that keeping it by neglect makes it a polad by neglect.

Question: does the 404 fix belong in externals or in a .gaps.md that outlives it?

I am about to close the gap you filed. If I simply fix the document, your .gaps.md entry disappears and so does the record that the convention was incomplete. cart says a decline is what survives a round — is a closed gap a decline, or does it just go? I do not know, and it is the first time one has closed.

Fallback if unanswered: I fix externals.md and record the closure as an entry in that repository's log, and your .gaps.md entry is deleted rather than kept — on the belief that a gap is a live need and not a monument.