diff --git a/.loom/event-log.md b/.loom/event-log.md index a0e9ab6..993853d 100644 --- a/.loom/event-log.md +++ b/.loom/event-log.md @@ -48,3 +48,58 @@ workaround goes looking for the gap that justified it and finds nothing.*** *A closed gap is **not** a decline: **a decline is what you considered and did not do; a closed gap is what you needed and got.** Opposite sign, and filing one as the other puts a thing you wanted into a list of things you rejected.* + +--- + +**Decided** (2026-09-07, loom + claude-substrate — `discovered`, `cart: osprey`): +**the path does not record the origin. A lock does**, holding the resolved URL and +the publisher's `ETag`, in `.loom/externals/.locks`. + +**Advances** the one command that has to send a request being able to construct +one. + +**Because** `loom-cli`'s builder tried to run `check` against a real tree and +could not. **The stored path does not round-trip to a URL** — *we hold +`git.hypertheory-labs.dev/loom/externals/externals.md` and the document is served +from `/loom/externals/raw/branch/main/.loom/published/externals.md`.* **It 404s, +measured.** + +**Two segments are dropped and the second is not routing:** + +- *the host's raw route and the branch* — **recoverable only by knowing that + host's URL shape and guessing a branch name** +- **`.loom/published/`** — *which `publication.md` says is the entire contract.* + **So a consumer's tree did not record whether a copy came from a published + surface or from a file its owner may rename at will.** + +*And the short form is worse than incomplete: a host may redirect it to **whatever +the default branch is at the time you ask**, so a lock holding one is locked to a +moving target and a branch rename reports as a change in the document.* + +> **This is the `ETag` mistake one layer down**, and the builder named the +> appetite behind both: ***the design is beautiful when nothing is written +> down**, and both times what made it possible was a property of one host.* + +*Second occurrence, so it is a pattern rather than an incident: **when a design +claims something is derivable and therefore need not be recorded, check whether +the derivation is a fact about the general case or about the host in front of +you.*** + +--- + +**Finding** (2026-09-07, claude-substrate — `cart: osprey`): **gitea's `ETag` +being the blob hash is a migration aid, not a mechanism.** + +*`loom-cli`'s builder ran `check` across eight documents with **no locks at all**, +by hashing local copies and comparing — **the exact thing this convention +forbids** — and it worked, because on this host the two coincide.* + +**It is worth doing once, to lock what was fetched by hand before a tool existed. +It is worth nothing after that**, and it works on gitea only. + +*Recorded because **the next person to notice the coincidence will think they have +found the good idea again**, and there is now a log entry saying it was found +twice and rejected twice.* + +*Seven of the eight were byte-identical to upstream, so this host's raw serving +normalises nothing — **which is a fact about this host and not a licence.*** diff --git a/.loom/published/externals.md b/.loom/published/externals.md index a9bdd86..9641f0e 100644 --- a/.loom/published/externals.md +++ b/.loom/published/externals.md @@ -5,8 +5,20 @@ ## Pull what you use **You fetch a copy of somebody's document and keep it** at -`.loom/externals//.md`. *The path says where it came from, so nothing -has to record an origin.* +`.loom/externals//.md`. + +> ~~*The path says where it came from, so nothing has to record an origin.*~~ +> **This was false and it was load-bearing.** *A stored path is short enough to +> read and therefore too short to resolve: it drops the host's routing, the +> branch, and — worst — the `published/` segment, **which is the whole contract.*** + +**The path is for a person. The origin is recorded in the lock**, resolved: host, +route, branch, and full path. + +*Record the **resolved** URL and not the short form. A host may redirect a short +form to whatever the default branch is **at the time you ask** — so a lock holding +one is locked to a moving target, and a rename of the branch reports as a change +in the document.* **Pull what you need to understand, not everything it depends on.** *A document you fetch may refer to others; follow one when you hit something you do not know. @@ -22,6 +34,21 @@ you fetch may refer to others; follow one when you hit something you do not know > `manifests/ingress.yaml`" is the whole value**, because it answers the only > question reconciliation asks.* +## What a lock holds + +**One record per adopted document, in `.loom/externals/.locks`:** + +- **where it was fetched from** — *resolved, as above* +- **the publisher's `ETag`** — *verbatim* + +**It is committed**, because the thing it locks is committed, and *a lock that +travels separately from what it locks is the drift this is meant to prevent.* + +> **A document with no lock is not broken; it is unlocked.** *Report it and fetch +> again.* **Do not adopt whatever the remote currently serves as the lock** — that +> asserts your copy is the one being served, which is the thing you were going to +> check. + ## Freshness is a conditional request **Locked on the publisher's `ETag`, verbatim — never a hash you compute.** *A