Files
externals/.loom/event-log.md
T
jeffryandClaude Opus 5 9f46b4652a the lock holds visibility, and it says public or not-public
The field shipped in loomctl, so this document was describing a three-column
format that no longer exists.

Access is checked once at fetch and the copy is durable, so an adoption's
legitimacy rested on the relative visibility of two repositories — a fact
recorded nowhere and changeable by a checkbox a year later by somebody who never
saw the adoption.

The design is loom-cli's. Record public or not-public and never private, because
an anonymous request cannot tell two repositories private to different people
apart, and that is exactly the case where private into private widens access.
One request per run rather than per document, since only your own visibility must
be current. Re-check a source only when the alarm would fire, since a stored
visibility decays in both directions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 09:51:49 -04:00

174 lines
8.4 KiB
Markdown

# Event log
**Decisions about this convention.** Appended, newest last, never revised. An
entry states **what was decided, what it is believed to advance, and the belief
that could turn out false.**
---
**Decided** (2026-09-07, loom + claude-substrate — `discovered`, `cart: osprey`):
**`404` is named in the convention as two answers wearing one status**, and a
client reports both readings rather than picking one.
**Advances** a consumer not being told the wrong one of *the document was
withdrawn* and *you no longer have access.*
**Because** it was filed as a gap against this document by `loom-cli`, using this
document's own test — **could you say whose job it is?** *It was ours.* **The
table listed `304`, `200` and `410` and not `404`**, while a host returns `404`
for both readings by design: *one that distinguished them would leak the
existence of things you may not see.*
*Over ssh they **are** distinguishable — permission denied against repository not
found — so a client with both transports should say which it used.*
---
**Decided** (2026-09-07, loom + claude-substrate — `discovered`, `cart: osprey`):
**a facet describes the local pair.** *A gap is true of the copy you hold, not of
the document upstream, so **a publisher fixing their end does not close it.***
**Advances** a consumer's tree never describing a document that is not in it.
**Because** we nearly deleted a consumer's `.gaps.md` on the grounds that the
upstream document had been repaired. **Their copy still lacked the row.** *The
second presence in `osprey` caught it, and the general form follows from the thing
this whole convention rests on — **the copy is theirs and everything beside it is
ours** — which we had not followed through to reconciliation.*
**So a gap closes at reconciliation, not at repair.**
*And the consequence we would not have reached: **what survives is not the gap, it
is what the gap justified.** A workaround is often not retired by a fix — it stops
being a workaround and becomes the specified behaviour, **unchanged in the code
and entirely changed in status.** That change is invisible where the code is, so
it is an entry in the consumer's own log — **otherwise somebody inheriting the
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.***
---
**Decided** (2026-09-07, loom + claude-substrate — `discovered`, `cart: marmalade`):
**do not adopt from a source less readable than the repository you are adopting
into.** *Reference-only, or ask them to publish.*
**Advances** a hazard that this convention creates by construction being named in
it.
**Because** loom saw it while arranging access to a private cluster repository:
***"then you'd have a file from a private repo in your repository, and that
doesn't sound kosher."*** **It is not.**
> **Adopting is copying, and confidentiality does not travel with the copy.**
> *The publisher loses control at the moment of adoption, because visibility is
> governed by the consumer's repository and not by theirs.*
**Nothing in a tree marks a copy as having come from somewhere private.** *A
credential lets you read; it does not let you redistribute, and this convention
had no way to say so.*
*The escape that is usually right: **the thing you needed was almost certainly not
the confidential part.*** **A repository that must stay private can have a public
sibling that publishes**, and the split usually follows a line that already
exists: *the operational tree — inventories, versions, topology — is what is
sensitive; the pages telling somebody what to decide are not.*
*Recorded as a general rule rather than a case, because the failure is silent and
one-way: **once copied into a public tree it is published**, and no later fix
retrieves it.*
---
## The lock grows a fourth column: visibility
**Decided.** *A lock record is now `path`, `url`, `etag`, `visibility`* — **and
the value is `public` or `not-public`, never `private`.**
**What it advances:** *the confidentiality rule stops depending on somebody
remembering it.* **Access is checked once, at fetch; the copy is durable and was
never asked about again** — *so the adoption's legitimacy rested on a fact
recorded nowhere and watched by nothing.*
**Whose it is:** *the question was Jeff's, asking whether he had overreacted on
private sources — he had not, but the rule was already narrower than he
remembered.* **The design is `loom-cli`'s**, *including the three parts I did not
have:* **`not-public` rather than `private`** *because an anonymous request cannot
distinguish two repositories private to different people, which is the case that
actually widens access;* **one request per run rather than per document**, *since
only your own visibility must be current;* **and re-checking a source only when
the alarm would fire**, *since a stored visibility decays both ways.*
**Declined: refusing the adoption.** *`loomctl` warns and proceeds.* **Two
repositories private to different people cannot be told apart from outside**, *so
a refusal would be wrong exactly as often as it was right.*
**The belief that could turn out false:** *that recording a coarse answer is
better than recording none.* **If people read `not-public` as `private`, the lock
is now a claim it cannot support** — *the wording in the document is the only
thing preventing that, which is thin.*
## Declined: documenting the field before it shipped
*The field was agreed in cart `sorrel` and this document was left wrong for a
day.* **Documenting a format that does not exist yet is the same mistake as
publishing into a repository nobody can read** — *it passes every check available
to the writer.*