Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cf2c9c2
docs(cdr): restack WIP cleanup audit with current boundaries
TomCC7 Oct 21, 2026
71c0889
docs(cdr): refresh the remaining legacy import audit count
TomCC7 Oct 22, 2026
462b720
fix(cdr): integrate corrected library ownership into PR #4740
TomCC7 Oct 22, 2026
c401b31
release(cdr): consume published cdrgen 0.1.2 in PR #4740
TomCC7 Oct 22, 2026
b87cc73
ci(cdr): inherit explicit release acceptance entry point
TomCC7 Oct 22, 2026
c9a13b7
Use standard ROS TF messages and library-backed frame queries
TomCC7 Oct 22, 2026
dd33f7b
Pin native builds to the verified ROS TF SDK source
TomCC7 Oct 22, 2026
65b1d1d
Use standard ROS TF conventions in CDR stack layer #4740
TomCC7 Oct 22, 2026
cb4c4e9
Preserve the license header in generated SDK TF messages
TomCC7 Oct 22, 2026
c223f3a
Use standard ROS TF conventions in CDR stack layer #4740
TomCC7 Oct 22, 2026
d1bab1f
Pin TF library to its fully verified atomic batch patch
TomCC7 Oct 22, 2026
f7723ad
Keep TF publication errors consistent with other output ports
TomCC7 Oct 22, 2026
70b412e
Use the final verified TF SDK archive in native builds
TomCC7 Oct 22, 2026
9f24830
Use standard ROS TF conventions in CDR stack layer #4740
TomCC7 Oct 22, 2026
20d9ade
Require all native TF callers and port contracts in CDR acceptance
TomCC7 Oct 22, 2026
cc463c1
Use standard ROS TF conventions in CDR stack layer #4740
TomCC7 Oct 22, 2026
57c33b1
fix(cdr): share generated ROS messages with the native SDK
TomCC7 Oct 23, 2026
2685b12
build(cdr): pin the shared message source for native consumers
TomCC7 Oct 23, 2026
611f609
Integrate shared native CDR types into feature PR #4740
TomCC7 Oct 23, 2026
1642d25
build(cdr): prepare shared messages in the SDK flake
TomCC7 Oct 23, 2026
e7a15cb
build(cdr): expose SDK git hashes to crate2nix
TomCC7 Oct 23, 2026
4723af6
chore(cdr): reconcile the planner lock with its migrated source
TomCC7 Oct 23, 2026
e692010
Build shared native messages in feature PR #4740
TomCC7 Oct 23, 2026
b483aaa
refactor(perception): separate value helpers and TF timestamp behavior
TomCC7 Oct 23, 2026
bae8859
ci(cdr): verify the independently reviewed value adapters
TomCC7 Oct 23, 2026
6b768ad
Separate reviewed sensor behavior from CDR migration in PR #4740
TomCC7 Oct 23, 2026
a62d677
Keep the perception autofix ancestry in stack PR #4740
TomCC7 Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion .github/workflows/cdr-native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
with:
python-version: '3.12'
enable-cache: true
- uses: denoland/setup-deno@v2
with:
deno-version: v2.6.10
- name: Install build and media dependencies
run: |
sudo apt-get update
Expand All @@ -42,7 +45,36 @@ jobs:
dimos/message_utils/test_pointcloud.py \
dimos/message_utils/test_pointcloud_colors.py \
dimos/protocol/tf/test_buffer.py
- name: Test native SDK
- name: Test SDK and build native consumers
run: |
cargo test --locked --manifest-path native/rust/dimos-module/Cargo.toml
cargo test --locked --manifest-path native/rust/dimos-module-macros/Cargo.toml
cargo test --locked --manifest-path dimos/mapping/ray_tracing/rust/Cargo.toml --lib
cargo test --locked --manifest-path dimos/navigation/global_planner/mls_planner/rust/Cargo.toml --lib
cargo test --locked --manifest-path dimos/navigation/local_planner/rust/Cargo.toml --features module,test-bodies
cargo test --locked --manifest-path dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml --features module
cargo test --locked --manifest-path dimos/hardware/sensors/camera/v4l2/rust/Cargo.toml --lib
cargo check --locked --manifest-path dimos/perception/depth2depth_cloud/rust/Cargo.toml --lib
cargo check --locked --manifest-path dimos/hardware/sensors/camera/realsense/rust/Cargo.toml --all-targets --features docs-only
cargo build --locked --manifest-path dimos/mapping/ray_tracing/rust/Cargo.toml --bin voxel_ray_tracing
cargo build --locked --manifest-path dimos/navigation/global_planner/mls_planner/rust/Cargo.toml --bin mls_planner
cargo build --locked --manifest-path dimos/navigation/local_planner/rust/Cargo.toml --features module --bin local_planner
cargo build --locked --manifest-path dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml --features module --bin trajectory_follower
- name: Prepare DimSim dependencies
working-directory: misc/DimSim/cli
run: deno install --node-modules-dir=auto --entrypoint bridge/cdr_test.ts
- name: Exchange generated messages with real native and TypeScript consumers
run: |
export DIMOS_NATIVE_RAY_TRACING_BINARY="$CARGO_TARGET_DIR/debug/voxel_ray_tracing"
export DIMOS_NATIVE_MLS_BINARY="$CARGO_TARGET_DIR/debug/mls_planner"
export DIMOS_NATIVE_LOCAL_PLANNER_BINARY="$CARGO_TARGET_DIR/debug/local_planner"
export DIMOS_NATIVE_FOLLOWER_BINARY="$CARGO_TARGET_DIR/debug/trajectory_follower"
export DIMOS_DIMSIM_DENO="$(command -v deno)"
uv run --no-sync pytest --noconftest --import-mode=importlib -o addopts='' -q \
dimos/mapping/ray_tracing/test_generated_native.py \
dimos/navigation/global_planner/mls_planner/test_generated_native.py \
dimos/navigation/local_planner/test_generated_native.py \
dimos/robot/unitree/test_dimsim_connection.py \
dimos/navigation/trajectory_follower/fancy/test_generated_native.py \
dimos/hardware/sensors/camera/realsense/test_camera.py \
dimos/perception/depth2depth_cloud/test_depth2depth_cloud_config.py
38 changes: 38 additions & 0 deletions docs/development/cdr-cutover-status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# CDR cutover and legacy cleanup status

**WIP.** The shared factory supports generated CDR types and legacy LCM types.
The repository migration is incomplete. Keep legacy schemas, decoders and value
wrappers until their callers are migrated and verified.

## Inspect remaining boundaries

Run the static audit from this checkout. It does not import runtime modules or
contact hardware:

```sh
python scripts/audit_cdr_boundaries.py --output /tmp/cdr-boundaries.json
python scripts/audit_cdr_boundaries.py --check
```

`--check` returns nonzero while candidates remain. This snapshot has **312 legacy
In/Out declarations** and **998 legacy imports**. These are syntax matches, not
validated runtime failures. Internal driver values can be valid conversion
boundaries. Inspect complete blueprint port pairs before changing them.

## Current validation limits

The default-layer check has 37 passing tests and four failures:

- The Python `TransportRecorder` skips generated values on LCM and Zenoh. The new
Rust recording path is separate; this does not prove Python capture cutover.
- The XArm and Piper collection graphs do not expose the expected generated
aggregate `coordinator_joint_state` input on their recorder.

Agent, drone, Habitat and other legacy graphs still need migration. Original
work and prior heads remain in the consolidation backups. This restack does not
complete or discard those migrations.

Before deleting an API, migrate its callers and verify the selected graph,
capture/replay, source timestamps and schema identity on an installed package.
Keep the converter's explicit historical decode boundary for old recordings.
Nix hardware packaging and physical robot behavior are not verified here.
125 changes: 125 additions & 0 deletions scripts/audit_cdr_boundaries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Copyright 2026 Dimensional Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""Inventory legacy runtime imports and typed ports without importing robot modules."""

from __future__ import annotations

import argparse
import ast
from collections import Counter
import json
from pathlib import Path


def qualified(node: ast.expr, imports: dict[str, str]) -> str:
if isinstance(node, ast.Name):
return imports.get(node.id, node.id)
if isinstance(node, ast.Attribute):
return qualified(node.value, imports) + "." + node.attr
return ast.unparse(node)


def legacy(name: str) -> bool:
if name == "dimos_lcm" or name.startswith("dimos_lcm."):
return True
parts = name.split(".")
return len(parts) >= 3 and parts[:2] == ["dimos", "msgs"] and parts[2].endswith("_msgs")


def audit(root: Path) -> dict:
imports_found = []
ports = []
for path in sorted((root / "dimos").rglob("*.py")):
relative = path.relative_to(root)
if path.name.startswith(("test_", "demo_", "tool_")) or path.name == "conftest.py":
continue
if relative.parts[:2] == ("dimos", "msgs"):
continue
tree = ast.parse(path.read_text(), filename=str(relative))
imports = {}
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom):
for alias in node.names:
full = f"{node.module}.{alias.name}"
imports[alias.asname or alias.name] = full
if legacy(full):
imports_found.append(
{"file": str(relative), "line": node.lineno, "symbol": full}
)
elif isinstance(node, ast.Import):
for alias in node.names:
imports[alias.asname or alias.name.split(".")[0]] = (
alias.name if alias.asname else alias.name.split(".")[0]
)
if legacy(alias.name):
imports_found.append(
{"file": str(relative), "line": node.lineno, "symbol": alias.name}
)
for node in ast.walk(tree):
if not isinstance(node, ast.AnnAssign) or not isinstance(
node.annotation, ast.Subscript
):
continue
annotation = node.annotation
direction = qualified(annotation.value, imports)
if direction not in {"dimos.core.stream.In", "dimos.core.stream.Out"}:
continue
candidates = [
qualified(n, imports)
for n in ast.walk(annotation.slice)
if isinstance(n, (ast.Name, ast.Attribute))
]
types = sorted({name for name in candidates if legacy(name)})
if types:
ports.append(
{
"file": str(relative),
"line": node.lineno,
"port": ast.unparse(node.target),
"direction": direction.rsplit(".", 1)[1],
"legacy_types": types,
}
)
return {
"status": "unfinished" if ports or imports_found else "clear",
"method": "Static Python import and typed In/Out scan; no runtime graph or hardware imports. Internal driver values are not automatically wire defects.",
"legacy_port_count": len(ports),
"legacy_import_count": len(imports_found),
"ports_by_subsystem": dict(sorted(Counter(p["file"].split("/")[1] for p in ports).items())),
"legacy_ports": ports,
"legacy_imports": imports_found,
}


def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1])
parser.add_argument("--output", type=Path)
parser.add_argument(
"--check", action="store_true", help="Fail while any legacy imports or ports remain."
)
args = parser.parse_args()
report = audit(args.root.resolve())
text = json.dumps(report, indent=2) + "\n"
if args.output:
args.output.write_text(text)
else:
print(text, end="")
return int(args.check and report["status"] != "clear")


if __name__ == "__main__":
raise SystemExit(main())
Loading