Compare commits

...
2 Commits
Author SHA1 Message Date
jeffryandClaude Opus 5 a5093c1efc compact the event log: six dropped, fifty kept, and the result is the finding
recording-decisions now permits compaction and names four kinds that may never be
dropped. Applying it removed six entries and left fifty, and the ratio is worth
more than the saving.

Every entry dropped became droppable by being published. what this tool is, the
lock format, unlocked is a state, --help as the documentation surface, and the
visibility field all now live in .loom/published/guarantees.md or README.md, and
conversion-destroys lives in cart/v2 and cart.usages.md. Nothing was summarised
away — the content moved into documents somebody else can lock, which is a stronger
place for it than a log only we read. The entry names each one and where it went,
so the compaction is auditable rather than trusted.

What did not compress is the point. Almost everything left is a decline, a
measurement, a supersession, or a belief shown wrong. Declines are not recoverable
from code because the code is what they are absent from; measurements are facts
about other people's systems that no artifact here holds; supersessions are changes
of mind, which is most of what a reader wants. The log is long because the work was
exploratory, not because it was padded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
2026-09-08 10:49:41 -04:00
jeffryandClaude Opus 5 045924ec36 tansy converts: three entries, no shelf
Publishes what the tool guarantees, on a condition that fired rather than a
decision reversed. Records the narrower promise that replaced promising the command
surface — a change to it lands on the page consumers already lock, so a rename
reports 200 the day it happens.

