Skip to content

Merge upstream rerun 0.35.0 - #27

Open
leshy wants to merge 1079 commits into
mainfrom
sync/upstream-0.35.0
Open

Merge upstream rerun 0.35.0#27
leshy wants to merge 1079 commits into
mainfrom
sync/upstream-0.35.0

Conversation

@leshy

@leshy leshy commented Jul 28, 2026

Copy link
Copy Markdown
Member

Merges upstream rerun 0.35.0 into the fork, from a base of 0.32.0-alpha.1 — three releases of upstream work (0.33, 0.34, 0.35).

Why this merge looks different from the last one

The 0.32.0a1 sync landed as a squash (5e4e46c94, 3391 files in one commit), so git had no ancestry link to upstream past 1f628f78c (0.30.0-alpha.1).
A plain git merge 0.35.0 would therefore have picked a merge base five releases stale and produced thousands of bogus conflicts.

This PR fixes that first.
The upstream commit the fork actually sits on was identified as 8e9635b322 by minimizing the tree diff against main, and a no-op -s ours merge records it as an ancestor.
The tree is provably unchanged by that commit; it exists purely to repair the merge base.

With the base repaired, the real merge produced 43 conflicts instead of thousands, and the next sync to 0.36 will be routine.

Conflict resolution

Category Files Resolution
Version strings 34 Upstream 0.35.0 — verified version-only, no fork content
Lockfiles 2 Regenerated from upstream
Fork code 3 Hand-merged, see below
Packaging 4 Upstream versions, fork entries preserved

The three real merges

re_video/src/player/mod.rs — the fork's live-stream GOP-continuity fix (don't respawn ffmpeg on GOP rollover) sat exactly on the code upstream rewrote, and upstream renamed get_video_buffervideo_source.
Kept the fork's contiguity if/else and ported it to the new API.

entrypoint.rs — kept the fork's --ws-url flag and the run_with_app_wrapper entry point.

re_viewer/src/native.rs — kept the "DimOS Viewer" window title; APP_ID = "dimos-viewer" was untouched.

Behaviour change: --follow is gone

Upstream removed file-tailing in 14f4d32843, deleting FromUriOptions.follow — the field the fork's --follow flag was plumbed into.
Upstream's note: "This feature was also broken for quite some time now."
Their replacement is sink teeing (log to viewer and .rrd from the producing process).

The flag is dropped rather than reimplemented, because the machinery behind it no longer exists upstream.
Verified nothing in the DimOS repo passes it — the --follow in dimos/robot/cli/dimos.py is an unrelated log-tailing flag on a different CLI.

start_native_viewer_with_wrapper rewritten

The fork's copy of start_native_viewer had drifted from upstream (126 lines vs 169) and silently missed 0.35's internal-catalog gRPC service and gRPC-server memory accounting.
Rewritten to mirror upstream's current implementation, keeping only the two fork hooks (startup_patch, app_wrapper), which also restores --headless support.
Upstream's cfg_if::cfg_if!cfg_select! migration was applied here too — upstream dropped the cfg-if dependency, which is what broke the first build.

Breaking changes checked against DimOS

Every breaking change in the 0.33/0.34/0.35 migration guides was grepped against the DimOS repo — zero hits in application code:

  • rerun.recording module removed, rr.send_dataframe stricter, log_tick no longer default (0.34)
  • rerun-sdk[dataplatform]/[datafusion][catalog] (0.33)
  • SaveScreenshot moved to ViewerControlService (0.34)
  • ParquetReader index columns now use IndexColumn, StateChange.state now an array (0.35)

Toolchain

Upstream moved rust-version 1.92 → 1.95 (0.35 uses the built-in cfg_select!) and datafusion 52.3 → 53.0.
Pinned toolchains and CI images need to match.

dimos-viewer bumped to 0.35.0a1 / 0.35.0-alpha.1.

Verification

  • cargo check -p dimos-viewer — clean
  • cargo build -p dimos-viewer --bin dimos-viewer — links
  • Fork integration points confirmed present after merge: run_with_app_wrapper, AppWrapper, StartupOptionsPatch, RerunArgs, --ws-url / DIMOS_VIEWER_WS_URL, APP_ID, the dimos workspace member, the dimos-viewer console script, and docs/websockets.md
  • Remaining warnings in rerun and dimos/src/interaction/ws.rs are pre-existing on main, not introduced here

Not run: the full test suite and web/wasm build.

grtlr and others added 30 commits June 16, 2026 11:49
### Related

* Closes RR-4851.

### What

`nullable` values where not handled correctly doing sorting. Extended
tests to reflect most common cases where no values exist.

Source-Ref: 0e781aeaf309debeca5eb4c9a3a56590640ebe05
### Related

- Closes RR-4889

### What

By default has a pool of 4 connections per origin because the underlying
HTTP/2 doesn't poll aggressively enough.

---------

Source-Ref: 6712b37e4d8f8696c14b75cf185a6870583c682c
Co-authored-by: Nick <24689722+ntjohnson1@users.noreply.github.com>
* Follow-up to rerun-io/reality#2333

Source-Ref: d3dc9348bb36354c383a730d247b60aca3aba09f
### Related

* Closes RR-4836
* Follow up: RR-4853
* Follow up: RR-4854
* Follow up: RR-4874

### What

This introduces a new `WatchEvent` gRPC call to the Catalog API, which
can be used to notify connected viewers about catalog lifecycle changes.

This PR is only a first step and introduces entry-based events, so no
registering of events (RR-4853). It also does not aim to improve the UI
around connection problems (RR-4854).

### Compatibility

For now the Hub returns `Unimplemented`, which the viewer handles
gracefully.

### Testing

* Adds a basic OSS-only test to `re_redap_test`, which tests both new
events.

Source-Ref: b500ae48ec3afb00c2bc4e2ddcbdd0a40334b890
which caused a subtle bug of the ui not showing the right video frame
reference
(found while looking into pushing fallback handling into blueprint
resolved queries to avoid problems like this)

Source-Ref: dc62cd0d9ec45797c0c052b0a5c9693039c76720
### What

This adds an initial version of agent skills for ingestion to the open
source repo.

Source-Ref: 24bcac8ad2887fc6479309d63df8d3fa94952f9c
Now `AppContext` is created only once per frame and remains accessible
througout just as intended - it is our most basic viewer context object
and contains. This is achieved primarily by moving time control
reference out of it. As a consequence we can remove some duplicated code
like modal handling

This is a direct follow-up to
* rerun-io/reality#2319

Reminder what `AppContext` is:
```rs
/// Application context that is shared across all parts of the viewer.
///
/// This context, in difference to [`crate::ViewerContext`] can exist for
/// any arbitrary state of the viewer. And not only when there is an open
/// recording.
```

Source-Ref: 5c148416012483a366976118f9b5752bab517840
Fixing CI failures due to deprecated manifest() in snippet and
whitespace errors.

Source-Ref: f6bc7ec73f4e71a7d76c1b827e9eb41eb8b5d9ba
It didn't wait long enough and ended up with partial data every now and
then

---------

Source-Ref: 3f87cafd8fb1e3992000c78a4eec4177dbb106ea
Co-authored-by: Isse <git@isse.rs>
Implements a compact dedicated voxel renderer with procedural cube
geometry, batch-level transparency, picking, outline masks, and a
spatial 3D visualizer.

### Related
* Part of rerun-io#11358
* Related to rerun-io#10276

### What

Implements a compact dedicated voxel renderer with procedural cube
geometry, batch-level transparency, picking, outline masks, and a
spatial 3D visualizer.

This adds `VoxelGridMap` as a sparse 3D voxel archetype with:

* Signed integer voxel indices via `IVec3D`, allowing negative grid
coordinates.
* Scalar cubic `cell_size`.
* Optional values, colors, opacity, value range, colormap, translation,
and rotation.
* A dedicated renderer path with compact per-voxel GPU instances.
* Spatial3D visualization, selection, outline masks, and bounding boxes.
* Rust, Python, and C++ SDK bindings, snippets, generated docs, tests,
snapshots, and a renderer benchmark.

---------

Source-Ref: a06249995ea9f25e74d2cbd509f1cd8aa71d2812
Co-authored-by: Yang Zhou <yangzhou.info@gmail.com>
Co-authored-by: Michael Grupp <mgrupp16@gmail.com>
Co-authored-by: Gábor Gyebnár <korteur@gmail.com>
Co-authored-by: Andreas Reich <r_andreas2@web.de>
Co-authored-by: Andreas Reich <andreas@rerun.io>
### Related

- part of
https://linear.app/rerun/project/py-chunk-chunk-centric-processing-pipeline-and-lenses-apis-in-python-1cf386cd9cd3
- closes
RR-4718
- closes RR-3198
- follow-up RR-4700 (to limit clutter here)

### What

- Makes `Chunk.from_record_batch()` far more flexible. This is now the
core piece for arrow -> chunk interoperability in the SDK
- Introduces `Chunk.from_record_batches()`.
- Rewrite `RecordingStream.send_dataframe()` based on the above (with
breaking changes, see migration guide).
- The conversion logic is exposed in `re_chunk::Chunk` and implemented
in `re_sorbet` for reusability.

