Skip to content

Point-LIO: mirror FAST-LIO cleanups (no-YAML config, memory2 Recorder, frame scheme)#2559

Merged
leshy merged 171 commits into
mainfrom
jeff/feat/pointlio_native
Jun 26, 2026
Merged

Point-LIO: mirror FAST-LIO cleanups (no-YAML config, memory2 Recorder, frame scheme)#2559
leshy merged 171 commits into
mainfrom
jeff/feat/pointlio_native

Conversation

@jeff-hykin

@jeff-hykin jeff-hykin commented Jun 22, 2026

Copy link
Copy Markdown
Member

Mirrors onto the Point-LIO native module the same cleanups already landed for FAST-LIO in #2498, so the two modules stay consistent.

jeff-hykin added 30 commits June 3, 2026 15:51
…lio_native flake/cmake consuming dimos-module-fastlio2 pointlio branch + Estimator/parameters sources)
…y path)

The fast-lio input was pinned to file:///Users/jeffhykin/... which only
exists on the Mac. Repoint to the dimensionalOS/dimos-module-fastlio2
pointlio branch on github so the flake builds on Linux. Same locked rev.
Rename the mirrored fastlio_blueprints.py to pointlio_blueprints.py and
wire it to PointLio (was incorrectly using FastLio2). Adds mid360-pointlio
and mid360-pointlio-voxels to the blueprint registry.
…race-fix flake relock

Adds the offline replay/inspection tooling for the pointlio_native module:
pcap_replay.hpp (streams a Livox pcap into the SDK callbacks), deterministic_clock
+ dual-thread replay options, the ruwik2_pt3 replay harness, the pcap_to_db tool
(append pointlio_odometry into an existing memory db at ~30Hz, streaming), validated
Point-LIO mid360.yaml, and the live smoke-test helper. flake.lock relocks onto the
fastlio2 pointlio rev carrying the mtx_buffer race fix; main.cpp comment corrected
to attribute the divergence fix to that lock (not the publish-rate gating).
Switches the flake's fast-lio input from path:/home/dimos/repos/dimos-module-fastlio2
to github:dimensionalOS/dimos-module-fastlio2/pointlio so the module builds on any
machine without a local fastlio2 clone. Relocked onto rev 7e5d88f (the mtx_buffer
race fix); verified pointlio_native builds from the github source.
…hful config

OUTPUT-model replay of the Jun-7 hand-shake bag diverged to ~25km (vs
hku-mars master's bounded ~5m). Two issues, both fixed here (paired with
the dimos-module-fastlio2 pointlio-branch curvature/deque fixes):

- main.cpp: heap-use-after-free thread race in bag-frame replay. The
  feeder thread drives run_main_iter via step() after each feed, but the
  main thread also drove run_main_iter, so both raced on the shared PCL
  measurement cloud (ASan: free in sync_packages, read-after-free in
  ImuProcess::Process). Force serial_replay in bag-frame mode so only the
  feeder thread touches the EKF.
- CMakeLists.txt + flake.nix: the iVox map backend needs glog; add the
  find_package/link and the nix buildInput. Drop ikd_Tree.cpp from
  sources (iVox replaces ikd-Tree).
- config/mid360.yaml (+ cpp/config duplicate): set satu_acc 5.5->3.0
  (master value — accel >=3g saturated, residual zeroed, keeps velocity
  bounded) and add ivox_grid_resolution=2.0 / ivox_nearby_type=6 (NEARBY6)
  matching the master config that produced the 5.028m baseline.
- replay_ruwik2_pt3.py: make MAX_WALL_SEC env-overridable.

After the fix the OUTPUT model stays bounded (peak |pos| 3.898m) on the
full bag; ASan reports zero memory errors.
…onsumes the iVox fix

