Skip to content

moczarr.store

Store layer: obstore-backed access to hive store roots and leaves.

One backend (obstore) by design — the walk's termination rule ("no digit children ⇒ nothing finer exists") and the debris model both lean on strongly-consistent, uncached delimiter-LIST semantics reaching this code unmediated, so a second backend would be a second correctness surface (rationale on the plan thread, espg/moczarr#1).

Leaf functions take (store_root, leaf) with leaf a store-relative path (from :func:moczarr.convention.leaf_path or :func:walk_leaves), so every access — local or S3 — goes through one store handle and a missing leaf is uniformly a clean GET miss, never a backend-dependent error.

Postures, per the design's D9 discipline:

  • The manifest is the bootstrap: absent reads None, malformed raises — there is no degraded mode without it.
  • Cache tiers (root MOC) are tolerant: garbage reads as absent with a debug log, and the caller degrades to :func:walk_leaves — never wrong answers.
  • The commit stamp gates completeness: an unstamped or malformed-stamp leaf is debris and reads None. Presence requires the stamp; absence (a clean LIST/GET miss) is trustworthy on its own.
  • A PRESENT-but-corrupt bitmap sidecar raises (see moczarr.coverage).
  • A stamp naming current is a pointer (zagg spec §1.5, versioned leaves): the arrays and the in-leaf sidecar are under that version subgroup, and :func:leaf_data_prefix is the one place that says so. The stamp read itself stays on the stable root, as do the leaf's siblings at its node. A pointer over a missing or unstamped version is debris (the open paths, which never read the version's stamp, catch a missing one only — see :func:_dangling_pointer).

bitmap_and(store_root, leaf, aoi, *, store=None, **store_kwargs)

Exact cell-level intersection via a leaf's coverage (bitmap or full).

