A node's user attributes, from either root document shape.
A format-2 .zattrsis the attributes object. A format-3 zarr.json is the
whole node record — zarr_format, node_type, consolidated_metadata, and
the attributes nested under attributes — so reading content_hash off its
top level always yields undefined. For the watchdog that means reporting
every poll as a change; for cache validation it means no token at all.
Returns {} rather than throwing for a non-object, or for a format-3 record
whose attributes is absent or not an object — both callers treat "no
attributes" as a normal, answerable state. Falling through to the record
itself in that case would expose zarr_format and node_type AS the node's
attributes, which is worse than an empty answer and would compare unequal to
the attrs the scene was loaded with on every poll.
The content signal is a zarr_format: 3 member, and alone it is a guess: a
format-2 document whose USER attributes happen to carry a zarr_format key is
indistinguishable from a format-3 one and would be answered as {} instead of
verbatim. Unreachable for a Luxar store, but a foreign store is not ours to
constrain.
docName, the document the bytes came from, settles it — both probes know it.
It may only DEMOTE: a name that is not zarr.json vetoes the unwrap, but a
name that IS zarr.json never forces one on a body that does not look like a
v3 record. Promoting on the name alone would answer {} for any non-v3 body
served from a zarr.json address — a shape no real server produces, but one
that fakes and misconfigured proxies do.
Mirrored on the Python side by _zarr_compat.attrs_from_node_doc, which takes
the same optional doc_name with the same demote-only rule; keep them in step.
A node's user attributes, from either root document shape.
A format-2
.zattrsis the attributes object. A format-3zarr.jsonis the whole node record —zarr_format,node_type,consolidated_metadata, and the attributes nested underattributes— so readingcontent_hashoff its top level always yieldsundefined. For the watchdog that means reporting every poll as a change; for cache validation it means no token at all.Returns
{}rather than throwing for a non-object, or for a format-3 record whoseattributesis absent or not an object — both callers treat "no attributes" as a normal, answerable state. Falling through to the record itself in that case would exposezarr_formatandnode_typeAS the node's attributes, which is worse than an empty answer and would compare unequal to the attrs the scene was loaded with on every poll.The content signal is a
zarr_format: 3member, and alone it is a guess: a format-2 document whose USER attributes happen to carry azarr_formatkey is indistinguishable from a format-3 one and would be answered as{}instead of verbatim. Unreachable for a Luxar store, but a foreign store is not ours to constrain.docName, the document the bytes came from, settles it — both probes know it. It may only DEMOTE: a name that is notzarr.jsonvetoes the unwrap, but a name that ISzarr.jsonnever forces one on a body that does not look like a v3 record. Promoting on the name alone would answer{}for any non-v3 body served from azarr.jsonaddress — a shape no real server produces, but one that fakes and misconfigured proxies do.Mirrored on the Python side by
_zarr_compat.attrs_from_node_doc, which takes the same optionaldoc_namewith the same demote-only rule; keep them in step.