The "arbitrary-dataframe-to-chunk(s)" semantics are riddled with edge
cases. This PR aims to strike a balance towards handling arbitrary
dataframe (from a fully spec'ed ChunkBatch to a random dataframe) with a
reasonable set of knobs and behaviour. The result is best described
through the API's docstring:

```python
class Chunk:
    @classmethod
    def from_record_batch(
        cls,
        record_batch: pa.RecordBatch,
        *,
        index: str | list[str] | None | _AutoIndex = AUTO_INDEX,
        entity_path: str | None = None,
    ) -> list[Chunk]:
        """
        Interpret an Arrow [`RecordBatch`][pyarrow.RecordBatch] as Rerun chunk data.

        Each column of the batch is classified as a row-id column, index (timeline) column,
        or a component column. Component columns are then grouped per entity path, and
        one chunk per entity path is emitted.

        The `rerun:*` arrow metadata, if it exists, drives the kind of each input column,
        as well as the entity/archetype/component type for component columns.

        If present, the row id column and chunk id metadata indicate that the batch represents
        a fully identified chunk, e.g. as produced by [`Chunk.to_record_batch`][rerun.experimental.Chunk.to_record_batch].
        Both the row ids and chunk id are preserved under the following conditions:
        - both are present in the input batch
        - `index` is omitted
        - `entity_path` is omitted

        If any of these conditions are not met, it means that either the batch is not fully
        identified, or that the chunk data is reinterpreted (e.g. entity path rewriting).
        In that case, fresh row ids and chunk id are generated and used instead of the input
        ones.

        Parameters
        ----------
        record_batch:
            The Arrow record batch to interpret.
            Component columns may be either lists (one component batch per row) or plain arrays
            (wrapped as single-element lists auto********ally).
        index:
            Determines which columns are index (timeline) columns. Each promoted column's
            time type is taken from its Arrow datatype: `int64` → sequence, `timestamp(ns)`
            → timestamp, `duration(ns)` → duration.

            - Omitted (the default): derive the index columns from the batch's Rerun metadata.
              The batch is treated as temporal if it carries index metadata. A batch with no index
              metadata is ambiguous and raises an error — unless it is an already-identified chunk
              (it carries a row-id column and a chunk id), which round-trips as-is and may therefore
              be static. Pass `index=None` to force a static interpretation.
            - A column name, or list of column names: treat exactly these columns as timelines.
              The remaining (non-row-id) columns become components.
            - `None`: produce static chunks (no timeline). Any index metadata or promoted index
              column is then a contradiction and is rejected.

            !!! note
                Static chunks with multiple rows are legitimate in some cases, but only the last
                row is visible from typical latest-at queries. An info-level message is emitted
                when this happens — except for an already-identified chunk that is preserved as-is
                (see above), which is passed through without this check.
        entity_path:
            Default entity path for component columns that do not otherwise specify one.
            Resolution order per component column is: its `rerun:entity_path` metadata, then the
            batch-level `rerun:entity_path` metadata, then the column-name convention (see
            *Notes*), then this argument, then the root entity (`/`).

        Returns
        -------
        One chunk per distinct entity path described by the batch, in first-seen column order.

        Raises
        ------
        ValueError
            In any of the following cases:

            - `index` was omitted and the batch carries no index metadata
              (an ambiguous raw batch). Pass `index=<column>` for temporal data or `index=None`
              for static data.
            - `index=None` was given but the batch also carries index metadata or names an
              index column (contradiction).
            - `index` names a column that is not present in the batch.
            - The batch contains no component columns (there is nothing to log).
            - A column promoted to an index contains null values. Time columns must be dense;
              static data is expressed with `index=None`, not with null times.
            - An index column has an Arrow datatype that is not a supported time type.
            - The batch is a fully-identified chunk (it carries both a row-id column and a chunk id)
              but resolves to more than one entity path. An identified chunk is preserved as a single
              chunk; drop the chunk-id metadata and/or the row-id column to reinterpret it into one
              chunk per entity (with freshly-minted ids).

        Notes
        -----
        **Column-name convention.** When a component column carries no `rerun:entity_path` /
        `rerun:component` metadata, its entity path is read from the column name: if the name starts
        with `/` and contains a `:`, the first part of the column name is interpreted as the entity
        path and the rest as the component identifier. Example: `/point:Points3D:positions` and
        `/metadata:foo`.

        Limitations/Future work
        -----------------------
        A batch that mixes static and temporal rows — aka where some index values are `null` — are
        rejected. Handling this case requires row-splitting and generating a mix of temporal and
        static chunks.

        Recording-property columns (named `property:…`, mapping to the `/__properties` entity) are
        not recognized by the column-name convention and are not mapped back to that entity.

        """
```

### Testing

The test suite aims to cover the spec laid out in the above docstring.

### Compatibility

Documented breaking changes in `RecordingStream.send_dataframe()`.
Previous implementation was experimental (though not marked as such) and
frail.

Source-Ref: 2f52ecc8081ab76101403cf926e34e7a279f2eb0
### Related

* Closes RR-4906.

### What

This should improve our robustness against corrupted artifact downloads,
in `rrd_bw_compat_test` by writing to tempfiles first. Artifacts are now
also downloaded to `~/.cache` (or equivalent) to prevent CI from picking
it up (we cache the `target/` dir).

Note that we can still end up with missing RRDs locally due to
networking problems, but `ensure_rrd_cached` is re-entrant.

Source-Ref: b2e5829cade8c1a4aca87f8dd72fcb7468a91e07
…er()`

### Related

* part of
https://linear.app/rerun/project/py-chunk-chunk-centric-processing-pipeline-and-lenses-apis-in-python-1cf386cd9cd3
* closes
RR-4733

### What

Update docs to cover `Chunk.from_record_batch` and related, and
`ChunkStore.reader()`.

Source-Ref: 2b56c61b48f70bcf5a2a8b665527cda9f987ffd5
<!--
Thank you for filing a pull request! We kindly ask you to:

1. Fill out this pull request template below, to make the review smoother.
2. Enable edits to your branch by our maintainers. This helps us to get your branch ready to merge. See here for more details:
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork
-->

### Related
This PR includes my other small PR (yes, I get this probably is a bad practice): rerun-io#12810


<!--
Include links to any related issues/PRs in a bulleted list, for example:
* Closes rerun-io#1234
* Part of rerun-io#1337
-->

<!--
Make sure the PR title and labels are set to maximize their usefulness for the CHANGELOG,
and our `git log`.

If you have noticed any breaking changes, include them in the migration guide.

We track various metrics at <https://build.rerun.io>.

For maintainers:
* To run all checks from `main`, comment on the PR with `@rerun-bot full-check`.
* To deploy documentation changes immediately after merging this PR, add the `deploy docs` label.

For more details check the PR section on <https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md>.
-->

Source-Ref: 6284cdeefbdb8f34162577785dbc2a1f171ea66b
* add sync-reality alias for @oxkitsune
* failed to merge PR directly will now still close it

Source-Ref: cf8983fc8cc4eae72535726393ca215677feb7a7
### Related

- broke in rerun-io/reality#2319

### What

The selection changed every frame when on a non-blueprint page (e.g.
redap table), causing a egui focus request for the selections list item
every frame, causing typing/keyboard focus to be broken on those page.

### Testing

tested on native viewer

Source-Ref: 0163ff9d28a01fa22e4a95076feb922f83aab4a9
…ests

Final step of the quiver PR chain (splitting up rerun-io#2263). Stacked on
rerun-io#2281.

Pure cleanup, no functional change:

* Shorter `ext::` import paths throughout
* `RegisterWithDatasetDataframe::try_from` destructuring instead of
per-column extracts
* `TaskId::from` / `into_string` conversions instead of manual struct
building
* `.unique()` instead of a BTreeSet round-trip for dedup

Deliberate deviations from the prototype branch (kept from main, not
regressed):
* `Option<&[SegmentId]>`-based segment filters in `re_server` (newer
than the prototype's empty-list convention)
* `QueryTasksDataframe`'s strongly-typed `Column<TaskId>` from rerun-io#2274

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
### 🚂 Quiver PR train
1. rerun-io#2274 — Introduce quiver + migrate QueryTasks ✅
2. rerun-io#2278 — RegisterWithDataset response ✅
3. rerun-io#2280 — ScanSegmentTable / ScanDatasetManifest ✅
4. rerun-io#2281 — QueryDataset
5. rerun-io#2283 — Polish: idio******** imports & typed test extracts
6. rerun-io#2287 — Catalog entries table + Tuid serialization
7. rerun-io#2288 — manifest-registry column helpers
8. rerun-io#2331 — DatasetManifest read _(combined into rerun-io#2334)_
9. rerun-io#2334 — DatasetManifest read + write paths
10. rerun-io#2335 — Strongly-typed `DatasetManifestBatch` via
`#[derive(Quiver)]`

_(Related: rerun-io#2314 — update to quiver 0.2.0)_

Source-Ref: 624799f63a0beb419aee9a20a673f792838e2d3d
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
### Related

- Closes rerun-io#9464
- Closes RR-4760

### What

Instead of navigating to some arbitrary open recording when closing a
recording, go through navigation history and find the last visited one
that's still open, and navigate there.

Source-Ref: 41fd7790a0eb86c7ded8ae293fe44abbf4b40b91
### Related

* new Rerun `VoxelGridMap` archetype:
rerun-io@fa40ec1
* Foxglove voxel grid:
https://docs.foxglove.dev/docs/sdk/schemas/voxel-grid
* rerun-io#11358

### What

Foxglove `VoxelGrid` stores voxels in a dense byte array with
row/column/slice stride and RGBA colors. The Rerun type uses sparse
voxel indices, but these can be easily mapped.

### Testing

Snapshot test with minimal MCAP file.
<img width="762" height="442" alt="image"
src="https://github.com/user-attachments/assets/d66e8b61-e264-423d-b2b8-f26eb6840043"
/>

### Compatibility

Just adds a new lens.

Source-Ref: 098205d410a54eafda88570723148be70837fe62
slipped through the cracks since wgsl is compiled at runtime only.

... so we're also fixing that here and add a test that validates all
wgsl shaders as part of re_renderer's test suite!

Source-Ref: 70f5f0ea869906cac65adea5ee21d880adede2cd
Follow-up to the quiver PR chain (rerun-io#2274rerun-io#2278rerun-io#2280rerun-io#2281rerun-io#2283), applying quiver beyond the wire dataframes.

* New `EntriesTableDataframe` (`#[derive(Quiver)]`) replaces the
hand-written schema and manual array construction in `redap_catalog`'s
`EntriesTable`. The existing `entries_table_schema` snapshot pins that
the schema is unchanged.
* As a side effect, `redap_catalog` no longer needs its `re_types` and
`re_types_core` dependencies.
* `Loggable for Tuid`'s `to_arrow` now builds through
`quiver::Column<Tuid>` instead of a manual `FixedSizeBinaryBuilder`.
* `Tuid::from_arrow` is deliberately unchanged: it ignores the validity
mask (per its datatype contract) and reads bulk zero-copy — quiver
currently supports neither (noted as quiver improvement suggestions in
`quiver_todo.md`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
### 🚂 Quiver PR train
1. rerun-io#2274 — Introduce quiver + migrate QueryTasks ✅
2. rerun-io#2278 — RegisterWithDataset response ✅
3. rerun-io#2280 — ScanSegmentTable / ScanDatasetManifest ✅
4. rerun-io#2281 — QueryDataset
5. rerun-io#2283 — Polish: idio******** imports & typed test extracts
6. rerun-io#2287 — Catalog entries table + Tuid serialization
7. rerun-io#2288 — manifest-registry column helpers
8. rerun-io#2331 — DatasetManifest read _(combined into rerun-io#2334)_
9. rerun-io#2334 — DatasetManifest read + write paths
10. rerun-io#2335 — Strongly-typed `DatasetManifestBatch` via
`#[derive(Quiver)]`

_(Related: rerun-io#2314 — update to quiver 0.2.0)_

---------

Source-Ref: ec23a72f41c5ea74446a16e499970dd51931c833
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Asked claude to ensure all our internal architecture docs are up-to-date

Source-Ref: 7b6cce3b0d4b021bed22ebe596862521b751b700
### Related

- Part of RR-4091

### What

Buffer time playing if video indicates that it's buffering.

This does not affect overall play behavior on what happens when
buffering, just when buffering happens.

https://github.com/user-attachments/assets/000462e1-3565-47ab-b935-97e73d99fedf

Source-Ref: 699a73699610d786e57f0e45eb222dbf016103a3
slipped through - this was always wrong despite the comment correctly
explaining it

Source-Ref: eb55e603d2b4981ff5bc00d05c7c30f36e986c63
### Related
* Small things identified while running ROS 2 bag tests for (unlanded)
bagfile plugin work

  ### What

Three fixes to ROS 2 reflection decoding caught while running ROS 2 bag
tests.

* **`byte`/`char` → uint8.** ROS 2 `byte` and `char` are both unsigned
8-bit; `char` was wrongly decoded as `int8`.
* **Pad empty message specs like rosidl.** Field-less specs now gets
`structure_needs_at_least_one_member`.
* **Reject `wstring`** `wstring` is UTF-16 and decoding it as a narrow
string corrupted the rest of the message. The reflection decoder now
skips `wstring` channels (raw fallback), and de/serialization errors.

  ### Testing
Unit tests in `re_ros_msg` and `re_mcap` (byte/char aliasing, padding,
wide/mixed enum specs, `wstring` detection). `pixi run cargo test -p
re_ros_msg -p re_mcap` green.

  ### Compatibility
No format or API changes. Affects only how ROS 2 MCAP channels decode
(`wstring` channels now fall back to lossless raw bytes instead of
producing corrupt data.)

Source-Ref: 0d3f1889c48eba97b4044b28145ffa1fadfedee9
Builds on rerun-io#2334. Replaces the naked `RecordBatch` inside
`DatasetManifestBatch` with a `#[derive(Quiver)]` struct, so the
dataset-manifest columns are validated and strongly typed.

### What
- New `DatasetManifestBatchQuiver` (`#[derive(Quiver)]`): every manifest
column as `quiver::Column<L>` (`Column<Option<L>>` for nullable).
`segment`-named Rust fields map to the legacy on-disk names via
`#[quiver(name = "rerun_partition_*")]`; `#[quiver(extra_columns)]`
collects the runtime `property:*` / index-range columns.
- `DatasetManifestBatch { handle, data: DatasetManifestBatchQuiver }`.
Construction via fallible `try_new` (validates the full schema once);
`num_rows()` covers the remaining need.
- Dropped the per-column accessors (`col_*_raw`, `col_rerun_*`,
`col_rerun_*_parsed`) — full-schema call sites read `batch.data.<field>`
directly. Kept `col_property_raw` for the runtime `property:*` columns.
The URL / segment-kind parsing now lives in the free, per-row helpers
`parse_storage_url` / `parse_segment_kind`.
- Projected (partial-schema) scans — drop-segments, schema-sha256
lookup, the dedup paths, and the patcher — deliberately bypass `try_new`
and extract individual columns via the generated
`DatasetManifestBatchQuiver::COLUMN_*` descriptors, since a partial
batch can't pass whole-schema validation.
- The drop-segments path (the only consumer of gRPC-schema scan output)
reads ids/layers via the public `ScanDatasetManifestDataframe`, keeping
`DatasetManifestBatchQuiver` purely on-disk-schema.
- `DatasetManifestInserter`/`DatasetManifestPatcher::apply` now return
the written `RecordBatch` instead of a `DatasetManifestBatch`: patch
payloads are partial, so wrapping them in a fully-typed batch would fail
validation. All callers discard the value anyway.

### Testing
`cargo check --all-targets`, clippy (deny-warnings), and `cargo nextest
run` — all clean for `redap_manifest_registry` (109 tests pass). `cargo
fmt`. CI integration tests exercise the manifest read/write/scan paths.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
### 🚂 Quiver PR train
1. rerun-io#2274 — Introduce quiver + migrate QueryTasks ✅
2. rerun-io#2278 — RegisterWithDataset response ✅
3. rerun-io#2280 — ScanSegmentTable / ScanDatasetManifest ✅
4. rerun-io#2281 — QueryDataset
5. rerun-io#2283 — Polish: idio******** imports & typed test extracts
6. rerun-io#2287 — Catalog entries table + Tuid serialization
7. rerun-io#2288 — manifest-registry column helpers
8. rerun-io#2331 — DatasetManifest read _(combined into rerun-io#2334)_
9. rerun-io#2334 — DatasetManifest read + write paths
10. rerun-io#2335 — Strongly-typed `DatasetManifestBatch` via
`#[derive(Quiver)]`

_(Related: rerun-io#2314 — update to quiver 0.2.0)_

---------

Source-Ref: 8fafa5f01211f6a41b0565112593a05fd1d91c3a
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
### Related
  * Subset of the typed-parser → lens migration draft rerun-io#1730
* Follows rerun-io#1555 (occupancy_grid lens), rerun-io#1991 (pose_stamped lens), and
the log/string lens PRs

  ### What
* Adds a lens for `sensor_msgs/msg/MagneticField` on top of the
`ros2_reflection` decoder, slotted in next to `occupancy_grid`.
* Deletes the typed `MagneticFieldMessageParser` and the now-unused
`MagneticField` struct definition.

  ### Testing
* New snapshot test `test_magnetic_field` using
`tests/assets/ros_magnetic_field.mcap`.
* Tested for regression: ran the same mcap through the old typed parser
and the new lens, the results were identical.
  <screenshot placeholder>

  ### Compatibility
No shape changes. The lens emits the same `Arrows3D:vectors`
(FixedSizeList<f32, 3>) and `CoordinateFrame:frame` (Utf8) as the
previous typed parser, on the same `ros2_timestamp` timeline derived
from `.header.stamp`.
`magnetic_field_covariance` is intentionally ignored, matching the
previous parser.

  ### Out of scope
This PR is a 1:1 logic move from parser to lens. It does not change NaN
handling for the `magnetic_field` vector (the ROS spec allows NaN in any
component if the sensor does not report that axis).

---------

Source-Ref: ce7e2f184795970593d4a0b575b2191ea67e2e4f
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
### What

This makes it possible to populate the `Selector` runtime that is used
in our SDKs with custom functions. This makes it easier to create
reusable transformations for data pipelines.

All functions should be registered and defined in `re_lenses` so that we
always share a common runtime across all products.

Source-Ref: 08ed1cad2dcedcda8ae8c1ccf5d239d77ce2029e
### Why
Some Hub calls return `ResaurceExhausted` when concurrency limits are
hit. They normally should be interpreted as suggestions for the client
to retry.

We want to take some of those retries off the customers' shoulders, so
we do them in the SDK.

### What
* Use `re_backoff` for exponential backoff with full jitter retry

### Compatibility
* No compatibility issues.

---------

Signed-off-by: Andrea Reale <andrea@rerun.io>

Source-Ref: bcfbb98afe1ac919f46134072710b109d517baec
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Andrea Reale <andrea-reale@users.noreply.github.com>
* Alternative to rerun-io/reality#2410
* Fixes RR-4944

Make extra sure that things are already loaded before taking screenshot

Source-Ref: 80f6441705b07500e2f20f0241457fc40e106369
MichaelGrupp and others added 23 commits July 22, 2026 10:57
### Related

The new start/end time and recover options are available in the Python
binding but were not yet exposed on the CLI.

### What

Adds 3 args to `rerun mcap convert`:

* `--recover`
* `--start-time` & `--end-time`

The time arguments allow strings with different time units /
representation for CLI ergonomics.

See `--help` strings / `cli.md` for all details.

### Testing

Manual test with an MCAP file

```
rerun mcap convert example.mcap --start-time 2025-06-02T11:26:50.16879979Z --end-time 1748863630s
…
INFO re_mcap::decoders: Filtering MCAP messages to log_time range [1748863610168799790, 1748863630000000000) (nanoseconds)
INFO rerun::commands::mcap: Processed 2261 messages.
```
vs
```
rerun mcap convert example.mcap
…
INFO rerun::commands::mcap: Processed 4187 messages.
```

### Compatibility

Just new CLI args.

Source-Ref: 2d5726db2ae8f11759c4772ebac2001a7215dde0
### Related

* Closes RR-5033
* Closes RR-5034

### What

This makes the internal Viewer catalog present unconditional. With this
PR, it is always started and always reachable via gRPC. The settings
dialog governs if RRD files get loaded into the Viewer catalog or take
the legacy path.

Also gets rid of the `internal_catalog` feature flag again.

Source-Ref: 58e3fac59a53699629fbc3d7067f0f94a52aac70
### Related

- part of
https://linear.app/rerun/project/py-chunk-chunk-centric-processing-pipeline-and-lenses-apis-in-python-1cf386cd9cd3
- closes RR-4667
- follow-up to rerun-io/reality#2646

### What

Introduce `Hdf5Reader` to the Python SDK.

Short-term future work at least includes:
-
RR-5249

### Testing

Include python integration tests

### Compatibility

New API surface.

---------

Source-Ref: 62525ea9a67988afd85194b20fc7728216dcaf41
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Nick <24689722+ntjohnson1@users.noreply.github.com>
On top of rerun-io#2683

### What

Exposes `re_video`'s GOP/keyframe detection and Annex B conversion
utilities to Python (through `rerun.experimental.video` for now) and
switches the dataloader's `VideoFrameDecoder` to use them instead of its
own hand-rolled H.264/H.265/AV1 keyframe heuristics in python.

---------

Source-Ref: 92ea101c846a821962b817705313386bd07da010
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…e's a time selection

### Related

* Fixes
RR-5193

### What

... and if we _somehow_ get there, simply select the entire time range.

Previously, we'd sometimes create very small selections, typically
0s-1s, which in a larger recording one wouldn't find. Therefore, just by
misclicking the loop button you end up with a time selection that you
then might later share on links which can be very confusing.
(the previous `initial_time_selection` tried to be clever about
`segments` (runs of continuous recording) but judging from the behavior
it was broken. Didn't spend time going deep there because a) with the
behavior change it's not important b) either way it may produce a
selection that you don't see in a large recording!)

https://github.com/user-attachments/assets/69f969fa-77a6-4bd6-a48b-d6fc383a3145

Source-Ref: 692326234cb43acf37e0be3af0c9a36cdd8024eb
Reduces boilerplate a bit by taking appropriate context objects for the
job.

There's gonna be a follow-up that makes `ViewContext` more readily
available in tests which builds on top of this!

---------

Source-Ref: eff1a0aed1431705b061dcb7f4794be8032c3773
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
### Related

* Follow-up to rerun-io#2592

### What

Replace the generic SQL filter fields on segment-table and
dataset-manifest scans with an explicit `SegmentIdFilter` protobuf
message.

The filter uses a `oneof` strategy: `scan_only` scans rows for the
listed segment IDs, while `skip` scans every segment except the listed
IDs. I wrote the protobuf definition like this to be very clear and
explicit, because an earlier version suggested putting "include" and
"exclude" on the filter and I thought it was ambiguous about "are we
including in the things to filter or including in the final results?"

The DataFusion providers normalize supported `=`, `!=`, `IN`, `NOT IN`,
and compatible boolean expressions into these strategies. Pushdown
remains `Inexact`, so DataFusion re-applies the original expression
after receiving the scan output. The code documents that this can become
`Exact` after capability negotiation or after compatibility with servers
that predate the new field is no longer required. We can do this after
ALL servers have been upgraded or we add some kind of versioning
information to the connection.

Remove generic SQL parsing, post-aggregation filtering, and
filter-specific public-to-internal column translation from both server
implementations.

### Testing

* Focused `cargo nextest` coverage for DataFusion normalization,
manifest-registry expression construction, and both scan endpoints
against the OSS server and dataplatform frontend

### Compatibility

The previous `sql_filter` field names and numbers are reserved, and the
new message uses new field numbers.
Old servers ignore the new field, while new servers ignore scan filter
fields sent by old clients.
Because pushed filters remain `Inexact`, downstream DataFusion
re-applies them and preserves query correctness during mixed-version
deployments.

Since we're still marking everything as `Inexact` we can guarantee
correctness by the follow on filters.

Source-Ref: 1782581f8117f3ef27364785aaacfeb3d8491ad0
### What

Ideally, coding agents should self-disclose themselves, especially when
creating issues and PRs auto********ally without a human in the loop. These
changes might help nudging the LLMs into doing that.

---------

Source-Ref: fdf08c3673bde074ac072629382bc0cd8c82e8a1
Co-authored-by: Michael Grupp <michael@rerun.io>
### Related

Follow-up to: rerun-io/reality#2771

### What

rerun-io#2771 introduced a small `IndexColumn` dataclass to describe an index
column (name, kind, input unit). It's also used in `ParquetReader`. We
previously were using a tuple of str that is eminently unergonomic.

### Testing

Updated test

### Compatibility

Breaking change without deprecation (`rerun.experimental`)

Source-Ref: d3f2b6d0b67c638d991bfd5258671479d8875f88
### Related

* Part of RR-5086
* Follow up RR-5248

### What

RRDs uploaded to OPFS for the Viewer catalog are persisted and take up
user's disk space. We want to be mindful about not poluting their disk,
so we use a introduce `RrdFingerprint` as a form of "content-based" hash
of an RRD.

For RRDs with footer, the hash is computed solely over the bytes of the
footer, for footerless RRDs, the hash is computed over the entire RRD.

A file is only uploaded to OPFS if it does not exist there yet and we
stop clearing files from OPFS on internal catalog startup.

### Compatibility

This PR should not add any new allocations to pre-existing code paths.

Source-Ref: 9a6e2ac7c36d9950e01fae550daff4cdb59e960a
Source-Ref: 5c94ad6fe73bc08fa7a4a21558279c84c5fb1241
Co-authored-by: Michael Grupp <michael@rerun.io>
Co-authored-by: Nick <24689722+ntjohnson1@users.noreply.github.com>
Co-authored-by: Lucas Meurer <hi@lucasmerlin.me>
### Related
* RR-4595

### What

Add pixi tasks to measure code coverage:
```bash
cd rerun
pixi run rs-coverage [crate]
pixi run rs-coverage-html [crate]
```

<img width="1539" height="693" alt="image"
src="https://github.com/user-attachments/assets/13329c6c-9ea9-49a5-89f3-8474ac58c0b7"
/>

---------

Source-Ref: 9ad6e7c24dc7351bc2e9b31f0ffa8d5af5571623
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…erun-io#12858)

### What

Loading a Draco- or meshopt-compressed glTF/GLB currently surfaces the raw `gltf` crate validation error:

```
invalid glTF: extensionsRequired[0] = "KHR_draco_mesh_compression": Unsupported extension
```

which names the extension but doesn't tell the user what to do. This maps that case to an actionable error instead:

```
This file requires glTF extension(s) that Rerun does not support: KHR_draco_mesh_compression.
If this is Draco or meshopt compression, re-export the model uncompressed.
```

### How

`gltf::import_slice` rejects unsupported `extensionsRequired` during validation, *before* any geometry is read (verified against gltf 1.4.1), so the previously-hypothesized "mesh has no triangles" path never triggers. On the `import_slice` error we re-parse with `Gltf::from_slice_without_validation` purely to recover and name the required extensions.

This is the "give a decent error message" slice of rerun-io#6365 — it does **not** add Draco/meshopt decoding.

### Confidence / disclosure

Written with the help of a coding agent (Claude), reviewed by me. Confidence is high: the change is small and localized to the import error path, the underlying `gltf` behavior was verified empirically, and there's a unit test covering the extension-naming. I'm less familiar with how this error ultimately renders in the viewer UI, so pointers there are welcome.

Part of rerun-io#6365.

Source-Ref: 506227337ac77bf76c1b78e092757a60c5a91682
- broke in rerun-io/reality#1879

Source-Ref: be0eeef65004f2ac6b8fa8e8458f3a90bc144178
Commit 5e4e46c imported rerun 0.32.0-alpha.1 as a squash, so git had no
history link to upstream past 1f628f7 (0.30.0-alpha.1). This no-op merge
records 8e9635b as an ancestor so subsequent upstream merges get a correct
merge base. Tree is unchanged.
Merges three releases of upstream work (0.33, 0.34, 0.35) onto a fork
based on 0.32.0-alpha.1.

The previous sync landed as a squash, so git's merge base was stale by
five releases. The parent commit grafts the real base (8e9635b) back
into the ancestry, which cut this merge from thousands of spurious
conflicts down to 43.

Conflicts resolved:

* Version strings, lockfiles and packaging — took upstream, preserving
  the "dimos" workspace member and the dimos-viewer console script.
* re_video player — kept the fork's live-stream GOP-continuity fix and
  ported it onto upstream's renamed `video_source` API.
* Window title — kept "DimOS Viewer".

Behaviour changes:

* `--follow` is removed. Upstream deleted file-tailing in 14f4d32
  along with `FromUriOptions.follow`, the field the flag fed into.
  Nothing in DimOS passes the flag.
* `start_native_viewer_with_wrapper` is rewritten against upstream's
  current `start_native_viewer`, keeping the `app_wrapper` and
  `startup_patch` hooks. The fork's copy had drifted and was missing
  0.35's internal-catalog service and gRPC memory accounting, and still
  used the dropped `cfg-if` dependency.

Upstream moved rust-version 1.92 to 1.95 and datafusion 52.3 to 53.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

import rerun as rr

output_path = Path(tempfile.mktemp(suffix=".rrd"))
gilrs-core's libudev-sys needs libudev.pc on Linux: libudev-dev on the
ubuntu check job, systemd-devel in the manylinux wheel containers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leshy leshy added the exclude from changelog Upstream label-check: PR not for the changelog label Jul 28, 2026
Newline before the start_native_viewer_with_wrapper doc comment, and
redirects for the Status -> State doc pages the rename moved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leshy leshy closed this Jul 28, 2026
… decoder

The GOP-rollover guard added in 2b473d1 required the enqueued samples to
lead *exactly* into the next GOP's keyframe (`last_enqueued + 1 >= gop_start`).
At the live edge that holds only when the tail of the old GOP has fully
arrived by the time its successor's IDR lands, which is not reliable: on a
1080p/53fps drone stream (GOP 192) the gap is regularly 2-3 samples, and every
one of those fell through to the reset branch — killing and respawning the
ffmpeg CLI process, then re-decoding from the keyframe.

A gap of a few samples is ingest jitter, not a seek, and the reset is
unnecessary regardless: the target is an IDR, which resets reference state by
definition, so it can be fed to the running decoder whether or not the frames
before it made it in. Skips of more than one GOP never reach this check —
handle_errors_and_reset_decoder_if_needed has already reset by then — so the
tolerance only has to cover jitter. It stays well under a GOP so that a
genuine forward skip inside the previous GOP still resets rather than decoding
the whole remainder for nothing.

Measured on a 75s replay of that stream, before -> after: 5 -> 0 gap resets,
7 -> 2 ffmpeg spawns (both at startup, 0.5ms apart), 8 -> 14 rollovers decoded
straight through. One long-lived ffmpeg process for the whole run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@leshy leshy reopened this Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

exclude from changelog Upstream label-check: PR not for the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.