And records a limit found by accident that follows from a guarantee rather than
from anybody's code: an ETag is opaque, we promise never to interpret one, so two
of them can be compared and never ordered. A consumer can know two versions
disagree and can never know which is behind. Anybody building freshness on this
inherits it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
2026-09-08 10:48:47 -04:00
3 changed files with 135 additions and 96 deletions
+113 -95
View File
@@ -7,21 +7,6 @@ by saying so.*
---
## 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
@@ -72,40 +57,6 @@ somebody's published surface or from a file they may rename at will.
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
@@ -450,16 +401,6 @@ unknown.**
next token*, **and because if a read scope is not enough, that is the only argument
for keeping ssh.**
## 2026-09-07 — `--help` is the documentation surface `marmalade`
**Decided:** *`--help` is what a person or an agent actually runs when handed an
unfamiliar CLI, so it is the surface that has to be good* — **say what a command
does and what it will not do.**
**A `.loom/published/` for `loomctl` is deferred, not declined.** *The distinction
matters because `init` was declined.* **It earns publication when somebody depends
on this tool's behaviour rather than reading its help.**
## 2026-09-07 — decided by fallback: where the credential lives `marmalade`
**Nobody chose this; the fallback became the decision and that is recorded so it
@@ -789,21 +730,6 @@ designed to be ephemeral is the first step in it not being ephemeral.**
unit.* **If two presences ever work from different machines, the cart has nowhere
to live**, *and everything above stops being true at once.*
## 2026-09-07 — conversion now destroys, so the log is the only record `quince`
**Under `cart/v1` the cart is untracked, so converting a round deletes its dailies
outright.** *Every previous conversion left them in git.*
**So an entry that was not written before the `rm` is gone**, *and the write-ahead
log is the mechanism* — **stage as you go, because at conversion the cart is the
only copy and you are about to delete it.**
**And it sharpens a conflict recorded in `cart.usages.md`:** *the annotation
protocol here says commit before dissolving because git is the only archive.*
**With an ignored cart there is no archive, so dissolving a notes file destroys
the annotations outright.** *Both documents are loom's; this is where an adopter
can see the collision.*
## 2026-09-07 — declined for now: reference-only adoption `quince`
**`externals` offers two ways out of the confidentiality rule.** *We implement
@@ -1041,27 +967,6 @@ it wrong.*
configured one.* **It only pays if it is the same everywhere**, *which is not ours
to decide and is with `bedrock`.*
## 2026-09-08 — the lock records visibility, and the word it will not use `sorrel`
**Decided:** *the lock carries what the source could be read as when it was
fetched, and `check` audits it against this repository's visibility now.*
**Believed to advance:** *access is verified once, at fetch, and the copy is
durable.* **Whether an adoption is still legitimate rests on the relative
visibility of two repositories — a fact somebody can change with a checkbox a year
later, without ever seeing the adoption.** *Recording it turns a silent permanent
hazard into something that runs.*
**The value is `public` or `not-public`, and never `private`.** *An anonymous
request tells those two apart and nothing finer* — **so it cannot see two
repositories private to different people, which is the case where adopting between
private repositories genuinely widens access.** *The word `private` would claim
precision the signal does not have.*
**Belief that could be shown wrong:** *that the coarse signal is worth having.*
**If the cases that matter here are all private-to-private, this alarm will never
fire and the field is ceremony.**
## 2026-09-08 — a probe is not a fetch, and confusing them clears alarms `sorrel`
**Recorded because the bug was one line and the trap is permanent.**
@@ -1092,3 +997,116 @@ three times, and then declined.*
*Recorded as a working note rather than a decision: **when a word could be read
narrowly or broadly, this repository has evidence that I pick narrow.***
## 2026-09-08 — published: what the tool guarantees `tansy`
**`.loom/published/guarantees.md`**, *and step 4 of `publication` was run: `200`
anonymously, off no credential of ours.*
**The earlier decision did not reverse; its condition fired.** *`.loom/published/`
was recorded as deferred rather than declined, on the condition that somebody
depends on the tool's behaviour rather than reading its help.* **A docs site whose
build calls `add`, `check` and `apply` is that consumer.**
*The delta is not the command list — that is a copy of what the code owns.*
**`--help` says what the tool does; a published page says what will keep being
true**, *and a reader cannot learn from a binary which of its behaviours survives
the next version.*
**The page includes what is not promised**, *which is the half a reimplementation
needs most:* **the command surface, the orientation file's format across
versions, the precision of the visibility signal, and that anything is checked
when nobody is looking.**
## 2026-09-08 — we do not promise the surface; we promise the change lands `tansy`
**A consumer's README tells a person to type `loomctl external add loom/<repo>
<doc>.md`.** *Nothing parses it — which is exactly why no check would catch a
rename.* **The thing that moved would not be a document anybody adopted.**
**Promising the surface would freeze the CLI. So the promise is narrower and
runs:**
> **We do not promise the surface holds. We promise a change to it lands on the
> page you already lock.**
*`guarantees.md` carries an append-only `Surface changes` section*, **so a rename
reports `200` to every consumer the day it happens.**
**Belief that could be shown wrong:** *that anybody remembers to write in it.*
**Nothing enforces the section***the same weakness as a facet nobody updates.*
## 2026-09-08 — two ETags can be compared and never ordered `tansy`
**Found by accident, and it is a consequence of a rule we published this
morning.**
*The docs site stamped a hand-written guide with the `ETag` it was read against,
and its banner said `written against an older guarantees`.* **It was backwards:
the guide was ahead of the site's copy, not behind.**
**And it cannot be fixed by trying harder.** *An `ETag` is opaque — that is the
point of it, and we guarantee we never interpret one.* **So a consumer can know
that two versions disagree and can never know which is behind.**
*The banner now claims no direction.* **Anybody building freshness on this
inherits the same limit**, *and it belongs in the log because it follows from the
guarantee rather than from anybody's code.*
*Consequence nobody predicted: reconciling cleared the banner with no
acknowledgement, which is correct — an acknowledgement is for a guide that is
behind, and this one was ahead.*
## 2026-09-08 — compacted, and it barely compressed `tansy`
**A compaction is itself a decision, so this is the entry `recording-decisions`
asks for.** *Six entries dropped, fifty kept. The uncompacted log is in git
history, which is where a reader who needs it goes.*
**Dropped, each because a competent reader can now recover it from the artifact,
and here is which artifact:**
- *`what this tool is`* — **`.loom/published/guarantees.md` and `README.md`**
- *`the lock, and what it holds`* — **`guarantees.md` documents the format**
- *`unlocked is a state`* — **`guarantees.md`, and `add` refuses in code**
- *`--help is the documentation surface`* — **`README.md` says so and points there**
- *`the lock records visibility, and the word it will not use`* — **`guarantees.md`
carries the field and the refusal of the word `private`**
- *`conversion now destroys, so the log is the only record`* — **`cart/v2`, adopted
here, and `cart.usages.md` names `wal.md` as the mechanism**
> **Every one of them became droppable by being published.** *Nothing was
> summarised away; the content moved into a document somebody else can lock, which
> is a stronger place for it than a log only we read.*
## What did not compress, and why that is the finding
**Fifty entries survived, and the reason is the rule rather than sentiment.**
*Almost all of them are one of the four kinds that may never be dropped:*
**Declines** — *`init`, `published check`, a separate `adopt` verb, a plugin
boundary, an audience declaration, reference-only adoption, resolving `404` over
ssh, a second orientation file, worktrees, a spec, fixing `annotating`.* **Not one
is recoverable from the code, because the code is what they are absent from.**
**Measurements** — *the `ETag` is a blob hash on gitea and not on GitHub; three
hosts and one partial clone; only gitea resolves its own short raw URL; a refused
write names the token's scopes; a private repository over HTTPS with a read
token.* **Facts about other people's systems, which no artifact here holds.**
**Supersessions** — *publication is not publicness; a cart is not committed; `add`
does not replace; `git` is not needed for `list` only; the private path is
exercised.* **Each is a change of mind, which is most of what a reader wants.**
**Beliefs shown wrong** — *the specimen's hash-as-lock; `others` read as
`everyone`; a probe treated as a fetch; a banner that claimed a direction two
opaque strings cannot support.*
> **The log is long because the work was exploratory, not because it is padded.**
> *A project that mostly built things would compact to a page. This one mostly
> found out it was wrong about things, and that is the part the code cannot
> hold.*
**Belief that could be shown wrong:** *that fifty is readable.* **It is today.**
*The next remedy is not another compaction — it is the guide `bedrock` needed,
and it is not needed yet.*
+1 -1
View File
@@ -11,4 +11,4 @@ git.hypertheory-labs.dev/loom/bedrock/recording-decisions.md https://git.hyperth
git.hypertheory-labs.dev/loom/bedrock/sibling-facets.md https://git.hypertheory-labs.dev/loom/bedrock/raw/branch/main/.loom/published/sibling-facets.md "a46446a34ccb8bfc533d3cce19f4c88548c4fa04" public
git.hypertheory-labs.dev/loom/bedrock/starting.md https://git.hypertheory-labs.dev/loom/bedrock/raw/branch/main/.loom/published/starting.md "b9eefba0f4668a496ccfc6a1377277f0721456d2" public
git.hypertheory-labs.dev/loom/cart/cart.md https://git.hypertheory-labs.dev/loom/cart/raw/branch/main/.loom/published/cart.md "15331f1a9cc81bf61a44830cfbb7c274f4c2b119" public
git.hypertheory-labs.dev/loom/externals/externals.md https://git.hypertheory-labs.dev/loom/externals/raw/branch/main/.loom/published/externals.md "a7586eb52caf275d9bcedbbd8042c43e5aaad0b9" public
git.hypertheory-labs.dev/loom/externals/externals.md https://git.hypertheory-labs.dev/loom/externals/raw/branch/main/.loom/published/externals.md "50673ccffc14d57150ac0a9027b0712d9dcf940d"
@@ -62,6 +62,7 @@ what to decide are not.**
- **where it was fetched from** — *resolved, as above*
- **the publisher's `ETag`** — *verbatim*
- **the visibility the source could be read at, when it was fetched**
**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.*
@@ -71,6 +72,26 @@ travels separately from what it locks is the drift this is meant to prevent.*
> asserts your copy is the one being served, which is the thing you were going to
> check.
### Why visibility is in the lock and not left to the moment
**Access is checked once and the copy is durable.** *A token gets you the read;
nothing revisits it afterwards.* **So the adoption's legitimacy rests on the
relative visibility of two repositories — and that is changeable by a checkbox, a
year later, by somebody who never saw the adoption.**
> **Record `public` or `not-public`. Never `private`.** *An anonymous request can
> tell you a repository is not public. It cannot tell two repositories private to
> **different people** apart* — **which is exactly the case where private into
> private genuinely widens access.** *Record the word you can verify.*
**Checking it costs one request per run, not one per document**, *because the only
thing that must be current is **your own** visibility.* **Re-check a source only
when the alarm would fire** — *you are public, it was recorded not-public* — *and
if it has since gone public, update the lock and say nothing.*
*A stored visibility decays in both directions, which is why the alarm re-checks
rather than trusting the record.*
## Freshness is a conditional request
**Locked on the publisher's `ETag`, verbatim — never a hash you compute.** *A