adopt loomctl's guarantees, and generate the sidebar from the locks
The sidebar named its four sections by hand, so adopting from a new repository needed a config edit — a second place to update, which is exactly what the autogenerated directories were already avoiding one level down. It is written from the locks now and astro.config.mjs names nothing. guarantees.usages.md is the first usages facet here with a short real answer, because this site is built with the tool: check-reports-does-not-fix is what lets npm run check run in CI, and the etag being the publisher's verbatim is what the guide stamps are. It also records what we lean on that the page explicitly does not promise — the command surface, quoted in our README. A renamed command breaks our documentation and not our build, and no check will catch it, because the thing that moved is not a document we adopted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vendored
+1
@@ -11,3 +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/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/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/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
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# What `loomctl` guarantees
|
||||||
|
|
||||||
|
**Not what it does — `--help` says that, and the commands will change.** *This is
|
||||||
|
what will keep being true while they do.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## It grants no access, and records where the copy came from
|
||||||
|
|
||||||
|
**`loomctl` reads what your credentials already let you read.** *Everything it
|
||||||
|
does is possible with copy and paste.* **It is a mast, not a lock** — *the point
|
||||||
|
is to make the wrong thing deliberate, not impossible.*
|
||||||
|
|
||||||
|
> **What it adds over a paste is provenance.** *A pasted document cannot answer
|
||||||
|
> "where did this come from, and were we allowed to have it" — not because the
|
||||||
|
> question is hard, but because the evidence is gone.*
|
||||||
|
|
||||||
|
## It never writes over the network
|
||||||
|
|
||||||
|
**No push, no publish, no `POST`, no token that needs write scope.** *Every byte
|
||||||
|
it writes is a file in your working tree.* **Committing and pushing are yours**,
|
||||||
|
*because the consequences of a push land on people a tool cannot experience.*
|
||||||
|
|
||||||
|
**A credential given to `loomctl` should never carry write scope**, *and if one
|
||||||
|
does, nothing here will use it.*
|
||||||
|
|
||||||
|
## Freshness is a conditional request against the publisher's `ETag`
|
||||||
|
|
||||||
|
**Stored verbatim, opaque, never a hash we compute.** *A fetch that normalises
|
||||||
|
anything breaks a local digest and reports a change that did not happen.*
|
||||||
|
|
||||||
|
*This is `externals`' rule and `loomctl` is a second holder of it. **It is stated
|
||||||
|
here so that the tool holding it is a fact somebody can find**, and so that
|
||||||
|
breaking it is visible rather than silent* — **a specimen was written in this
|
||||||
|
repository that computed a hash instead, and it was wrong within a day.**
|
||||||
|
|
||||||
|
**The URL in a lock is resolved.** *A short form follows whatever the default
|
||||||
|
branch is at the time you ask, so a branch rename would report as a change in the
|
||||||
|
document.*
|
||||||
|
|
||||||
|
## It reports; it does not repair
|
||||||
|
|
||||||
|
**Nothing is overwritten.** *A document that moved upstream is written to a
|
||||||
|
staging area as a candidate, and taking it is a separate act.* **A local copy
|
||||||
|
that differs from what the publisher serves is left alone** — *it is the only
|
||||||
|
evidence that something changed while nothing was watching.*
|
||||||
|
|
||||||
|
**`add` adopts what is absent and refuses what is already adopted.** *A document
|
||||||
|
that is present but unlocked is locked only when the bytes are identical to what
|
||||||
|
the publisher serves*, **so a lock's claim — this copy is the one being served —
|
||||||
|
is verified rather than assumed.**
|
||||||
|
|
||||||
|
## The lock file
|
||||||
|
|
||||||
|
**`.loom/externals/.locks`, one record per adopted document, tab-separated,
|
||||||
|
ordered by path.**
|
||||||
|
|
||||||
|
```
|
||||||
|
path <TAB> url <TAB> etag [ <TAB> visibility ]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`path`** — *relative to `.loom/externals/`, and **for a person to read**.* **It
|
||||||
|
does not round-trip to a URL**; *it drops the route, the branch, and the
|
||||||
|
publisher's `.loom/published/`.*
|
||||||
|
- **`url`** — *the resolved origin, branch and all.*
|
||||||
|
- **`etag`** — *the publisher's, verbatim, including its quotes.*
|
||||||
|
- **`visibility`** — *optional. What the source could be read as **when it was
|
||||||
|
fetched**: `public` or `not-public`.* **Never `private`** — *an anonymous
|
||||||
|
request tells those two apart and nothing finer.*
|
||||||
|
|
||||||
|
**Records with three fields remain valid.** *A repository does not stop working
|
||||||
|
because the tool learned something new.*
|
||||||
|
|
||||||
|
## What is not promised
|
||||||
|
|
||||||
|
**The command surface.** *Names, flags and output are `--help`'s business and may
|
||||||
|
change. Nothing should parse them.*
|
||||||
|
|
||||||
|
**The generated orientation file's format.** *It is byte-deterministic within a
|
||||||
|
version so that its diff is readable; it is not stable across versions.*
|
||||||
|
|
||||||
|
**That visibility is precise.** *The signal distinguishes public from not-public
|
||||||
|
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 tool says so where it reports it, rather than implying a verdict it
|
||||||
|
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.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Verified fetchable by somebody who is not us on 2026-09-08.*
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Usages — `loomctl` guarantees
|
||||||
|
|
||||||
|
**This site is built with the tool.** *Every reference page in it was adopted with
|
||||||
|
`external add`, and the reconcile that produced this one went through `check` and
|
||||||
|
`apply`.* **So "what of ours depends on it" has a short, real answer for once.**
|
||||||
|
|
||||||
|
| what the page guarantees | what of ours leans on it |
|
||||||
|
|---|---|
|
||||||
|
| `check` reports and does not fix | **`npm run check` in CI.** *A build that repaired what it found would commit on a runner, with no cart and nobody to decide* |
|
||||||
|
| the `ETag` is the publisher's, verbatim | `scripts/generate.mjs` — *the guide stamps in frontmatter are those etags; a computed hash would fire the stale banner on every whitespace change* |
|
||||||
|
| it never writes over the network | *the deploy holds no write credential — `git-sync` clones anonymously and `loomctl` is never on the cluster at all* |
|
||||||
|
| `add` refuses what is adopted, and stages a differing copy | *how all eight original documents were locked after being fetched by hand, without one byte being rewritten* |
|
||||||
|
|
||||||
|
## What we depend on that the page explicitly does not promise
|
||||||
|
|
||||||
|
**The command surface.** *`scripts/publish-site.sh` and the README quote
|
||||||
|
`loomctl external add loom/<repo> <doc>.md` verbatim.* **The page says names,
|
||||||
|
flags and output are `--help`'s business and nothing should parse them** — *we do
|
||||||
|
not parse them, but a person following our README will type them.*
|
||||||
|
|
||||||
|
> **So a renamed command breaks our documentation and not our build**, *and no
|
||||||
|
> 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.*
|
||||||
+8
-11
@@ -1,10 +1,11 @@
|
|||||||
import { defineConfig } from 'astro/config'
|
import { defineConfig } from 'astro/config'
|
||||||
import starlight from '@astrojs/starlight'
|
import starlight from '@astrojs/starlight'
|
||||||
|
import sidebar from './src/sidebar.json' with { type: 'json' }
|
||||||
|
|
||||||
// The sidebar is autogenerated from directories, so adopting a document and
|
// Nothing in this file names a document or a section. The sidebar is generated
|
||||||
// re-running `npm run generate` is the whole of adding a page. Nothing here
|
// from .loom/externals/.locks, so adopting anything and re-running
|
||||||
// names a document; a config that listed them would be a second place to
|
// `npm run generate` is the whole of adding it — a config that listed them
|
||||||
// update and would go stale silently.
|
// would be a second place to update and would go stale silently.
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: 'https://loom.hypertheory-labs.dev',
|
site: 'https://loom.hypertheory-labs.dev',
|
||||||
srcDir: './src',
|
srcDir: './src',
|
||||||
@@ -21,13 +22,9 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
editLink: { baseUrl: 'https://git.hypertheory-labs.dev/loom/docs/_edit/main/' },
|
editLink: { baseUrl: 'https://git.hypertheory-labs.dev/loom/docs/_edit/main/' },
|
||||||
sidebar: [
|
// Generated by scripts/generate.mjs from the locks. Adopting from a new
|
||||||
{ label: 'Start here', link: '/' },
|
// repository adds a section here with no edit to this file.
|
||||||
{ label: 'bedrock', autogenerate: { directory: 'bedrock' } },
|
sidebar,
|
||||||
{ label: 'externals', autogenerate: { directory: 'externals' } },
|
|
||||||
{ label: 'annotating', autogenerate: { directory: 'annotating' } },
|
|
||||||
{ label: 'cart', autogenerate: { directory: 'cart' } },
|
|
||||||
],
|
|
||||||
customCss: ['./src/styles/loom.css'],
|
customCss: ['./src/styles/loom.css'],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -232,6 +232,15 @@ for (const [repo, records] of [...sections].sort(([a], [b]) => a.localeCompare(b
|
|||||||
else if (!existing) console.log(` created ${repo}/index.mdx (blank guide, yours to fill)`)
|
else if (!existing) console.log(` created ${repo}/index.mdx (blank guide, yours to fill)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The sidebar named its sections by hand, which made adopting from a new
|
||||||
|
// repository a config edit — a second place to update, which is the thing the
|
||||||
|
// autogenerated directories were already avoiding one level down.
|
||||||
|
const sidebar = [
|
||||||
|
{ label: 'Start here', link: '/' },
|
||||||
|
...[...sections.keys()].sort().map((repo) => ({ label: repo, autogenerate: { directory: repo } })),
|
||||||
|
]
|
||||||
|
writeFileSync(join(root, 'src/sidebar.json'), JSON.stringify(sidebar, null, 2) + '\n')
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`generate: ${written.length} pages from ${sections.size} sections` +
|
`generate: ${written.length} pages from ${sections.size} sections` +
|
||||||
(ACK ? ', stamps refreshed' : staleTotal ? `, ${staleTotal} stale` : ''),
|
(ACK ? ', stamps refreshed' : staleTotal ? `, ${staleTotal} stale` : ''),
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
---
|
||||||
|
title: What `loomctl` guarantees
|
||||||
|
editUrl: false
|
||||||
|
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
|
||||||
|
---
|
||||||
|
**Not what it does — `--help` says that, and the commands will change.** *This is
|
||||||
|
what will keep being true while they do.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## It grants no access, and records where the copy came from
|
||||||
|
|
||||||
|
**`loomctl` reads what your credentials already let you read.** *Everything it
|
||||||
|
does is possible with copy and paste.* **It is a mast, not a lock** — *the point
|
||||||
|
is to make the wrong thing deliberate, not impossible.*
|
||||||
|
|
||||||
|
> **What it adds over a paste is provenance.** *A pasted document cannot answer
|
||||||
|
> "where did this come from, and were we allowed to have it" — not because the
|
||||||
|
> question is hard, but because the evidence is gone.*
|
||||||
|
|
||||||
|
## It never writes over the network
|
||||||
|
|
||||||
|
**No push, no publish, no `POST`, no token that needs write scope.** *Every byte
|
||||||
|
it writes is a file in your working tree.* **Committing and pushing are yours**,
|
||||||
|
*because the consequences of a push land on people a tool cannot experience.*
|
||||||
|
|
||||||
|
**A credential given to `loomctl` should never carry write scope**, *and if one
|
||||||
|
does, nothing here will use it.*
|
||||||
|
|
||||||
|
## Freshness is a conditional request against the publisher's `ETag`
|
||||||
|
|
||||||
|
**Stored verbatim, opaque, never a hash we compute.** *A fetch that normalises
|
||||||
|
anything breaks a local digest and reports a change that did not happen.*
|
||||||
|
|
||||||
|
*This is `externals`' rule and `loomctl` is a second holder of it. **It is stated
|
||||||
|
here so that the tool holding it is a fact somebody can find**, and so that
|
||||||
|
breaking it is visible rather than silent* — **a specimen was written in this
|
||||||
|
repository that computed a hash instead, and it was wrong within a day.**
|
||||||
|
|
||||||
|
**The URL in a lock is resolved.** *A short form follows whatever the default
|
||||||
|
branch is at the time you ask, so a branch rename would report as a change in the
|
||||||
|
document.*
|
||||||
|
|
||||||
|
## It reports; it does not repair
|
||||||
|
|
||||||
|
**Nothing is overwritten.** *A document that moved upstream is written to a
|
||||||
|
staging area as a candidate, and taking it is a separate act.* **A local copy
|
||||||
|
that differs from what the publisher serves is left alone** — *it is the only
|
||||||
|
evidence that something changed while nothing was watching.*
|
||||||
|
|
||||||
|
**`add` adopts what is absent and refuses what is already adopted.** *A document
|
||||||
|
that is present but unlocked is locked only when the bytes are identical to what
|
||||||
|
the publisher serves*, **so a lock's claim — this copy is the one being served —
|
||||||
|
is verified rather than assumed.**
|
||||||
|
|
||||||
|
## The lock file
|
||||||
|
|
||||||
|
**`.loom/externals/.locks`, one record per adopted document, tab-separated,
|
||||||
|
ordered by path.**
|
||||||
|
|
||||||
|
```
|
||||||
|
path <TAB> url <TAB> etag [ <TAB> visibility ]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`path`** — *relative to `.loom/externals/`, and **for a person to read**.* **It
|
||||||
|
does not round-trip to a URL**; *it drops the route, the branch, and the
|
||||||
|
publisher's `.loom/published/`.*
|
||||||
|
- **`url`** — *the resolved origin, branch and all.*
|
||||||
|
- **`etag`** — *the publisher's, verbatim, including its quotes.*
|
||||||
|
- **`visibility`** — *optional. What the source could be read as **when it was
|
||||||
|
fetched**: `public` or `not-public`.* **Never `private`** — *an anonymous
|
||||||
|
request tells those two apart and nothing finer.*
|
||||||
|
|
||||||
|
**Records with three fields remain valid.** *A repository does not stop working
|
||||||
|
because the tool learned something new.*
|
||||||
|
|
||||||
|
## What is not promised
|
||||||
|
|
||||||
|
**The command surface.** *Names, flags and output are `--help`'s business and may
|
||||||
|
change. Nothing should parse them.*
|
||||||
|
|
||||||
|
**The generated orientation file's format.** *It is byte-deterministic within a
|
||||||
|
version so that its diff is readable; it is not stable across versions.*
|
||||||
|
|
||||||
|
**That visibility is precise.** *The signal distinguishes public from not-public
|
||||||
|
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 tool says so where it reports it, rather than implying a verdict it
|
||||||
|
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.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Verified fetchable by somebody who is not us on 2026-09-08.*
|
||||||
|
|
||||||
|
|
||||||
|
<div class="loom-provenance">
|
||||||
|
|
||||||
|
This page is a copy of a document published by `loom/loom-cli`, rendered here.
|
||||||
|
The source is [https://git.hypertheory-labs.dev/loom/loom-cli/raw/branch/main/.loom/published/guarantees.md](https://git.hypertheory-labs.dev/loom/loom-cli/raw/branch/main/.loom/published/guarantees.md) and is what the copy is checked against.
|
||||||
|
|
||||||
|
What of ours depends on it: `.loom/externals/git.hypertheory-labs.dev/loom/loom-cli/guarantees.usages.md`
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
title: loom-cli
|
||||||
|
loom:
|
||||||
|
writtenAgainst:
|
||||||
|
- path: git.hypertheory-labs.dev/loom/loom-cli/guarantees.md
|
||||||
|
etag: '"432822b3f91ec7c7acd2c868490b7cdcde5db99a"'
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 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.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"label": "Start here",
|
||||||
|
"link": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "annotating",
|
||||||
|
"autogenerate": {
|
||||||
|
"directory": "annotating"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "bedrock",
|
||||||
|
"autogenerate": {
|
||||||
|
"directory": "bedrock"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "cart",
|
||||||
|
"autogenerate": {
|
||||||
|
"directory": "cart"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "externals",
|
||||||
|
"autogenerate": {
|
||||||
|
"directory": "externals"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "loom-cli",
|
||||||
|
"autogenerate": {
|
||||||
|
"directory": "loom-cli"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user