Reads the stamp once. aoi is a morton cover — packed uint64 words, decimal strings, or an object exposing __morton_moc__() (mortie's Moc). encoding: "full" short-circuits to MOC membership against the shard's own id — no sidecar GET, no expansion. The "bitmap" path pays the one sidecar GET. None when the leaf carries neither (box-only, debris, absent) — the caller falls back to the box verdict. An empty array is a definitive miss: both encodings are exact, not conservative.

Source code in src/moczarr/store.py
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
def bitmap_and(
    store_root: str, leaf: str, aoi, *, store: Any = None, **store_kwargs: Any
) -> np.ndarray | None:
    """Exact cell-level intersection via a leaf's coverage (bitmap or full).

    Reads the stamp once. ``aoi`` is a morton cover — packed ``uint64``
    words, decimal strings, or an object exposing ``__morton_moc__()``
    (mortie's ``Moc``). ``encoding: "full"`` short-circuits to MOC
    membership against the shard's own id — no sidecar GET, no expansion.
    The ``"bitmap"`` path pays the one sidecar GET. ``None`` when the leaf
    carries neither (box-only, debris, absent) — the caller falls back to
    the box verdict. An empty array is a definitive miss: both encodings
    are exact, not conservative.
    """
    from mortie import moc_and

    aoi = as_moc_words(aoi)
    handle = _resolve_store(store_root, store, store_kwargs)
    stamp = read_commit(store_root, leaf, store=handle)
    coverage = parse_leaf_coverage(stamp)
    if not coverage:
        return None
    if coverage.get("encoding") == "full":
        word = morton_word(split_leaf_name(leaf.rstrip("/").rsplit("/", 1)[-1])[0])
        return moc_and(np.asarray([word], dtype=np.uint64), aoi)
    occupied = read_coverage_bitmap(store_root, leaf, stamp=stamp, store=handle)
    if occupied is None:
        return None
    return moc_and(occupied, aoi)

leaf_data_prefix(leaf, stamp)

Where a leaf's arrays and in-leaf sidecar live, given its ROOT stamp.

The one reader rule of zagg spec §1.5 ("Versioned leaves"): a root stamp naming current makes the stable {id}.zarr prefix a pointer — every array, chunk and in-leaf sidecar key is under {leaf}/{current}/ — and a stamp without it is a legacy leaf whose arrays sit at the root. No spec token marks the difference and a store legitimately mixes both, so the question is asked per leaf, of the stamp every reader has already fetched: following the pointer costs no request.

Pure name arithmetic — nothing is read, so a pointer naming a version that is not there (a corrupted leaf, §1.5) is not detected here; the caller's read under the returned prefix misses, which is its debris answer. stamp=None (debris, or an absent leaf) returns the root.

What still lives beside the STABLE root, never under the version: the leaf's siblings at its node (the stats sidecar, granules.json, the §4.6 column) and the root zarr.json itself — the stamp read stays on the root, which mirrors the version's stamp.

Raises ValueError for a current that is not a version name (§4.2: a single path component beginning run-): that stamp claims a version and cannot be half-trusted, and composing a key from it could address something outside the leaf.

Source code in src/moczarr/store.py
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def leaf_data_prefix(leaf: str, stamp: dict | None) -> str:
    """Where a leaf's arrays and in-leaf sidecar live, given its ROOT stamp.

    The one reader rule of zagg spec §1.5 ("Versioned leaves"): a root stamp
    naming ``current`` makes the stable ``{id}.zarr`` prefix a **pointer** —
    every array, chunk and in-leaf sidecar key is under ``{leaf}/{current}/``
    — and a stamp without it is a legacy leaf whose arrays sit at the root.
    No ``spec`` token marks the difference and a store legitimately mixes
    both, so the question is asked per leaf, of the stamp every reader has
    already fetched: following the pointer costs no request.

    Pure name arithmetic — nothing is read, so a pointer naming a version
    that is not there (a corrupted leaf, §1.5) is not detected here; the
    caller's read under the returned prefix misses, which is its debris
    answer. ``stamp=None`` (debris, or an absent leaf) returns the root.

    What still lives beside the STABLE root, never under the version: the
    leaf's siblings at its node (the stats sidecar, ``granules.json``, the
    §4.6 column) and the root ``zarr.json`` itself — the stamp read stays on
    the root, which mirrors the version's stamp.

    Raises ``ValueError`` for a ``current`` that is not a version name
    (§4.2: a single path component beginning ``run-``): that stamp claims a
    version and cannot be half-trusted, and composing a key from it could
    address something outside the leaf.
    """
    root = leaf.strip("/")
    current = stamp.get(LEAF_CURRENT_KEY) if isinstance(stamp, dict) else None
    if current is None:
        return root
    if (
        not isinstance(current, str)
        or not current.startswith(LEAF_VERSION_PREFIX)
        or "/" in current
    ):
        raise ValueError(
            f"leaf {root} names an invalid version {current!r}: a stamp's "
            f"{LEAF_CURRENT_KEY!r} must be one path component beginning "
            f"{LEAF_VERSION_PREFIX!r} (zagg spec §1.5/§4.2)"
        )
    return f"{root}/{current}"

load_root_coverage(store_root, *, store=None, **store_kwargs)

The store-root coverage envelope, or None when unusable.

Tolerant (the root MOC is a regenerable cache): a missing object, unparsable JSON, or an unknown spec/encoding all read as absent — with a debug log so the degradation is discoverable — and the caller falls back to :func:walk_leaves.

Source code in src/moczarr/store.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def load_root_coverage(store_root: str, *, store: Any = None, **store_kwargs: Any) -> dict | None:
    """The store-root coverage envelope, or ``None`` when unusable.

    Tolerant (the root MOC is a regenerable cache): a missing object,
    unparsable JSON, or an unknown spec/encoding all read as absent — with a
    debug log so the degradation is discoverable — and the caller falls back
    to :func:`walk_leaves`.
    """
    handle = _resolve_store(store_root, store, store_kwargs)
    try:
        payload = read_json(handle, ROOT_COVERAGE_NAME)
    except ValueError as e:
        logger.debug(f"unparsable {ROOT_COVERAGE_NAME} at {store_root} ({e}); ignoring")
        return None
    envelope = parse_root_coverage(payload)
    if payload is not None and envelope is None:
        logger.debug(f"{ROOT_COVERAGE_NAME} at {store_root} has an unknown spec/encoding; ignoring")
    return envelope

open_object_store(path, *, anonymous=False, **kwargs)

Open an obstore store at path (s3://... or a local directory).

Read-only posture: a missing local directory raises FileNotFoundError (the writer creates stores; the reader never does). anonymous=True skips request signing for public buckets (the source.coop case); kwargs pass through to S3Store.from_url (region=... etc.).

Ambient credentials (no explicit keys/endpoint, no anonymous): obstore's native chain reads env vars then falls back to EC2 instance metadata — it cannot see AWS profiles/SSO, so a laptop with AWS_PROFILE set gets an IMDS HostUnreachable, not a credential error. When boto3 is importable and resolves credentials, prefer its resolver via Boto3CredentialProvider (which carries the session's region into the store config itself). Environments without boto3, or where boto3 resolves nothing, keep the bare store — env/IMDS behavior unchanged.

Source code in src/moczarr/store.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
def open_object_store(path: str, *, anonymous: bool = False, **kwargs: Any):
    """Open an obstore store at ``path`` (``s3://...`` or a local directory).

    Read-only posture: a missing local directory raises ``FileNotFoundError``
    (the writer creates stores; the reader never does). ``anonymous=True``
    skips request signing for public buckets (the source.coop case);
    ``kwargs`` pass through to ``S3Store.from_url`` (``region=...`` etc.).

    Ambient credentials (no explicit keys/endpoint, no ``anonymous``):
    obstore's native chain reads env vars then falls back to EC2 instance
    metadata — it cannot see AWS profiles/SSO, so a laptop with
    ``AWS_PROFILE`` set gets an IMDS ``HostUnreachable``, not a credential
    error. When boto3 is importable and resolves credentials, prefer its
    resolver via ``Boto3CredentialProvider`` (which carries the session's
    region into the store config itself). Environments without boto3, or
    where boto3 resolves nothing, keep the bare store — env/IMDS behavior
    unchanged.
    """
    if path.startswith("s3://"):
        from obstore.store import S3Store

        if anonymous:
            kwargs.setdefault("skip_signature", True)
        else:
            supplied = {k.lower().removeprefix("aws_") for k in kwargs} | {
                k.lower().removeprefix("aws_") for k in (kwargs.get("config") or {})
            }
            if not supplied & _EXPLICIT_S3_KEYS:
                provider = _ambient_provider()
                if provider is not None:
                    kwargs["credential_provider"] = provider
        return S3Store.from_url(path, **kwargs)
    from obstore.store import LocalStore

    local = Path(path).expanduser().resolve()
    if not local.is_dir():
        raise FileNotFoundError(f"{path!r} is not a directory — not a readable store root")
    return LocalStore(local)

read_commit(store_root, leaf, *, store=None, **store_kwargs)

A leaf's commit stamp, or None for debris / absent leaves.

One GET of the leaf's root zarr.json (the leaf is vanilla zarr v3 by convention, so the root group metadata is that one object; no zarr machinery needed to check completeness). A missing object, a missing stamp, and a malformed (non-mapping) stamp are the same answer: not complete. A present-but-unparsable zarr.json raises — that leaf claims to exist and cannot be half-trusted.

Source code in src/moczarr/store.py
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
def read_commit(
    store_root: str, leaf: str, *, store: Any = None, **store_kwargs: Any
) -> dict | None:
    """A leaf's commit stamp, or ``None`` for debris / absent leaves.

    One GET of the leaf's root ``zarr.json`` (the leaf is vanilla zarr v3 by
    convention, so the root group metadata is that one object; no zarr
    machinery needed to check completeness). A missing object, a missing
    stamp, and a malformed (non-mapping) stamp are the same answer: not
    complete. A present-but-unparsable ``zarr.json`` raises — that leaf
    claims to exist and cannot be half-trusted.
    """
    handle = _resolve_store(store_root, store, store_kwargs)
    meta = read_json(handle, f"{leaf.strip('/')}/zarr.json")
    return _stamp_from_meta(meta)

read_commits(store_root, leaves, *, store=None, concurrency=32, **store_kwargs)

Commit stamps for many leaves, batched (issue #5).

One result per input leaf, aligned by position, each with :func:read_commit semantics — None for debris/absent, a raise for a present-but-unparsable zarr.json (:func:read_leaf_metas is the shared substrate).

Source code in src/moczarr/store.py
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
def read_commits(
    store_root: str,
    leaves: Sequence[str],
    *,
    store: Any = None,
    concurrency: int | None = 32,
    **store_kwargs: Any,
) -> list[dict | None]:
    """Commit stamps for many leaves, batched (issue #5).

    One result per input leaf, aligned by position, each with
    :func:`read_commit` semantics — ``None`` for debris/absent, a raise for
    a present-but-unparsable ``zarr.json`` (:func:`read_leaf_metas` is the
    shared substrate).
    """
    metas = read_leaf_metas(
        store_root, leaves, store=store, concurrency=concurrency, **store_kwargs
    )
    return [_stamp_from_meta(meta) for meta in metas]

read_coverage_bitmap(store_root, leaf, *, stamp=None, coverage=None, store=None, **store_kwargs)

A leaf's exact occupied cell words from its bitmap sidecar, or None.

None for anything without a "bitmap" sidecar to read: debris, a box-only envelope, encoding: "full" (there IS no sidecar — the shard id is the exact MOC; :func:bitmap_and short-circuits on it), or a missing sidecar object. A present-but-corrupt sidecar raises (decoder's posture). The shard id comes from the leaf basename via the frozen first-_ split; cell_order from the envelope.

The sidecar sits beside the arrays, so on a versioned leaf it is under the version the root stamp names (:func:leaf_data_prefix). Pass an already-read root stamp to skip the stamp GET. coverage — an already-parsed envelope — still overrides the one read off the stamp, but no longer skips that GET by itself: the envelope does not carry the pointer, the stamp does.

Source code in src/moczarr/store.py
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
def read_coverage_bitmap(
    store_root: str,
    leaf: str,
    *,
    stamp: dict | None = None,
    coverage: dict | None = None,
    store: Any = None,
    **store_kwargs: Any,
) -> np.ndarray | None:
    """A leaf's exact occupied cell words from its bitmap sidecar, or ``None``.

    ``None`` for anything without a ``"bitmap"`` sidecar to read: debris, a
    box-only envelope, ``encoding: "full"`` (there IS no sidecar — the shard
    id is the exact MOC; :func:`bitmap_and` short-circuits on it), or a
    missing sidecar object. A present-but-corrupt sidecar raises (decoder's
    posture). The shard id comes from the leaf basename via the frozen
    first-``_`` split; ``cell_order`` from the envelope.

    The sidecar sits beside the arrays, so on a versioned leaf it is under
    the version the root stamp names (:func:`leaf_data_prefix`). Pass an
    already-read root ``stamp`` to skip the stamp GET. ``coverage`` — an
    already-parsed envelope — still overrides the one read off the stamp,
    but no longer skips that GET by itself: the envelope does not carry the
    pointer, the stamp does.
    """
    import obstore
    from obstore.exceptions import NotFoundError

    handle = _resolve_store(store_root, store, store_kwargs)
    if stamp is None:
        stamp = read_commit(store_root, leaf, store=handle)
    if coverage is None:
        coverage = parse_leaf_coverage(stamp)
    if not coverage or coverage.get("encoding") != "bitmap" or not coverage.get("sidecar"):
        return None
    shard, _window = split_leaf_name(leaf.rstrip("/").rsplit("/", 1)[-1])
    try:
        data = obstore.get(handle, f"{leaf_data_prefix(leaf, stamp)}/{coverage['sidecar']}").bytes()
    except (FileNotFoundError, NotFoundError):
        return None
    return decode_bitmap(bytes(data), shard, int(coverage["cell_order"]))

read_json(store, key)

GET+parse one small JSON object; None when it does not exist.

Parse errors propagate — tolerant callers wrap this per their tier's posture.

Source code in src/moczarr/store.py
176
177
178
179
180
181
182
183
184
185
186
187
188
189
def read_json(store, key: str):
    """GET+parse one small JSON object; ``None`` when it does not exist.

    Parse errors propagate — tolerant callers wrap this per their tier's
    posture.
    """
    import obstore
    from obstore.exceptions import NotFoundError

    try:
        data = obstore.get(store, key).bytes()
    except (FileNotFoundError, NotFoundError):
        return None
    return json.loads(bytes(data))

read_leaf_coverage(store_root, leaf, *, store=None, **store_kwargs)

A leaf's coverage envelope off its commit stamp, or None.

Source code in src/moczarr/store.py
398
399
400
401
402
def read_leaf_coverage(
    store_root: str, leaf: str, *, store: Any = None, **store_kwargs: Any
) -> dict | None:
    """A leaf's coverage envelope off its commit stamp, or ``None``."""
    return parse_leaf_coverage(read_commit(store_root, leaf, store=store, **store_kwargs))

read_leaf_metas(store_root, leaves, *, store=None, concurrency=32, **store_kwargs)

Raw root zarr.json payloads for many leaves, batched (issue #5).

The substrate :func:read_commits maps over, exposed so a caller that needs MORE than the stamp from the same object — the pyramid layer reads the D11 role/zagg_overview root attrs alongside it (zagg spec §4.3) — never pays a second GET. One result per input leaf, aligned by position: None for an absent object, the parsed payload otherwise; a present-but-unparsable zarr.json raises (that leaf claims to exist and cannot be half-trusted). concurrency bounds the in-flight GETs (obstore.get_async behind a semaphore); None or 1 keeps the serial path for debugging.

Source code in src/moczarr/store.py
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
def read_leaf_metas(
    store_root: str,
    leaves: Sequence[str],
    *,
    store: Any = None,
    concurrency: int | None = 32,
    **store_kwargs: Any,
) -> list[dict | None]:
    """Raw root ``zarr.json`` payloads for many leaves, batched (issue #5).

    The substrate :func:`read_commits` maps over, exposed so a caller that
    needs MORE than the stamp from the same object — the pyramid layer reads
    the D11 ``role``/``zagg_overview`` root attrs alongside it (zagg spec
    §4.3) — never pays a second GET. One result per input leaf, aligned by
    position: ``None`` for an absent object, the parsed payload otherwise; a
    present-but-unparsable ``zarr.json`` raises (that leaf claims to exist
    and cannot be half-trusted). ``concurrency`` bounds the in-flight GETs
    (``obstore.get_async`` behind a semaphore); ``None`` or ``1`` keeps the
    serial path for debugging.
    """
    handle = _resolve_store(store_root, store, store_kwargs)
    keys = [f"{leaf.strip('/')}/zarr.json" for leaf in leaves]
    if concurrency is None or concurrency <= 1:
        return [read_json(handle, key) for key in keys]
    import asyncio

    async def gather():
        semaphore = asyncio.Semaphore(concurrency)
        return await asyncio.gather(*(_get_json_async(handle, key, semaphore) for key in keys))

    return _run_coroutine(gather())

read_manifest(store_root, *, store=None, **store_kwargs)

The store's validated morton_hive.json; None when absent.

Loud on malformed content (bad JSON or a failed :func:parse_manifest): the manifest is the reader's bootstrap, so garbage here is an error, not a degradable cache.

Source code in src/moczarr/store.py
192
193
194
195
196
197
198
199
200
def read_manifest(store_root: str, *, store: Any = None, **store_kwargs: Any) -> dict | None:
    """The store's validated ``morton_hive.json``; ``None`` when absent.

    Loud on malformed content (bad JSON or a failed :func:`parse_manifest`):
    the manifest is the reader's bootstrap, so garbage here is an error, not
    a degradable cache.
    """
    payload = read_json(_resolve_store(store_root, store, store_kwargs), MANIFEST_NAME)
    return None if payload is None else parse_manifest(payload)

walk_columns(store_root, *, store=None, concurrency=None, path_grouping=1, **store_kwargs)

Yield the store-relative path of every §4.6 column artifact (issue #36).

The column twin of :func:walk_leaves — same walk, same contracts (fallback/verification path, stamped and debris objects alike, set identical between the serial and concurrent forms, order not guaranteed) — but yielding the *.pyramid.zarr objects the name seam classifies as columns. This is the read-the-columns discovery §4.6 prescribes: the manifest's pyramid block MAY lag a config-only change, so "which leaves actually carry columns" is answerable only from the columns themselves. Completeness stays the caller's check (:func:read_commit — an unstamped column prefix is debris), and a column's classification is its role/zagg_column attrs (:func:moczarr.column.read_column_record), never the name alone.

The suffix is the seam at every depth, so on a staged store this yields two §4.6 kinds interleaved: the leaf columns at shard_order nodes, and the issue-#384 stage columns a staged sweep leaves at its dispatch nodes (the same artifact shape under an ancestor node's prefix). A caller tells them apart by node order, read off the path. :func:moczarr.column.read_column_record and :func:moczarr.column.open_column address leaf columns only — both are keyed by shard id and refuse an ancestor-node id — so a stage column is discoverable here and not readable through that pair today (espg/moczarr#36b). The split is deliberate rather than an oversight: §4.6 makes stage-column existence at a given ancestor order orchestration, never contract ("a reader binds to the ladder artifacts of §4.4, not to stage columns"), so a path-addressed reader for them is a design step this surface does not take on spec.

Source code in src/moczarr/store.py
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
def walk_columns(
    store_root: str,
    *,
    store: Any = None,
    concurrency: int | None = None,
    path_grouping: int = 1,
    **store_kwargs: Any,
) -> Iterator[str]:
    """Yield the store-relative path of every §4.6 column artifact (issue #36).

    The column twin of :func:`walk_leaves` — same walk, same contracts
    (fallback/verification path, stamped and debris objects alike, set
    identical between the serial and concurrent forms, order not guaranteed)
    — but yielding the ``*.pyramid.zarr`` objects the name seam classifies
    as columns. This is the read-the-columns discovery §4.6 prescribes: the
    manifest's ``pyramid`` block MAY lag a config-only change, so "which
    leaves actually carry columns" is answerable only from the columns
    themselves. Completeness stays the caller's check
    (:func:`read_commit` — an unstamped column prefix is debris), and a
    column's classification is its ``role``/``zagg_column`` attrs
    (:func:`moczarr.column.read_column_record`), never the name alone.

    The suffix is the seam at **every** depth, so on a staged store this
    yields two §4.6 kinds interleaved: the **leaf columns** at
    ``shard_order`` nodes, and the issue-#384 **stage columns** a staged
    sweep leaves at its dispatch nodes (the same artifact shape under an
    *ancestor* node's prefix). A caller tells them apart by node order, read
    off the path. :func:`moczarr.column.read_column_record` and
    :func:`moczarr.column.open_column` address **leaf** columns only — both
    are keyed by shard id and refuse an ancestor-node id — so a stage column
    is discoverable here and not readable through that pair today
    (espg/moczarr#36b). The split is deliberate rather than an oversight:
    §4.6 makes stage-column existence at a given ancestor order
    *orchestration, never contract* ("a reader binds to the ladder artifacts
    of §4.4, not to stage columns"), so a path-addressed reader for them is
    a design step this surface does not take on spec.
    """
    yield from _walk(
        store_root,
        "column",
        store=store,
        concurrency=concurrency,
        path_grouping=path_grouping,
        **store_kwargs,
    )

walk_leaves(store_root, *, store=None, concurrency=None, path_grouping=1, **store_kwargs)

Yield the store-relative path of every leaf zarr — the discovery walk.

The fallback/verification path (never the hot path): one delimiter-LIST per digit node — no digit children means nothing finer exists (LIST is strongly consistent and object stores have no empty prefixes, so absence is definitive). Yields stamped and debris leaves alike — completeness is the caller's check (:func:read_commit), matching the tiered postures. A §4.6 leaf column (*.pyramid.zarr) is never yielded: the name seam excludes it, and it has to, because a column carries a commit stamp of its own and would pass that completeness check. Columns have their own discovery walk (:func:walk_columns, issue #36).

path_grouping is the manifest's digit-chunking (spec §6.1) — child classification depends on it, so callers walking a grouped store must pass the manifest's value (readers hold the manifest before any path work; D10).

concurrency > 1 batches the LISTs breadth-parallel, one tree level at a time (obstore.list_with_delimiter_async behind a semaphore). The yielded SET is identical to the serial walk's; the ORDER may differ (level-by-level vs depth-first) — callers sort, per the contract.

Source code in src/moczarr/store.py
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
def walk_leaves(
    store_root: str,
    *,
    store: Any = None,
    concurrency: int | None = None,
    path_grouping: int = 1,
    **store_kwargs: Any,
) -> Iterator[str]:
    """Yield the store-relative path of every leaf zarr — the discovery walk.

    The fallback/verification path (never the hot path): one delimiter-LIST
    per digit node — no digit children means nothing finer exists (LIST is
    strongly consistent and object stores have no empty prefixes, so absence
    is definitive). Yields stamped and debris leaves alike — completeness is
    the caller's check (:func:`read_commit`), matching the tiered postures.
    A §4.6 leaf **column** (``*.pyramid.zarr``) is never yielded: the name
    seam excludes it, and it has to, because a column carries a commit stamp
    of its own and would pass that completeness check. Columns have their
    own discovery walk (:func:`walk_columns`, issue #36).

    ``path_grouping`` is the manifest's digit-chunking (spec §6.1) — child
    classification depends on it, so callers walking a grouped store must
    pass the manifest's value (readers hold the manifest before any path
    work; D10).

    ``concurrency`` > 1 batches the LISTs breadth-parallel, one tree level
    at a time (``obstore.list_with_delimiter_async`` behind a semaphore).
    The yielded SET is identical to the serial walk's; the ORDER may differ
    (level-by-level vs depth-first) — callers sort, per the contract.
    """
    yield from _walk(
        store_root,
        "leaf",
        store=store,
        concurrency=concurrency,
        path_grouping=path_grouping,
        **store_kwargs,
    )

warn_if_stale(store_root, shard, envelope)

O7 lazy staleness detection for one opened, commit-stamped leaf.

Call with POSITIVE evidence of a committed shard (an opened leaf with a stamp) that the root MOC does not list. Usually benign — a run in progress writes the root MOC only at end of run — so this warns ONCE per store per process with the context, returns whether stale, and never auto-walks. envelope may be None (no root MOC at all): that is absence, not staleness, and reads False. A malformed envelope cannot vouch for the shard and counts as stale.

Source code in src/moczarr/store.py
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
def warn_if_stale(store_root: str, shard: str | int, envelope: dict | None) -> bool:
    """O7 lazy staleness detection for one opened, commit-stamped leaf.

    Call with POSITIVE evidence of a committed shard (an opened leaf with a
    stamp) that the root MOC does not list. Usually benign — a run in
    progress writes the root MOC only at end of run — so this warns ONCE per
    store per process with the context, returns whether stale, and never
    auto-walks. ``envelope`` may be ``None`` (no root MOC at all): that is
    absence, not staleness, and reads ``False``. A malformed envelope cannot
    vouch for the shard and counts as stale.
    """
    if envelope is None:
        return False
    from moczarr.convention import morton_decimal

    decimal = morton_decimal(shard)
    try:
        if ranges_contain(envelope, decimal):
            return False
    except (KeyError, TypeError, ValueError):
        pass  # malformed envelope cannot vouch for the shard -> stale
    key = store_root.rstrip("/")
    if key not in _stale_warned:
        _stale_warned.add(key)
        warnings.warn(
            f"commit-stamped shard {decimal} is not listed by {store_root}/"
            f"{ROOT_COVERAGE_NAME} — the root MOC lags the leaves. Usually benign "
            f"(a run in progress writes the root MOC at end of run); otherwise a "
            f"crashed run, a concurrent-run union race, or out-of-band writes. "
            f"The store's writer can regenerate it (zagg's refresh, or the sweep).",
            stacklevel=2,
        )
    return True