docs(link): the empty-catalog fix is plane-wide, and the stock-install walk that proves it

10.3 recorded the empty-`catalog` defect as a tree-family bug. It was inline in
three places -- the body catalogue, statics and land, and the tree -- and all
three now share one comparison. Records why BridgeLeases keeps the other shape,
and names the two defects as one kind of thing: a value meaning "I am not
asserting anything" has two spellings on a wire, and a stock install finds
whichever one you did not think about.

Adds the whole-plane check against a stock ServUO install: every family asked
with a real catalog, an absent one and an empty one, plus the cross-family and
stale-catalog refusals and both of stock ServUO's empty decoration files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
2026-09-14 02:33:25 -05:00
parent dcf7be4975
commit 047ecb6771

View File

@@ -1145,6 +1145,28 @@ sending `""` — a serialisation of "I have no fingerprint to assert" — had ev
a sentence naming no catalog at all ("catalog is now 8159778b"). Found by an offline probe that a sentence naming no catalog at all ("catalog is now 8159778b"). Found by an offline probe that
passed one by accident. passed one by accident.
It was **inline in three places** by the time it was found: the body catalogue (phase 3), statics
and land (phase 5) and the tree (phase 7). All three now go through one
`BridgeAssets.CatalogMismatch`, because three copies of a comparison are three chances for the next
family to get it wrong in a way only a differently-written client would ever reveal. It is
deliberately *not* the shape `BridgeLeases` uses for its own `expected`: there the value is a world
property, where an empty string is a legitimate thing to expect and `!= null` is correct.
Both defects are the same kind of thing and worth naming as one: **a value that means "I am not
asserting anything" has two spellings on a wire, and a stock install finds whichever one you did not
think about.** The plane is now checked against a stock ServUO install as a whole — every family,
each asked with a real catalog, an absent one and an empty one:
```
cliloc.table walk 67,496 rows, 12 pages
body manifest / fetch 1,095 rows; ok with a real, absent and empty catalog
static + land fetch ok with a real, absent and empty catalog
static/land carry their OWN catalog art 66a112c1 vs body 323f284f — a cross-family id is refused
tree manifest / fetch 141 files incl. BOTH empty ones; all three ways
empty files carry a VALID gzip member 2 rows gunzip to 0 bytes
a STALE catalog is still refused body, static and tree all 422
```
**`GZipStream` writes nothing for zero bytes of input.** The gzip header is emitted lazily on the **`GZipStream` writes nothing for zero bytes of input.** The gzip header is emitted lazily on the
first write, so a stream opened and closed without one yields a zero-length buffer rather than the first write, so a stream opened and closed without one yields a zero-length buffer rather than the
20-byte empty member — which is not a valid gzip stream. **Stock ServUO 57.4 ships two empty 20-byte empty member — which is not a valid gzip stream. **Stock ServUO 57.4 ships two empty