a published surface is not only markdown

add appended .md unconditionally, so openapi.json became openapi.json.md. Reported
from use against a repository that publishes an OpenAPI document beside its prose.
It is now supplied only when the name carries no extension of its own.

Two consequences came with it that the report could not have seen. A facet's name
was built by stripping the extension, so openapi.json would have taken
openapi.usages.md and collided with the facet for a sibling openapi.md; only a
trailing .md is stripped now. And the unlocked walk matched *.md only, so a
hand-fetched .json under .loom/externals was adopted, unlocked, and invisible to
check; it now walks everything that is not the lock file or a dotfile.

The assumption was never decided, it was typed. externals says a repository
publishes documents and publication says prose in whatever form its readers need.
Neither says markdown and three places in this tool did.

Also records that the wrong diagnosis cost more than the bug: the repository is
private, a scratch config with no token made every fetch look broken, and loomctl
config would have said so in one line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
This commit is contained in:
2026-09-11 11:16:31 -04:00
co-authored by Claude Opus 5
parent e0ef0d02f8
commit b92797b4a2
6 changed files with 92 additions and 6 deletions
+37
View File
@@ -1185,3 +1185,40 @@ first thing to batch.**
had to repair a lock by hand. **No test we wrote would have caught it**: both
sites round-tripped fine in isolation, and the field only vanishes across the
handoff between two of them.*
## 2026-09-11 — a published surface is not only markdown
**`loomctl external add <repo> openapi.json` asked for `openapi.json.md`.** *`.md`
was appended unconditionally, which is right for `cart` and wrong for anything
carrying its own extension.* **Reported from use against a repository publishing
an OpenAPI document beside its prose.**
**Fixed: `.md` is supplied only when the name has no extension at all**, *never
appended to one that has its own.*
**Two consequences went with it, and neither would have been noticed from the
report:**
**Facets.** *A facet's name was built by stripping the extension, so
`openapi.json` would have taken `openapi.usages.md`* — **colliding with the facet
for a sibling `openapi.md`.** *Only a trailing `.md` is stripped now, so it is
`openapi.json.usages.md`, and `sibling-facets`' shape survives for documents that
are not prose.*
**The unlocked walk.** *It matched `*.md` only, so a hand-fetched `.json` under
`.loom/externals/` was invisible to `check`* — **adopted, unlocked, and never
reported.** *It now walks everything that is not the lock file or a dotfile.*
> **The assumption was never decided; it was typed.** *`externals` says a
> repository publishes **documents**, and `publication` says prose **in whatever
> form its readers need**.* **Neither says markdown, and three places in this tool
> did.**
**Belief that could be shown wrong:** *that extension-or-not is a good enough
rule.* **A name like `v1.2-notes` would be read as carrying an extension**, *and
the 404 path now lists the real surface, which is how somebody would find out.*
*Incidental, and worth recording because it cost a wrong diagnosis: the repository
is private, and a scratch test with a token-less config made every fetch look
broken.* **`loomctl config` says whether a token was found, and reading it first
would have been faster than reasoning.**