The iVox-port + divergence fixes live in dimos-module-fastlio2 @ pointlio
commit 02d5066, which is committed locally but NOT pushed (per the task's
no-push constraint). The flake's fast-lio input was pointing at
github:dimensionalOS/dimos-module-fastlio2/pointlio, whose lock pinned the
pre-fix rev 7e5d88f. Since CMakeLists.txt already drops ikd_Tree.cpp (iVox
replaces ikd-Tree), building against that stale github source fails with
KD_TREE undefined-reference linker errors.

Repoint fast-lio at path:/home/dimos/repos/dimos-module-fastlio2 and bump
the lock so `nix build .#pointlio_native` consumes the local 02d5066 source.
Verified: build exits 0, no KD_TREE errors, 661176-byte binary.

NOTE: this bakes a machine-specific absolute path into the lock. Once
Repo A's pointlio branch is pushed, switch this input back to
github:dimensionalOS/dimos-module-fastlio2/pointlio and bump the lock to
02d5066 for portability.
Now that dimos-module-fastlio2 pointlio (02d5066, the iVox port + divergence
fix) is on origin, switch the fast-lio flake input from the local path: pin
back to github:dimensionalOS/dimos-module-fastlio2/pointlio and bump the lock
to rev 02d5066. This makes jeff/feat/pointlio_native self-contained and
portable (no machine-specific path in the lock).

Verified: nix build .#pointlio_native exits 0, no KD_TREE errors.
… add --force

