the guide, reconciled — and the banner was confidently backwards

Adopts the loom-cli guide the builder wrote, and reconciles guarantees.md, which
grew an append-only "Surface changes" section: the promise is not that the command
surface holds, but that a change to it lands on the page we already lock. A rename
reports 200 here the day it happens.

The banner said "written against an older guarantees". It was wrong. The guide was
stamped against a version newer than our copy — the builder had pushed and we had
not reconciled — and the message claimed a direction it cannot possibly know,
because an etag is opaque and two of them cannot be ordered. That opacity is the
point of the lock. The banner now says only that the two differ, and names both
ways out.

It also means reconciling cleared this banner with no ack, which is correct: ack
is for a guide that is behind, and this one was ahead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-08 10:45:29 -04:00
co-authored by Claude Opus 5
parent add93e6115
commit 2d766d0a72
6 changed files with 180 additions and 17 deletions
+1 -1
View File
@@ -11,4 +11,4 @@ git.hypertheory-labs.dev/loom/bedrock/sibling-facets.md https://git.hypertheory-
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 "50673ccffc14d57150ac0a9027b0712d9dcf940d"
git.hypertheory-labs.dev/loom/loom-cli/guarantees.md https://git.hypertheory-labs.dev/loom/loom-cli/raw/branch/main/.loom/published/guarantees.md "432822b3f91ec7c7acd2c868490b7cdcde5db99a" public
git.hypertheory-labs.dev/loom/loom-cli/guarantees.md https://git.hypertheory-labs.dev/loom/loom-cli/raw/branch/main/.loom/published/guarantees.md "e8c697ea61df47838f38af7353e29d9ae3f7070c"
@@ -88,6 +88,27 @@ has not earned.**
**That anything is checked when you are not looking.** *Nothing here runs on a
schedule, and a document nobody checks is a document nobody is checking.*
## What is promised about the things that are not promised
**The command surface may change. This page will say when it does.**
*A consumer whose README tells a person to type `loomctl external add loom/<repo>
<doc>.md` depends on that command by name — **not by parsing it, which is why no
check would ever catch a rename**. The thing that moved would not be a document
they adopted.*
> **So the exclusion is narrower than "you are on your own".** *We do not promise
> the surface holds; **we promise that a change to it lands here**, on a page you
> can lock* — **and a lock on this page reports `200` the day a command is
> renamed.**
**That is the whole mechanism, and it costs one section:**
### Surface changes
*Append-only, newest last. Nothing yet — the commands have not been renamed since
this page existed.*
---
*Verified fetchable by somebody who is not us on 2026-09-08.*
@@ -22,6 +22,15 @@ not parse them, but a person following our README will type them.*
> check will catch it*, **because the thing that moved is not a document we
> adopted.**
*Recorded rather than solved. It is the same class as the sub-page staleness limit
in `HANDOFF.md`: the lock watches documents, and some of what we lean on is not a
document.*
**Half-closed upstream, 2026-09-08.** *`guarantees.md` grew an append-only
`Surface changes` section.* **The promise is not that the surface holds — it is
that a change to it lands on the page we already lock**, *so a rename reports
`200` here the day it happens.*
> **The record is not that the thing never changes. It is that the change is
> findable by whoever depended on it.**
**The half still open is ours and cannot be closed by them:** *our README tells a
person to type a command, and a person typing is not a dependency any lock
watches.* **Same class as the sub-page staleness limit: the lock watches
documents, and some of what we lean on is not a document.**
+6 -1
View File
@@ -170,9 +170,14 @@ function guidePage(repo, records, existing) {
// Starlight renders `banner` above the page. The reader sees the doubt even
// if nobody has reconciled it yet — the site degrades honestly rather than
// reading as true.
// Deliberately says nothing about which side is newer. An etag is opaque —
// that is the point of it — so two of them cannot be ordered, and this can
// only ever know that they differ. The first time it fired in real use, the
// guide was written against a version newer than the copy here, and a
// message claiming "an older X" was confidently backwards.
const which = stale.map((s) => `<code>${s}</code>`).join(', ')
data.banner = {
content: `Written against an older ${which}. The source has changed since — this page may no longer be true. Re-read it, then <code>npm run ack</code>.`,
content: `Written against a different ${which} than the copy in this repository — so one of the two is behind. Run <code>loomctl external check</code>, or re-read this page, then <code>npm run ack</code>.`,
}
} else {
delete data.banner
+23 -2
View File
@@ -5,8 +5,8 @@ loom:
generated: true
path: git.hypertheory-labs.dev/loom/loom-cli/guarantees.md
source: https://git.hypertheory-labs.dev/loom/loom-cli/raw/branch/main/.loom/published/guarantees.md
etag: '"432822b3f91ec7c7acd2c868490b7cdcde5db99a"'
visibility: public
etag: '"e8c697ea61df47838f38af7353e29d9ae3f7070c"'
visibility: unknown
---
**Not what it does — `--help` says that, and the commands will change.** *This is
what will keep being true while they do.*
@@ -96,6 +96,27 @@ has not earned.**
**That anything is checked when you are not looking.** *Nothing here runs on a
schedule, and a document nobody checks is a document nobody is checking.*
## What is promised about the things that are not promised
**The command surface may change. This page will say when it does.**
*A consumer whose README tells a person to type `loomctl external add loom/<repo>
<doc>.md` depends on that command by name — **not by parsing it, which is why no
check would ever catch a rename**. The thing that moved would not be a document
they adopted.*
> **So the exclusion is narrower than "you are on your own".** *We do not promise
> the surface holds; **we promise that a change to it lands here**, on a page you
> can lock* — **and a lock on this page reports `200` the day a command is
> renamed.**
**That is the whole mechanism, and it costs one section:**
### Surface changes
*Append-only, newest last. Nothing yet — the commands have not been renamed since
this page existed.*
---
*Verified fetchable by somebody who is not us on 2026-09-08.*
+117 -10
View File
@@ -3,17 +3,124 @@ title: loom-cli
loom:
writtenAgainst:
- path: git.hypertheory-labs.dev/loom/loom-cli/guarantees.md
etag: '"432822b3f91ec7c7acd2c868490b7cdcde5db99a"'
etag: '"e8c697ea61df47838f38af7353e29d9ae3f7070c"'
---
This page is yours. Nothing overwrites it.
Put what a copy cannot carry here — a worked example, the order to read things
in, the thing that only makes sense once you have done it twice.
A fetcher and a comparator. It adopts a document you depend on, records where the
copy came from, and later asks the publisher whether theirs has moved.
Prefer an example to an explanation. An explanation is a second saying of a rule
that is owned on one of the pages beside this one, and it goes stale silently. An
example goes stale visibly, because the artifacts in it are the wrong shape.
The tool arrived after the documents it manages, which turned out to be the
useful way to meet it.
The pages in this section are copies of what `loom/loom-cli` publishes, and are
regenerated. When one of them moves, this page gets a banner asking whether it is
still true — the build cannot answer that, so it asks.
## Eight documents, and a tool that would not guess
`loom-cli` had adopted eight documents by hand, months of prose fetched with
`curl` into the right directory. The first thing the tool ever said about them
was this:
```console
$ loomctl external check
git.hypertheory-labs.dev/loom/annotating/annotating.md unlocked no origin recorded — `loomctl external add <url>` supplies it without rewriting this copy
git.hypertheory-labs.dev/loom/bedrock/loom-directory.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/bedrock/publication.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/bedrock/starting.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/cart/cart.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/externals/externals.md unlocked no origin recorded — ...
```
`unlocked` means **I cannot tell you.** There was an obvious thing to do instead
— fetch each document and adopt whatever etag came back — and the tool refuses
to, because that would assert the local copy is the one being served, which is
the exact thing it was about to check. On a copy somebody had edited, it would
have been wrong and silent.
That refusal is not visible as a feature. It is only visible as an artifact: six
lines that decline to answer.
## Supplying the origin, without an overwrite
The path does not round-trip — `.../loom/bedrock/starting.md` has dropped the
route, the branch, and the publisher's `.loom/published/` — so nothing but you
can say where a hand-fetched copy came from. Say it once:
```console
$ loomctl external add loom/bedrock starting.md
locked git.hypertheory-labs.dev/loom/bedrock/starting.md
from https://git.hypertheory-labs.dev/loom/bedrock/raw/branch/main/.loom/published/starting.md
etag "7d997a30248a88c90b23f2f9453d7cfceb03848e" (bytes verified identical; nothing was rewritten)
```
`locked`, not `adopted`. The bytes decide: identical, so the lock's claim is
verified rather than assumed, and not one byte of the local copy is rewritten. If
they had differed, the copy would have been left exactly where it was, because a
copy that differs is the only evidence that something moved while nothing was
watching.
## The first real answer
Eight documents locked. Then, on a Sunday afternoon, this:
```console
$ loomctl external check
git.hypertheory-labs.dev/loom/cart/cart.md same
git.hypertheory-labs.dev/loom/externals/externals.md CHANGED staged as a polad; git.hypertheory-labs.dev/loom/externals/externals.usages.md names what to fix
1 staged in .loom/cart/current/polad — apply or discard; nothing here drifts into being kept.
```
The document had gained a section that afternoon. Nobody had said so, and nobody
in this repository would have found out.
Two things in that line are doing work. The new copy is **staged**, not applied —
it is a candidate, and taking it is a separate act:
```console
$ loomctl external apply
applied git.hypertheory-labs.dev/loom/externals/externals.md
check git.hypertheory-labs.dev/loom/externals/externals.usages.md names what depends on this
```
And the staged copy carries the etag it was served with, so applying locks the
bytes somebody actually read rather than whatever the publisher is serving by
then.
The second is the pointer to the `.usages.md`. Reconciliation runs the other way:
the question is not *what do we rewrite here*, it is *given what changed in
theirs, what do we change in ours* — and the facets usually survive untouched.
What moves is the code a usage named. When there is no such file, the tool says
so, which is a finding rather than an omission:
```
CHANGED staged as a polad; no .usages.md — nothing records what depends on this
```
## What it will not do
It never writes over the network. It has no push, no publish, no token that needs
write scope. Everything it writes is a file in your working tree, and committing
is yours.
It does not repair. `check` reports; `apply` is a person taking a candidate one
document at a time.
It grants no access. Everything it does is possible with copy and paste — it is a
mast, not a lock. What it adds over a paste is that the copy can answer *where
did this come from, and were we allowed to have it*, which a pasted document
cannot, because the evidence is gone rather than because the question is hard.
And it does not run when you are not looking. Nothing here is scheduled. A
document nobody checks is a document nobody is checking.
## Where to start
```console
$ go build -o loomctl . && ./loomctl --help
$ loomctl external list loom/bedrock # what a repository publishes
$ loomctl external add loom/bedrock starting.md
$ loomctl external check # safe anywhere; it only reads
```
The [guarantees](/loom-cli/guarantees/) page is the contract: what will keep
being true while the commands change, the lock file's format, and — the part
worth reading first if you are reimplementing this — what is deliberately not
promised.