Files
externals/.loom/event-log.md
T
jeffryandClaude Opus 5 101b0280c4 venues moved to bedrock; keep only the sentence about externals
bedrock publishes venues.md now, so the four-line section here had become the
second saying of a rule owned elsewhere.

Kept the one sentence that is genuinely this document's: put a choice where
reconciliation will look for it, because a .usages.md is what somebody opens when
a document moves.

The old heading — "venues, for things you cannot fetch" — was wrong and had been
since it was written. A venue is not defined by being unfetchable, it is defined
by your having decided something. Kafka's documentation is extremely fetchable.

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

191 lines
9.1 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.*
---
## Declined: keeping the venue section
**`bedrock` publishes `venues.md` now**, *so this document's four-line section had
become the second saying of a rule owned elsewhere.*
**Kept: the one sentence that is genuinely about externals** — *put a choice where
reconciliation will look for it.* **That is a claim about `.usages.md`**, *which is
this document's, and it happens to be the sentence that tells you when **not** to
write a venue file.*
*Everything else went, including the "things you cannot fetch" framing.* **That
heading was wrong and had been since it was written:** *a venue is not defined by
being unfetchable — it is defined by your having decided something.* **Kafka's
documentation is extremely fetchable.**