Extends pcap_to_db.py to populate both pointlio_odometry and pointlio_lidar
streams (start-aligned onto the db's earliest ts) so pointlio can be compared
against fastlio in one recording. --force overwrites existing pointlio streams.
Untracks the machine-specific fastlio_test/setup_network symlinks (enhance
overlay) and drops the empty tools/__init__.py.
…o tools

- Consolidate config/ to one default.yaml (the tuned Mid-360/iVox config);
  remove the unused upstream sensor presets (avia, horizon, marsim, ouster64,
  velodyne, mid360). Module now defaults to default.yaml.
- Remove tools/replay_ruwik2_pt3.py (pcap_to_db.py covers offline replay) and
  tools/demo_live_test.py.
…egistry

- --db is now optional: with no existing db, build one from scratch (defaults
  to <pcap>.db next to the pcap); with an existing db, append + time-align as
  before.
- Rename the internal recorder Rec/RecConfig -> _Rec/_RecConfig so the
  blueprint-registry generator skips it (a tool helper isn't a public module);
  fixes test_all_blueprints_is_current.
- Docstring: document from-scratch generation using the ruwik2_part3 LFS sample.
… rm cpp/README + config copies; concise comments

- config: consolidate to a single config/default.yaml; drop the ROS-only
  lid_topic/imu_topic + odom frame-id/publish/pcd_save keys (parsed-but-unused
  by the native binary), and note which params are Mid-360-specific.
- delete cpp/config/{mid360.json,mid360.yaml} (duplicate) and cpp/README.md.
- tighten verbose comments in main.cpp, pcap_replay.hpp, timing.hpp
  (comments only; binary rebuilds clean).
… db name in docstring

120s clip (elapsed 55-175s) of the ruwik velocity-spike recording — the data
that diverges through FAST-LIO at the 0.5m pre-KF voxel and is bounded under
Point-LIO. Use via get_data('ruwik2_part3'); pcap_to_db --pcap <it> builds the
db from scratch.
….0 clock bug

- module.py docstring: Point-LIO (not FAST-LIO2) + correct import path.
- pcap_to_db.py: use 'is not None' (not 'or') for the ts fallback so a real
  sensor ts of 0.0 isn't replaced by wall time (which would misclassify the
  stream clock in _resolve_offset).
… NIC

Reads a Livox Mid-360 pcap into RAM, rewrites packet timestamps to
current-time, and replays point/IMU/status onto a virtual network
interface at a configurable rate + delay. Synthesizes the Livox SDK2
control protocol (discovery + GetInternalInfo/FwType ACKs, CRC16/CRC32)
so an unmodified consumer (pointlio) handshakes with it as a real sensor.
Builds via nix (rustPlatform.buildRustPackage, cargoLock from Cargo.lock).
…bal_map

- Cloud now published in the sensor frame (mid360_link): use fastlio2
  get_body_cloud() (undistorted scan, no world registration) instead of
  inverse-transforming the world cloud. No transform in publish_lidar.
- Split frames: frame_id (mid360_link) on both the cloud + odometry
  headers; odom_parent_frame_id (odom) -> odom_frame_id (base_link) for
  the TF publish.
- Remove global_map / voxel_map.hpp entirely (deleted file, config,
  blueprint + pcap_to_db references).
- Bump fast-lio pin to fcbd1c2 (adds get_body_cloud).
get_data() at module level triggered a git-LFS download during blueprint
validation (test_blueprint_is_valid), which CI blocks via git-lfs-guard —
failing the whole test matrix. Default pcap to empty; resolve the capture
path at run time instead.
Port the minimal pcap-replay subsystem from jeff/feat/go2_record into the
clean branch so FAST-LIO can run offline from a Mid-360 pcap, matching the
Point-LIO pcap_to_db workflow:

- cpp: pcap_replay.hpp + timing.hpp (header-only), main.cpp refactored so the
  main loop runs from either the live SDK or a pcap feeder thread, with an
  optional deterministic sensor-clock mode. Keeps the clean branch's
  velocity-cap (guarded set_max_velocity_norm_ms) and flake (velocity-cap
  fast-lio); does not pull go2_record's tcpdump record path.
- module.py: replay_pcap / replay_skip_until_ns / first_packet_marker /
  deterministic_clock config fields; skip network validation in replay mode.
- tools/pcap_to_db.py: replay a pcap through FastLio2 (real-time, non-
  deterministic) and append fastlio_odometry + fastlio_lidar into an existing
  memory2 db, time-aligned onto its clock. --force overwrites.
…FastLio2Recorder

- livox/pcap_recorder.py: standalone tcpdump pcap capture (LivoxPcapRecorder),
  decoupled from FAST-LIO. The lidar/SLAM module no longer owns packet capture.
- fastlio2/recorder.py: FastLio2Recorder records fastlio_odometry + fastlio_lidar
  and rewrites ONLY those streams' timestamps onto the db clock (promoted from
  pcap_to_db's inline recorder; fixes the ts==0.0 falsy-fallback bug).
- pcap_to_db.py now imports FastLio2Recorder instead of an inline copy.
FastLio2 no longer produces a global voxel map — odometry + registered lidar
only. Removed global_map Out, map config, and the mapping.GlobalPointcloud spec.
Updated all consumers (fastlio_blueprints, alfred_nav, g1_onboard, g1_nav_onboard,
mobile, pcap_to_db) to drop map args + the global_map remap. Nav blueprints lose
their fastlio map; full nav wants a separate mapper wired in (follow-up).
# Conflicts:
#	dimos/hardware/sensors/lidar/fastlio2/tools/pcap_to_db.py
#	dimos/memory2/module.py
…tive

# Conflicts:
#	dimos/hardware/sensors/lidar/pointlio/module.py
Convert the memory2 Recorder from thread/disposable rx subscriptions to
manual async callbacks via process_observable, and let pose_setter_for
methods be async (awaited in _resolve_pose). Update the fastlio and go2
recorders accordingly.
Raise TypeError at decoration time if a non-async function is decorated,
and always await the setter in _resolve_pose.
Switch recorders to async: the base Recorder now uses process_observable
async callbacks and pose_setter_for requires async setters. Converted the
pointlio recorder's pose setters to async to match.
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2335 1 2334 74
View the full list of 1 ❄️ flaky test(s)
dimos.e2e_tests.test_dimsim_spatial_memory::test_go_to_the_bed

Flake rate in main: 21.15% (Passed 41 times, Failed 11 times)

Stack Traces | 559s run time
lcm_spy = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7a26aa0df5c0>
start_blueprint = <function start_blueprint.<locals>.set_name_and_start at 0x7a26a6f3e5c0>
human_input = <function human_input.<locals>.send_human_input at 0x7a26a6f3e660>
dim_sim = <dimos.e2e_tests.dim_sim_client.DimSimClient object at 0x7a26a9336c60>
explore_house = <function explore_house.<locals>.explore at 0x7a26a6f3eb60>

    @pytest.mark.self_hosted_large
    def test_go_to_the_bed(lcm_spy, start_blueprint, human_input, dim_sim, explore_house) -> None:
        start_blueprint(
            "run",
            "unitree-go2-agentic",
            simulator="dimsim",
        )
        lcm_spy.save_topic(".../McpClient/on_system_modules/res")
        lcm_spy.wait_for_saved_topic(".../McpClient/on_system_modules/res", timeout=1200.0)
    
        explore_house()
    
        human_input("go to the bed")
    
>       lcm_spy.wait_until_odom_position(-3.567, -1.332, threshold=2, timeout=180)

dim_sim    = <dimos.e2e_tests.dim_sim_client.DimSimClient object at 0x7a26a9336c60>
explore_house = <function explore_house.<locals>.explore at 0x7a26a6f3eb60>
human_input = <function human_input.<locals>.send_human_input at 0x7a26a6f3e660>
lcm_spy    = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7a26aa0df5c0>
start_blueprint = <function start_blueprint.<locals>.set_name_and_start at 0x7a26a6f3e5c0>

dimos/e2e_tests/test_dimsim_spatial_memory.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/e2e_tests/lcm_spy.py:182: in wait_until_odom_position
    self.wait_for_message_result(
        predicate  = <function LcmSpy.wait_until_odom_position.<locals>.predicate at 0x7a26a6f3ed40>
        self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7a26aa0df5c0>
        threshold  = 2
        timeout    = 180
        x          = -3.567
        y          = -1.332
dimos/e2e_tests/lcm_spy.py:168: in wait_for_message_result
    self.wait_until(
        event      = <threading.Event at 0x7a26a93366f0: unset>
        fail_message = 'Failed to get to position x=-3.567, y=-1.332'
        listener   = <function LcmSpy.wait_for_message_result.<locals>.listener at 0x7a26a6f3ec00>
        predicate  = <function LcmSpy.wait_until_odom_position.<locals>.predicate at 0x7a26a6f3ed40>
        self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7a26aa0df5c0>
        timeout    = 180
        topic      = '/odom#geometry_msgs.PoseStamped'
        type       = <class 'dimos.msgs.geometry_msgs.PoseStamped.PoseStamped'>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7a26aa0df5c0>

    def wait_until(
        self,
        *,
        condition: Callable[[], bool],
        timeout: float,
        error_message: str,
        poll_interval: float = 0.1,
    ) -> None:
        start_time = time.time()
        while time.time() - start_time < timeout:
            if condition():
                return
            time.sleep(poll_interval)
>       raise TimeoutError(error_message)
E       TimeoutError: Failed to get to position x=-3.567, y=-1.332

condition  = <bound method Event.is_set of <threading.Event at 0x7a26a93366f0: unset>>
error_message = 'Failed to get to position x=-3.567, y=-1.332'
poll_interval = 0.1
self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7a26aa0df5c0>
start_time = 1782452239.9823167
timeout    = 180

dimos/e2e_tests/lcm_spy.py:105: TimeoutError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@jeff-hykin jeff-hykin marked this pull request as ready for review June 26, 2026 04:16
@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR mirrors the FAST-LIO cleanups from #2498 onto Point-LIO, keeping the two native LiDAR modules consistent in their configuration pattern, recorder structure, and TF frame scheme.

  • No-YAML config: default.yaml and config_path are deleted; all Point-LIO tuning parameters are now declared as typed Pydantic fields on PointLioConfig and passed to the C++ binary as plain --flag value CLI args. NativeModuleConfig.to_cli_args already handles list[float] fields (gravity, extrinsic vectors) by joining them with commas, matching the new parse_doubles helper in main.cpp.
  • Unified recorder: The bespoke PointlioPoseRecorder (pose_recorder.py) and the standalone time-aligning PointlioRecorder are merged into a single PointlioRecorder that extends the shared memory2 Recorder base; @pose_setter_for setters are updated to async def throughout (FAST-LIO, Go2, Unitree blueprints).
  • Frame scheme alignment: body_frame_id/body_start_frame_id are renamed to child_frame_id/frame_id; a new sensor_frame_id field stamps the published point-cloud header separately from the odometry frames. macOS unicast support is added to the virtual Mid-360 replayer and SDK config.

Confidence Score: 5/5

Safe to merge — changes are mechanical cleanups mirroring an already-landed FAST-LIO refactor with no novel logic.

The diff removes the YAML-loading path and replaces it with typed Pydantic fields whose CLI serialisation (including list[float] comma-joining for gravity/extrinsic vectors) is handled by the existing NativeModuleConfig.to_cli_args. The Recorder migration is structurally identical to the FAST-LIO change already in main, and the memory2/module.py async promotion is guarded by a runtime iscoroutinefunction check. The macOS unicast fix is a symmetrical change across Rust and C++ headers. No new algorithmic logic is introduced.

No files require special attention. The two pre-existing style observations in module.py and main.cpp (extrinsic vector validation and parse_doubles error surfacing) were noted in the prior review and remain unchanged.

Important Files Changed

Filename Overview
dimos/hardware/sensors/lidar/pointlio/module.py Replaces YAML config path with ~50 typed Pydantic fields on PointLioConfig; renames frame fields and adds sensor_frame_id; removes cli_exclude (no longer needed). List[float] fields serialise correctly via NativeModuleConfig.to_cli_args.
dimos/hardware/sensors/lidar/pointlio/cpp/main.cpp Replaces YAML loading with direct CLI arg parsing for all PointLioParams fields; adds parse_doubles helper; adds sensor_frame_id; renames body_frame_id to child_frame_id. Silent-discard on bad CSV input is a known pre-existing P2.
dimos/hardware/sensors/lidar/pointlio/recorder.py Drastically simplified: now extends Recorder base, removes bespoke sqlite/timestamp-alignment logic, uses async @pose_setter_for. Staleness tolerance check is intentionally dropped (mirrors FAST-LIO behaviour).
dimos/memory2/module.py PoseSetter type and _resolve_pose updated to async; pose_setter_for now validates iscoroutinefunction at decoration time; on_msg in _subscribe_port switched to async def and dispatched via process_observable.
dimos/hardware/sensors/lidar/pointlio/scripts/pcap_to_db.py Major refactor: removes --odom-stream-name/--lidar-stream-name/--force/--time-offset; adds per-field --tuning flags; --config is now a hidden YAML override file; adds LFS fetching for --pcap and --db; uses PointlioRecorder with remappings.
dimos/hardware/sensors/lidar/virtual_mid360/src/main.rs macOS-specific unicast path for point/IMU packets — on macOS data_dest is host_ip instead of the multicast group, matching the SDK config change in livox_sdk_config.hpp.
dimos/hardware/sensors/lidar/common/livox_sdk_config.hpp Platform-conditional multicast_ip: empty string on macOS (binds host_ip to receive unicasts) vs 224.1.1.5 on Linux. Correctly paired with the Rust-side change.
dimos/hardware/sensors/lidar/fastlio2/recorder.py Pose setters updated to async def, matching the new Recorder contract; _lidar_pose uses getattr defensive fallback matching PointlioRecorder style.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph Hardware["Hardware / Replay"]
        MID360["Mid-360 LiDAR\n(real or VirtualMid360 PCAP)"]
    end

    subgraph PointLIO["PointLio NativeModule (C++ subprocess)"]
        SDK["Livox SDK2 callbacks"]
        ALGO["Point-LIO IESKF estimator"]
        CLI["CLI args from PointLioConfig\n(no YAML)"]
        CLI --> ALGO
        SDK --> ALGO
        ALGO --> |"odometry (nav_msgs.Odometry)"|OUT_ODOM["Out: odometry"]
        ALGO --> |"lidar (sensor_msgs.PointCloud2)\nstamped with sensor_frame_id"|OUT_LIDAR["Out: lidar"]
        ALGO --> |"TF: frame_id → child_frame_id"|TF["TF bus"]
    end

    subgraph Recorder["PointlioRecorder (memory2 Recorder)"]
        IN_ODOM["In: pointlio_odometry\n(remapped ← odometry)"]
        IN_LIDAR["In: pointlio_lidar\n(remapped ← lidar)"]
        POSE_SETTER["@pose_setter_for async\n_odom_pose → caches _last_odom_pose\n_lidar_pose → returns cached pose"]
        DB["SQLite db\npointlio_odometry / pointlio_lidar tables\n(with pose anchor per row)"]
        IN_ODOM --> POSE_SETTER
        IN_LIDAR --> POSE_SETTER
        POSE_SETTER --> DB
    end

    MID360 -->|"UDP point/IMU\n(multicast Linux / unicast macOS)"| SDK
    OUT_ODOM -->|"autoconnect"| IN_ODOM
    OUT_LIDAR -->|"autoconnect"| IN_LIDAR
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    subgraph Hardware["Hardware / Replay"]
        MID360["Mid-360 LiDAR\n(real or VirtualMid360 PCAP)"]
    end

    subgraph PointLIO["PointLio NativeModule (C++ subprocess)"]
        SDK["Livox SDK2 callbacks"]
        ALGO["Point-LIO IESKF estimator"]
        CLI["CLI args from PointLioConfig\n(no YAML)"]
        CLI --> ALGO
        SDK --> ALGO
        ALGO --> |"odometry (nav_msgs.Odometry)"|OUT_ODOM["Out: odometry"]
        ALGO --> |"lidar (sensor_msgs.PointCloud2)\nstamped with sensor_frame_id"|OUT_LIDAR["Out: lidar"]
        ALGO --> |"TF: frame_id → child_frame_id"|TF["TF bus"]
    end

    subgraph Recorder["PointlioRecorder (memory2 Recorder)"]
        IN_ODOM["In: pointlio_odometry\n(remapped ← odometry)"]
        IN_LIDAR["In: pointlio_lidar\n(remapped ← lidar)"]
        POSE_SETTER["@pose_setter_for async\n_odom_pose → caches _last_odom_pose\n_lidar_pose → returns cached pose"]
        DB["SQLite db\npointlio_odometry / pointlio_lidar tables\n(with pose anchor per row)"]
        IN_ODOM --> POSE_SETTER
        IN_LIDAR --> POSE_SETTER
        POSE_SETTER --> DB
    end

    MID360 -->|"UDP point/IMU\n(multicast Linux / unicast macOS)"| SDK
    OUT_ODOM -->|"autoconnect"| IN_ODOM
    OUT_LIDAR -->|"autoconnect"| IN_LIDAR
Loading

Reviews (5): Last reviewed commit: "-" | Re-trigger Greptile

@leshy leshy enabled auto-merge (squash) June 26, 2026 04:22
@jeff-hykin jeff-hykin disabled auto-merge June 26, 2026 04:30
@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Jun 26, 2026
@leshy leshy enabled auto-merge (squash) June 26, 2026 05:55
@leshy leshy merged commit 73f47a1 into main Jun 26, 2026
44 of 45 checks passed
@leshy leshy deleted the jeff/feat/pointlio_native branch June 26, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Required CI checks have passed on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants