From 20561e7a124c2f4c6d91d1b84f472810340461aa Mon Sep 17 00:00:00 2001 From: chipunderblade Date: Thu, 3 Sep 2026 16:28:23 +0800 Subject: [PATCH 1/3] feat!: migrate Forge to Dora 1.0 --- .github/workflows/ci.yml | 10 +-- CHANGELOG.md | 29 +++++++- Cargo.lock | 72 ++++++------------- README.md | 30 ++++---- RELEASING.md | 38 +++++----- SECURITY.md | 4 +- cpp/forge_msgs/CMakeLists.txt | 2 +- cpp/forge_robot/CMakeLists.txt | 6 +- cpp/forge_robot/README.md | 22 +++--- ...Dora041Targets.cmake => DoraTargets.cmake} | 11 +-- crates/forge_msgs/Cargo.toml | 6 +- crates/forge_msgs/README.md | 2 + packages/msgs/pyproject.toml | 2 +- packages/policy/pyproject.toml | 6 +- packages/robot/pyproject.toml | 6 +- packages/tool/README.md | 10 +-- packages/tool/pyproject.toml | 4 +- pyproject.toml | 10 +-- scripts/check_forge_msgs_schema.py | 44 ++++++++---- scripts/check_python_distributions.py | 14 +++- scripts/check_release_versions.py | 48 +++++++++---- uv.lock | 39 +++++----- versions.toml | 11 +-- 23 files changed, 242 insertions(+), 184 deletions(-) rename cpp/forge_robot/cmake/{Dora041Targets.cmake => DoraTargets.cmake} (94%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1d3ee5..4752142 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,8 +72,10 @@ jobs: - name: Check out repository uses: actions/checkout@v4 - - name: Set up Rust for Dora C++ API - uses: dtolnay/rust-toolchain@stable + - name: Set up Rust 1.95 for Dora C++ API + uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.95.0" - name: Set up C++ dependencies uses: mamba-org/setup-micromamba@v2 @@ -127,13 +129,13 @@ jobs: shell: bash -el {0} run: ctest --test-dir cpp/forge_robot/build --output-on-failure - - name: Configure C++ forge_robot Dora v0.4.1 runner + - name: Configure C++ forge_robot Dora v1.0.0 runner shell: bash -el {0} run: >- cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora -G Ninja -DFORGE_ROBOT_CPP_WITH_DORA=ON -DFORGE_ROBOT_CPP_BUILD_TESTS=ON - - name: Compile C++ forge_robot Dora v0.4.1 runner + - name: Compile C++ forge_robot Dora v1.0.0 runner shell: bash -el {0} run: cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile diff --git a/CHANGELOG.md b/CHANGELOG.md index 294ac9e..4d2ad82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,36 @@ # Changelog -Forge package families are versioned independently. Implementations of the same logical family across Python, Rust, C++, and the language-neutral interface contract share one version and one protected GitLab tag. +Forge package families are versioned independently. Python, Rust, and C++ implementations of the same logical family share one package version and protected GitLab tag; language-neutral interface versions are tracked separately. ## Unreleased +## forge-policy 2.0.0 - 2026-09-03 + +Protected tag: `forge-policy-v2.0.0` + +- Migrate the Python Dora runner dependency from `dora-rs 0.4.1` to `1.0.0`. +- Require the Forge Msgs 2 carrier line. + +## forge-robot 2.0.0 - 2026-09-03 + +Protected tag: `forge-robot-v2.0.0` + +- Migrate the Python Dora runner dependency and optional C++ node bridge from Dora 0.4.1 to 1.0.0. +- Require the Forge Msgs 2 carrier line while keeping the driver contract and node input/output semantics unchanged. + +## forge-msgs 2.0.0 - 2026-09-03 + +Protected tag: `forge-msgs-v2.0.0` + +- Move the public Rust `RecordBatch` API from Arrow 54 to Arrow 59 for Dora 1.0 interoperability. +- Preserve the cross-language `forge_msgs.v1` wire schema; the package major and wire-schema version are now tracked independently. + +## forge-tool 2.0.0 - 2026-09-03 + +Protected tag: `forge-tool-v2.0.0` + +- Move the optional Dora carrier integration to the Forge Msgs 2 line. + ## forge-tool 1.0.0 - 2026-08-27 Protected tag: `forge-tool-v1.0.0` diff --git a/Cargo.lock b/Cargo.lock index f8246b4..9673a39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,9 +42,9 @@ dependencies = [ [[package]] name = "arrow-array" -version = "54.3.1" +version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12fcdb3f1d03f69d3ec26ac67645a8fe3f878d77b5ebb0b15d64a116c212985" +checksum = "1e5f6adeffdf587d7a31db5d2266189624b526730cd3627f9ff9fedae97ad584" dependencies = [ "ahash", "arrow-buffer", @@ -53,37 +53,41 @@ dependencies = [ "chrono", "half", "hashbrown", - "num", + "num-complex", + "num-integer", + "num-traits", ] [[package]] name = "arrow-buffer" -version = "54.3.1" +version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "263f4801ff1839ef53ebd06f99a56cecd1dbaf314ec893d93168e2e860e0291c" +checksum = "097d193003ce7995d5d087089069ec2a6e0187faf5a6f8c9f38af2645d987182" dependencies = [ "bytes", "half", - "num", + "num-bigint", + "num-traits", ] [[package]] name = "arrow-data" -version = "54.3.1" +version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cfdd7d99b4ff618f167e548b2411e5dd2c98c0ddebedd7df433d34c20a4429" +checksum = "9ba2f832eaeca24b8f26143dba750e42ee4ab51cf7d65e701ca9607cfda9f358" dependencies = [ "arrow-buffer", "arrow-schema", "half", - "num", + "num-integer", + "num-traits", ] [[package]] name = "arrow-schema" -version = "54.3.1" +version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cfaf5e440be44db5413b75b72c2a87c1f8f0627117d110264048f2969b99e9" +checksum = "10fab8d4563491417ba801fab29d205104d20d4bdf37bda6cd1cf425cff598cd" [[package]] name = "autocfg" @@ -216,7 +220,7 @@ dependencies = [ [[package]] name = "forge_msgs" -version = "1.3.0" +version = "2.0.0" dependencies = [ "arrow-array", "arrow-schema", @@ -272,9 +276,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "iana-time-zone" @@ -424,25 +428,11 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" dependencies = [ "num-integer", "num-traits", @@ -466,28 +456,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" diff --git a/README.md b/README.md index 0882468..52c77eb 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ family across Python, Rust, C++, and the language-neutral interface remain synch unrelated families may release at different rates. Each release is identified by a protected family tag such as -`forge-msgs-v1.3.0`; Tool releases use `forge-tool-v`. Historical generic tags +`forge-msgs-v2.0.0`; Tool releases use `forge-tool-v`. Historical generic tags such as `v1.0.0` belong to an earlier repository layout and do not identify these releases. @@ -89,11 +89,11 @@ forge/ - A C++20-capable compiler and CMake 3.20 or newer for C++ packages; `cpp/forge_msgs` and its dependents require C++20 - Apache Arrow C++ for `cpp/forge_msgs` -- Rust/Cargo and network access, or a local Dora `v0.4.1` checkout, for the +- Rust 1.95 or newer and network access, or a local Dora `v1.0.0` checkout, for the optional C++ `forge_robot` Dora runner - [`uv`](https://docs.astral.sh/uv/) for Python dependency management -- Dora runtime when running real nodes (`dora-rs==0.4.1` is used by the Python - node packages) +- Dora runtime 1.0.0 when running real nodes (`dora-rs==1.0.0` is used by the + Python node packages) ## Installation @@ -145,7 +145,7 @@ cmake --build cpp/forge_robot/build ``` Build and compile-link validate the C++ `forge_robot` Dora runner against Dora -`v0.4.1`: +`v1.0.0`: ```bash cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ @@ -155,14 +155,14 @@ cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compil ``` The C++ Dora API headers are generated by Dora's CXX bridge. By default, -`cpp/forge_robot` clones `https://github.com/dora-rs/dora.git` at tag -`v0.4.1`; it does not use Dora `main`. To use a local Dora `v0.4.1` checkout: +`cpp/forge_robot` downloads the Dora `v1.0.0` source archive with a pinned SHA256; +it does not use Dora `main`. To use a local Dora `v1.0.0` checkout: ```bash -git clone --branch v0.4.1 https://github.com/dora-rs/dora.git /path/to/dora-v0.4.1 +git clone --branch v1.0.0 https://github.com/dora-rs/dora.git /path/to/dora-v1.0.0 cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v0.4.1 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile ``` @@ -174,7 +174,7 @@ include(FetchContent) FetchContent_Declare( forge GIT_REPOSITORY https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git - GIT_TAG forge-msgs-v1.3.0 + GIT_TAG forge-msgs-v2.0.0 SOURCE_SUBDIR cpp/forge_msgs ) FetchContent_MakeAvailable(forge) @@ -214,7 +214,7 @@ include(FetchContent) FetchContent_Declare( forge_robot GIT_REPOSITORY https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git - GIT_TAG forge-robot-v1.0.1 + GIT_TAG forge-robot-v2.0.0 SOURCE_SUBDIR cpp/forge_robot ) FetchContent_MakeAvailable(forge_robot) @@ -236,20 +236,20 @@ the public umbrella header: For packages that only implement driver logic, safety clipping, or Arrow validation, keep `FORGE_ROBOT_CPP_WITH_DORA` off. To compile a Dora runner in the downstream package, enable the option at configure time and either let CMake -download Dora `v0.4.1` or point `DORA_ROOT_DIR` at a local Dora `v0.4.1` +download Dora `v1.0.0` or point `DORA_ROOT_DIR` at a local Dora `v1.0.0` checkout: ```bash cmake -S . -B build \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v0.4.1 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 ``` ## Testing Verify that every Python, Rust, and C++ implementation matches its package -family version in `versions.toml`, including the Msgs interface major and lock -files: +family version in `versions.toml`, including the independently tracked Msgs +interface version and lock files: ```bash python scripts/check_release_versions.py diff --git a/RELEASING.md b/RELEASING.md index b813f3a..ca9c6cd 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -9,11 +9,14 @@ Forge is a Monorepo with independently versioned logical package families. Imple ```toml [packages] common = "1.0.1" -msgs = "1.3.0" -robot = "1.0.1" -policy = "1.0.1" +msgs = "2.0.0" +robot = "2.0.0" +policy = "2.0.0" kinematics = "1.0.1" -tool = "0.1.0" +tool = "2.0.0" + +[interfaces] +msgs = 1 ``` The root `pyproject.toml` is a virtual uv workspace, not a published `forge` Python distribution. Its project version is workspace tooling metadata and is not a package-family release version. @@ -29,7 +32,7 @@ The root `pyproject.toml` is a virtual uv workspace, not a published `forge` Pyt | Kinematics | `packages/kinematics` | `forge-kinematics-v` | | Tool | `interfaces/forge_tool`, `packages/tool` | `forge-tool-v` | -Do not create separate Python/Rust/C++ tags for one family. `forge-msgs-v1.0.0`, for example, identifies the v1 schema plus all three language implementations at the tagged commit. +Do not create separate Python/Rust/C++ tags for one family. `forge-msgs-v2.0.0`, for example, identifies the Msgs 2 language implementations at the tagged commit. Package majors and wire-schema versions are tracked independently because a language API can break while the cross-language schema remains compatible. Do not use or move historical generic tags such as `v1.0.0`. They belong to an earlier repository layout. All new release tags must use a family namespace. @@ -37,11 +40,11 @@ The initial five `1.0.0` tags may point to the same clean commit. Tool's first r ```text forge-common-v1.0.1 -forge-msgs-v1.3.0 -forge-robot-v1.0.0 -forge-policy-v1.1.0 +forge-msgs-v2.0.0 +forge-robot-v2.0.0 +forge-policy-v2.0.0 forge-kinematics-v1.0.2 -forge-tool-v0.1.0 +forge-tool-v2.0.0 ``` ## Downstream dependencies @@ -50,7 +53,7 @@ Use the tag for the exact family being consumed: ```toml [tool.uv.sources] -forge-msgs = { git = "https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git", tag = "forge-msgs-v1.0.1", subdirectory = "packages/msgs" } +forge-msgs = { git = "https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git", tag = "forge-msgs-v2.0.0", subdirectory = "packages/msgs" } forge-common = { git = "https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git", tag = "forge-common-v1.0.1", subdirectory = "packages/common" } ``` @@ -66,17 +69,16 @@ A downstream `uv.lock` or `Cargo.lock` records the exact commit resolved from ea 6. Run the version gate and relevant tests before review. When one family introduces a dependency whose minimum version is being released from -the same revision, publish the dependency family first. For the coordinated Msgs 1.2.0 -and Tool 0.1.0 releases, `forge-msgs 1.2.0` must be available before publishing -`forge-tool 0.1.0`, so `forge-tool[dora]` can resolve its `forge-msgs>=1.2.0,<2` -requirement. +the same revision, publish the dependency family first. For the coordinated 2.0 migration, +`forge-msgs 2.0.0` must be available before publishing `forge-tool 2.0.0`, +`forge-policy 2.0.0`, or `forge-robot 2.0.0`. -`./scripts/check_release_versions.py` verifies family synchronization, workspace membership, internal Python requirements, uv/Cargo locks, and the Msgs interface major. In GitLab and GitHub tag pipelines it also reads `CI_COMMIT_TAG` or `GITHUB_REF_NAME` and rejects unknown families, non-SemVer tags, and tags whose version differs from `versions.toml`. +`./scripts/check_release_versions.py` verifies family synchronization, workspace membership, internal Python requirements, uv/Cargo locks, and the independently declared Msgs interface version. In GitLab and GitHub tag pipelines it also reads `CI_COMMIT_TAG` or `GITHUB_REF_NAME` and rejects unknown families, non-SemVer tags, and tags whose version differs from `versions.toml`. A tag can be checked locally before creation: ```bash -./scripts/check_release_versions.py --tag forge-msgs-v1.3.0 +./scripts/check_release_versions.py --tag forge-msgs-v2.0.0 ``` ## Release requirements @@ -272,8 +274,8 @@ After review: When one release depends on another version from the same commit, do not batch-push the tags. Push and publish the dependency tag first, verify the exact package version from -the public registry, and only then push the dependent tag. For Msgs 1.2.0 and Tool 0.1.0, -publish `forge-msgs-v1.2.0` before `forge-tool-v0.1.0`. +the public registry, and only then push the dependent tag. For the 2.0 migration, publish +`forge-msgs-v2.0.0` before the Tool, Policy, and Robot 2.0 tags. The initial five `1.0.0` baseline tags have already been created: diff --git a/SECURITY.md b/SECURITY.md index 11b0d54..fac8904 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,9 +2,9 @@ ## Supported Versions -Forge supports the latest release in each `1.x` package-family line. Security +Forge supports the latest release in each package-family line. Security fixes are prepared on the development branch and released under protected -family tags such as `forge-msgs-v1.0.0`. Historical generic repository-era tags +family tags such as `forge-msgs-v2.0.0`. Historical generic repository-era tags are not part of these support lines. ## Reporting a Vulnerability diff --git a/cpp/forge_msgs/CMakeLists.txt b/cpp/forge_msgs/CMakeLists.txt index de00e46..3426625 100644 --- a/cpp/forge_msgs/CMakeLists.txt +++ b/cpp/forge_msgs/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) -project(forge_msgs_cpp VERSION 1.3.0 LANGUAGES CXX) +project(forge_msgs_cpp VERSION 2.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/cpp/forge_robot/CMakeLists.txt b/cpp/forge_robot/CMakeLists.txt index bac70e3..6ebde4d 100644 --- a/cpp/forge_robot/CMakeLists.txt +++ b/cpp/forge_robot/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) -project(forge_robot_cpp VERSION 1.0.1 LANGUAGES CXX) +project(forge_robot_cpp VERSION 2.0.0 LANGUAGES CXX) find_package(Python3 COMPONENTS Interpreter) @@ -28,14 +28,14 @@ set(FORGE_ROBOT_CPP_SOURCES if(FORGE_ROBOT_CPP_WITH_DORA) if(NOT (DORA_CXX_INCLUDE_DIR AND DORA_CXX_LIBRARY)) - include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Dora041Targets.cmake) + include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/DoraTargets.cmake) set(DORA_CXX_INCLUDE_DIR ${dora_cxx_include_dir}) set(DORA_CXX_LIBRARY dora_node_api_cxx) set(DORA_CXX_BRIDGE_SOURCE ${node_bridge}) elseif(NOT DORA_CXX_BRIDGE_SOURCE) message(FATAL_ERROR "Pre-generated Dora CXX artifacts require DORA_CXX_BRIDGE_SOURCE. " - "Omit DORA_CXX_INCLUDE_DIR/DORA_CXX_LIBRARY to use the built-in Dora v0.4.1 helper." + "Omit DORA_CXX_INCLUDE_DIR/DORA_CXX_LIBRARY to use the built-in Dora v1.0.0 helper." ) endif() list(APPEND FORGE_ROBOT_CPP_SOURCES src/node_runner.cpp) diff --git a/cpp/forge_robot/README.md b/cpp/forge_robot/README.md index 39da421..9f3f3b4 100644 --- a/cpp/forge_robot/README.md +++ b/cpp/forge_robot/README.md @@ -34,7 +34,7 @@ The optional Dora runner mirrors the Python `forge_robot` node loop: The driver interfaces, clipping helpers, and Arrow validation do not depend on Dora headers. `RunDoraRobotNode()` is compiled only when `FORGE_ROBOT_CPP_WITH_DORA=ON`. The Dora C++ API is generated from Dora -`v0.4.1` with CXX bridge sources, so the default build path is pinned to that +`v1.0.0` with CXX bridge sources, so the default build path is pinned to that tag instead of Dora `main`. ## Build @@ -47,7 +47,7 @@ cmake --build cpp/forge_robot/build ctest --test-dir cpp/forge_robot/build --output-on-failure ``` -Build and compile-link validate the Dora runner against Dora `v0.4.1`: +Build and compile-link validate the Dora runner against Dora `v1.0.0`: ```bash cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ @@ -56,15 +56,15 @@ cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile ``` -The command above downloads Dora from GitHub at tag `v0.4.1` and builds -`dora-node-api-cxx` with Cargo. To avoid downloading during configure/build, -provide a local Dora `v0.4.1` checkout: +The command above downloads the SHA256-pinned Dora `v1.0.0` source archive and +builds `dora-node-api-cxx` with Cargo. To avoid downloading during +configure/build, provide a local Dora `v1.0.0` checkout: ```bash -git clone --branch v0.4.1 https://github.com/dora-rs/dora.git /path/to/dora-v0.4.1 +git clone --branch v1.0.0 https://github.com/dora-rs/dora.git /path/to/dora-v1.0.0 cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v0.4.1 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile ``` @@ -84,7 +84,7 @@ include(FetchContent) FetchContent_Declare( forge_robot GIT_REPOSITORY https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git - GIT_TAG forge-robot-v1.0.1 + GIT_TAG forge-robot-v2.0.0 SOURCE_SUBDIR cpp/forge_robot ) FetchContent_MakeAvailable(forge_robot) @@ -112,11 +112,11 @@ interfaces, safety clipping, or Arrow validation. This avoids pulling in Rust/Cargo and the Dora C++ API build. When enabling the Dora runner from a consumer project, pass -`FORGE_ROBOT_CPP_WITH_DORA=ON`. The default path builds against Dora `v0.4.1`; -pass `DORA_ROOT_DIR=/path/to/dora-v0.4.1` to use an existing local checkout. +`FORGE_ROBOT_CPP_WITH_DORA=ON`. The default path builds against Dora `v1.0.0`; +pass `DORA_ROOT_DIR=/path/to/dora-v1.0.0` to use an existing local checkout. ```bash cmake -S . -B build \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v0.4.1 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 ``` diff --git a/cpp/forge_robot/cmake/Dora041Targets.cmake b/cpp/forge_robot/cmake/DoraTargets.cmake similarity index 94% rename from cpp/forge_robot/cmake/Dora041Targets.cmake rename to cpp/forge_robot/cmake/DoraTargets.cmake index f0718aa..05bad78 100644 --- a/cpp/forge_robot/cmake/Dora041Targets.cmake +++ b/cpp/forge_robot/cmake/DoraTargets.cmake @@ -1,10 +1,10 @@ -set(DORA_ROOT_DIR "" CACHE PATH "Path to the root of a local Dora v0.4.1 checkout") +set(DORA_ROOT_DIR "" CACHE PATH "Path to the root of a local Dora v1.0.0 checkout") set(dora_c_include_dir "${CMAKE_CURRENT_BINARY_DIR}/include/c") set(dora_cxx_include_dir "${CMAKE_CURRENT_BINARY_DIR}/include/cxx") set(node_bridge "${CMAKE_CURRENT_BINARY_DIR}/node_bridge.cc") set(operator_bridge "${CMAKE_CURRENT_BINARY_DIR}/operator_bridge.cc") -set(dora_bridge_copy_script "${CMAKE_CURRENT_BINARY_DIR}/copy_dora041_bridges.cmake") +set(dora_bridge_copy_script "${CMAKE_CURRENT_BINARY_DIR}/copy_dora_bridges.cmake") file(WRITE ${dora_bridge_copy_script} [=[ file(GLOB node_bridge_sources "${DORA_TARGET_DIR}/debug/build/dora-node-api-cxx-*/out/cxxbridge/sources/dora-node-api-cxx/src/lib.rs.cc") @@ -17,7 +17,7 @@ list(LENGTH node_bridge_headers node_bridge_header_count) list(LENGTH operator_bridge_sources operator_bridge_source_count) list(LENGTH operator_bridge_headers operator_bridge_header_count) if(node_bridge_source_count EQUAL 0 OR node_bridge_header_count EQUAL 0 OR operator_bridge_source_count EQUAL 0 OR operator_bridge_header_count EQUAL 0) - message(FATAL_ERROR "Could not find Dora v0.4.1 CXX bridge outputs in ${DORA_TARGET_DIR}") + message(FATAL_ERROR "Could not find Dora v1.0.0 CXX bridge outputs in ${DORA_TARGET_DIR}") endif() list(GET node_bridge_sources 0 node_bridge_source) @@ -68,8 +68,9 @@ if(DORA_ROOT_DIR) else() ExternalProject_Add(Dora PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dora - GIT_REPOSITORY https://github.com/dora-rs/dora.git - GIT_TAG v0.4.1 + URL https://codeload.github.com/dora-rs/dora/tar.gz/refs/tags/v1.0.0 + URL_HASH SHA256=2e84db8afde1e2d6e73fd03e62a1fbe6e43442a408a098c12f30484e367ab183 + DOWNLOAD_EXTRACT_TIMESTAMP TRUE BUILD_IN_SOURCE TRUE CONFIGURE_COMMAND "" BUILD_COMMAND diff --git a/crates/forge_msgs/Cargo.toml b/crates/forge_msgs/Cargo.toml index 7b6c7fb..c69855f 100644 --- a/crates/forge_msgs/Cargo.toml +++ b/crates/forge_msgs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forge_msgs" -version = "1.3.0" +version = "2.0.0" edition.workspace = true license.workspace = true authors.workspace = true @@ -13,8 +13,8 @@ name = "forge_msgs" path = "src/lib.rs" [dependencies] -arrow-array = "54.3.1" -arrow-schema = "54.3.1" +arrow-array = "59.1" +arrow-schema = "59.1" bytes = "1.10.0" ndarray = "0.17.2" image = { version = "0.25.9", default-features = false, features = ["png", "jpeg"] } diff --git a/crates/forge_msgs/README.md b/crates/forge_msgs/README.md index 24c8034..a5d078b 100644 --- a/crates/forge_msgs/README.md +++ b/crates/forge_msgs/README.md @@ -25,6 +25,8 @@ The crate currently exports: Each message type is designed for single-row Arrow `RecordBatch` interchange. +Forge Msgs 2 uses Arrow 59 so its public Rust `RecordBatch` API aligns with Dora 1.0 nodes. + `PointCloudBuffer` transports decoded Cartesian point records whose dynamic fixed-width fields and strides still matter across a node boundary. Its borrowed `PointCloudBufferView` performs checked, endian-aware scalar and fixed-array diff --git a/packages/msgs/pyproject.toml b/packages/msgs/pyproject.toml index d81a129..21fa14d 100644 --- a/packages/msgs/pyproject.toml +++ b/packages/msgs/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge-msgs" -version = "1.3.0" +version = "2.0.0" description = "Python message models and Arrow serialization for Forge robotics dataflows." readme = "README.md" authors = [ diff --git a/packages/policy/pyproject.toml b/packages/policy/pyproject.toml index fa4b342..723152d 100644 --- a/packages/policy/pyproject.toml +++ b/packages/policy/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge-policy" -version = "1.0.1" +version = "2.0.0" description = "Reusable policy node protocol and Dora runner for Forge robotics applications." readme = "README.md" requires-python = ">=3.12" @@ -10,8 +10,8 @@ authors = [ { name = "X-ERA" } ] dependencies = [ - "dora-rs==0.4.1", - "forge-msgs>=1.0.0,<2", + "dora-rs==1.0.0", + "forge-msgs>=2.0.0,<3", ] [project.urls] diff --git a/packages/robot/pyproject.toml b/packages/robot/pyproject.toml index c750082..efdf202 100644 --- a/packages/robot/pyproject.toml +++ b/packages/robot/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge-robot" -version = "1.0.1" +version = "2.0.0" description = "Reusable robot driver protocols, base classes, and Dora node helpers for Forge." readme = "README.md" requires-python = ">=3.12" @@ -10,8 +10,8 @@ authors = [ { name = "X-ERA" } ] dependencies = [ - "dora-rs==0.4.1", - "forge-msgs>=1.0.0,<2", + "dora-rs==1.0.0", + "forge-msgs>=2.0.0,<3", ] [project.urls] diff --git a/packages/tool/README.md b/packages/tool/README.md index 82d5205..a1f0733 100644 --- a/packages/tool/README.md +++ b/packages/tool/README.md @@ -413,10 +413,10 @@ Explicitly import from `forge_tool.dora`: ## Protocol documentation -- [Tool documentation index](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v1.0.0/interfaces/forge_tool/README.md) -- [Architecture](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v1.0.0/interfaces/forge_tool/ARCHITECTURE.md) -- [ToolEndpoint Wire protocol](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v1.0.0/interfaces/forge_tool/PROTOCOL.md) -- [Canonical `ToolMessage` Arrow schema](https://github.com/Forgelab-Robotics/forge/blob/forge-msgs-v1.2.0/interfaces/forge_msgs/tool.v1.yaml) +- [Tool documentation index](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v2.0.0/interfaces/forge_tool/README.md) +- [Architecture](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v2.0.0/interfaces/forge_tool/ARCHITECTURE.md) +- [ToolEndpoint Wire protocol](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v2.0.0/interfaces/forge_tool/PROTOCOL.md) +- [Canonical `ToolMessage` Arrow schema](https://github.com/Forgelab-Robotics/forge/blob/forge-msgs-v2.0.0/interfaces/forge_msgs/tool.v1.yaml) ## Development @@ -428,4 +428,4 @@ uv run pytest packages/tool/tests ## License -Apache-2.0. See the release [LICENSE](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v1.0.0/LICENSE). +Apache-2.0. See the release [LICENSE](https://github.com/Forgelab-Robotics/forge/blob/forge-tool-v2.0.0/LICENSE). diff --git a/packages/tool/pyproject.toml b/packages/tool/pyproject.toml index e670c69..f9e34bf 100644 --- a/packages/tool/pyproject.toml +++ b/packages/tool/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge-tool" -version = "1.0.0" +version = "2.0.0" description = "Typed endpoint contracts for Forge query, action, and session tools." readme = "README.md" requires-python = ">=3.12" @@ -12,7 +12,7 @@ authors = [ dependencies = [] [project.optional-dependencies] -dora = ["forge-msgs>=1.2.0,<2"] +dora = ["forge-msgs>=2.0.0,<3"] [tool.uv.sources] forge-msgs = { workspace = true } diff --git a/pyproject.toml b/pyproject.toml index 61c88e7..246077c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge" -version = "1.0.0" +version = "2.0.0" description = "Core message schemas and Dora node helpers for Forge robotics applications." readme = "README.md" requires-python = ">=3.12" @@ -10,10 +10,10 @@ authors = [ ] dependencies = [ "forge-common>=1.0.0,<2", - "forge-msgs>=1.0.0,<2", - "forge-policy>=1.0.0,<2", - "forge-robot>=1.0.0,<2", - "forge-tool>=1.0.0,<2", + "forge-msgs>=2.0.0,<3", + "forge-policy>=2.0.0,<3", + "forge-robot>=2.0.0,<3", + "forge-tool>=2.0.0,<3", ] [dependency-groups] diff --git a/scripts/check_forge_msgs_schema.py b/scripts/check_forge_msgs_schema.py index 47d17c0..f97cdc1 100644 --- a/scripts/check_forge_msgs_schema.py +++ b/scripts/check_forge_msgs_schema.py @@ -1,6 +1,7 @@ from __future__ import annotations import sys +import tomllib from pathlib import Path from typing import Any @@ -8,7 +9,7 @@ ROOT = Path(__file__).resolve().parents[1] SCHEMA_DIR = ROOT / "interfaces" / "forge_msgs" -MANIFEST_PATH = SCHEMA_DIR / "forge_msgs.v1.yaml" +VERSIONS_PATH = ROOT / "versions.toml" ALLOWED_IMPLEMENTATIONS = {"python", "rust", "cpp"} @@ -16,6 +17,17 @@ class SchemaError(ValueError): pass +def _interface_version() -> int: + try: + with VERSIONS_PATH.open("rb") as handle: + value = tomllib.load(handle)["interfaces"]["msgs"] + except (OSError, KeyError, tomllib.TOMLDecodeError) as exc: + raise SchemaError(f"{VERSIONS_PATH}: failed to load Msgs interface version: {exc}") from exc + if isinstance(value, bool) or not isinstance(value, int) or value < 1: + raise SchemaError(f"{VERSIONS_PATH}: interfaces.msgs must be a positive integer") + return value + + def _load_yaml(path: Path) -> dict[str, Any]: try: value = yaml.safe_load(path.read_text(encoding="utf-8")) @@ -72,19 +84,25 @@ def _validate_message(path: Path, name: str, message: Any) -> None: def validate() -> list[str]: - manifest = _load_yaml(MANIFEST_PATH) + interface_version = _interface_version() + manifest_path = SCHEMA_DIR / f"forge_msgs.v{interface_version}.yaml" + manifest = _load_yaml(manifest_path) version = manifest.get("version") package = manifest.get("package") if not isinstance(version, int) or version < 1: - raise SchemaError(f"{MANIFEST_PATH}: version must be a positive integer") + raise SchemaError(f"{manifest_path}: version must be a positive integer") + if version != interface_version: + raise SchemaError( + f"{manifest_path}: version must match versions.toml interfaces.msgs={interface_version}" + ) if not isinstance(package, str) or not package: - raise SchemaError(f"{MANIFEST_PATH}: package must be a non-empty string") + raise SchemaError(f"{manifest_path}: package must be a non-empty string") schema_files = manifest.get("schema_files") if not isinstance(schema_files, dict) or not schema_files: - raise SchemaError(f"{MANIFEST_PATH}: schema_files must be a non-empty mapping") + raise SchemaError(f"{manifest_path}: schema_files must be a non-empty mapping") if "common" not in schema_files: - raise SchemaError(f"{MANIFEST_PATH}: schema_files must include common") + raise SchemaError(f"{manifest_path}: schema_files must include common") seen_messages: dict[str, Path] = {} loaded_files: set[Path] = set() @@ -92,17 +110,17 @@ def validate() -> list[str]: for domain, filename in schema_files.items(): if not isinstance(domain, str) or not domain: - raise SchemaError(f"{MANIFEST_PATH}: schema domain names must be non-empty") + raise SchemaError(f"{manifest_path}: schema domain names must be non-empty") if not isinstance(filename, str) or not filename: - raise SchemaError(f"{MANIFEST_PATH}: schema filenames must be non-empty") + raise SchemaError(f"{manifest_path}: schema filenames must be non-empty") path = SCHEMA_DIR / filename if path in loaded_files: raise SchemaError( - f"{MANIFEST_PATH}: schema file referenced twice: {filename}" + f"{manifest_path}: schema file referenced twice: {filename}" ) if not path.is_file(): - raise SchemaError(f"{MANIFEST_PATH}: missing schema file: {filename}") + raise SchemaError(f"{manifest_path}: missing schema file: {filename}") loaded_files.add(path) document = _load_yaml(path) @@ -133,12 +151,12 @@ def validate() -> list[str]: unreferenced = sorted( path.name - for path in SCHEMA_DIR.glob("*.v1.yaml") - if path != MANIFEST_PATH and path not in loaded_files + for path in SCHEMA_DIR.glob(f"*.v{interface_version}.yaml") + if path != manifest_path and path not in loaded_files ) if unreferenced: raise SchemaError( - f"{MANIFEST_PATH}: unreferenced v1 schema files: {unreferenced}" + f"{manifest_path}: unreferenced v{interface_version} schema files: {unreferenced}" ) summaries.append(f"total: {len(seen_messages)} messages") diff --git a/scripts/check_python_distributions.py b/scripts/check_python_distributions.py index 2de2934..53d44bd 100755 --- a/scripts/check_python_distributions.py +++ b/scripts/check_python_distributions.py @@ -25,7 +25,11 @@ "tool": Path("packages/tool"), } _TOOL_EXTRAS = {"dora"} -_TOOL_REQUIREMENTS = {"forge-msgs>=1.2.0,<2 ; extra == 'dora'"} +_TOOL_REQUIREMENTS = {"forge-msgs>=2.0.0,<3 ; extra == 'dora'"} +_RUNTIME_REQUIREMENTS = { + "forge-policy": {"dora-rs==1.0.0", "forge-msgs>=2.0.0,<3"}, + "forge-robot": {"dora-rs==1.0.0", "forge-msgs>=2.0.0,<3"}, +} class DistributionCheckError(RuntimeError): @@ -133,9 +137,15 @@ def _check_metadata( raise DistributionCheckError( f"{archive_name}: metadata must declare License-File: LICENSE" ) + requirements = set(metadata.get_all("Requires-Dist", [])) + expected_runtime = _RUNTIME_REQUIREMENTS.get(name) + if expected_runtime is not None and requirements != expected_runtime: + raise DistributionCheckError( + f"{archive_name}: {name} requirements must equal " + f"{sorted(expected_runtime)}" + ) if name == "forge-tool": extras = set(metadata.get_all("Provides-Extra", [])) - requirements = set(metadata.get_all("Requires-Dist", [])) if extras != _TOOL_EXTRAS: raise DistributionCheckError( f"{archive_name}: forge-tool extras must equal {sorted(_TOOL_EXTRAS)}" diff --git a/scripts/check_release_versions.py b/scripts/check_release_versions.py index 73ce6d1..4ba06d0 100755 --- a/scripts/check_release_versions.py +++ b/scripts/check_release_versions.py @@ -15,6 +15,7 @@ VERSIONS_PATH = Path("versions.toml") WORKSPACE_PROJECT = Path("pyproject.toml") FAMILY_ORDER = ("common", "msgs", "robot", "policy", "kinematics", "tool") +INTERFACE_ORDER = ("msgs",) PYTHON_PROJECTS = { "common": Path("packages/common/pyproject.toml"), "msgs": Path("packages/msgs/pyproject.toml"), @@ -43,18 +44,18 @@ EXPECTED_INTERNAL_REQUIREMENTS = { WORKSPACE_PROJECT: { "forge-common>=1.0.0,<2", - "forge-msgs>=1.0.0,<2", - "forge-policy>=1.0.0,<2", - "forge-robot>=1.0.0,<2", - "forge-tool>=1.0.0,<2", + "forge-msgs>=2.0.0,<3", + "forge-policy>=2.0.0,<3", + "forge-robot>=2.0.0,<3", + "forge-tool>=2.0.0,<3", }, - Path("packages/policy/pyproject.toml"): {"forge-msgs>=1.0.0,<2"}, - Path("packages/robot/pyproject.toml"): {"forge-msgs>=1.0.0,<2"}, + Path("packages/policy/pyproject.toml"): {"forge-msgs>=2.0.0,<3"}, + Path("packages/robot/pyproject.toml"): {"forge-msgs>=2.0.0,<3"}, Path("packages/tool/pyproject.toml"): set(), } EXPECTED_OPTIONAL_INTERNAL_REQUIREMENTS = { Path("packages/tool/pyproject.toml"): { - "dora": {"forge-msgs>=1.2.0,<2"}, + "dora": {"forge-msgs>=2.0.0,<3"}, }, } UV_PACKAGE_FAMILIES = { @@ -143,6 +144,26 @@ def _load_family_versions() -> dict[str, str]: } +def _load_interface_versions() -> dict[str, int]: + document = _load_toml(VERSIONS_PATH) + interfaces = _table(document, VERSIONS_PATH, "interfaces") + if set(interfaces) != set(INTERFACE_ORDER): + raise ReleaseVersionError( + f"{VERSIONS_PATH}: interfaces differ; " + f"expected {sorted(INTERFACE_ORDER)}, found {sorted(interfaces)}" + ) + + versions: dict[str, int] = {} + for interface in INTERFACE_ORDER: + value = interfaces[interface] + if isinstance(value, bool) or not isinstance(value, int) or value < 1: + raise ReleaseVersionError( + f"{VERSIONS_PATH}: interfaces.{interface} must be a positive integer" + ) + versions[interface] = value + return versions + + def _declared_version(path: Path, table: str) -> str: value = _table(_load_toml(path), path, table).get("version") return _strict_version(value, f"{path}: [{table}].version") @@ -367,9 +388,9 @@ def _check_cpp(findings: list[str], versions: dict[str, str]) -> None: ) -def _check_interface(findings: list[str], versions: dict[str, str]) -> None: - path = Path("interfaces/forge_msgs/forge_msgs.v1.yaml") - expected_major = versions["msgs"].split(".", 1)[0] +def _check_interface(findings: list[str], interface_versions: dict[str, int]) -> None: + expected_major = str(interface_versions["msgs"]) + path = Path(f"interfaces/forge_msgs/forge_msgs.v{expected_major}.yaml") try: text = _read_text(path) except ReleaseVersionError as exc: @@ -380,7 +401,7 @@ def _check_interface(findings: list[str], versions: dict[str, str]) -> None: findings.append(f"{path}: missing integer version") elif match.group(1) != expected_major: findings.append( - f"{path}: Msgs major expected {expected_major}, found {match.group(1)}" + f"{path}: Msgs interface version expected {expected_major}, found {match.group(1)}" ) @@ -436,6 +457,7 @@ def main() -> int: try: versions = _load_family_versions() + interface_versions = _load_interface_versions() except ReleaseVersionError as exc: print(f"Forge family version validation failed:\n - {exc}", file=sys.stderr) return 1 @@ -447,7 +469,7 @@ def main() -> int: _check_uv_lock(findings, versions, workspace_version) _check_cargo_lock(findings, versions) _check_cpp(findings, versions) - _check_interface(findings, versions) + _check_interface(findings, interface_versions) release_tag = _detected_ci_tag(arguments.tag) _check_release_tag(findings, versions, release_tag) @@ -460,6 +482,8 @@ def main() -> int: print("Forge package-family versions are aligned:") for family in FAMILY_ORDER: print(f" {family}: {versions[family]}") + for interface in INTERFACE_ORDER: + print(f" {interface} interface: v{interface_versions[interface]}") print(" Workspace, internal requirements, uv lock, and Cargo lock: aligned") if release_tag is not None: print(f" Release tag: {release_tag}") diff --git a/uv.lock b/uv.lock index 991cb1c..f8216d6 100644 --- a/uv.lock +++ b/uv.lock @@ -225,24 +225,25 @@ wheels = [ [[package]] name = "dora-rs" -version = "0.4.1" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "numpy" }, { name = "pyarrow" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a1/ff/894f11890a526f107d3d06b0e71209b45e5a7bb3666aed23725308bbf78a/dora_rs-0.4.1.tar.gz", hash = "sha256:fec74e823d438c6281caf2447b077f9299380b849a5ab113961bcf5e1d061332", size = 400799, upload-time = "2026-01-20T20:43:23.349Z" } +sdist = { url = "https://files.pythonhosted.org/packages/21/81/3293648e08be7bf7710f3385dc94361ce941962bdf50f2b573f3417e0898/dora_rs-1.0.0.tar.gz", hash = "sha256:8fbf60c84f55c08504d43e93440b01580ea56940bc4297ff795b2a4acf4177b7", size = 1693532, upload-time = "2026-09-02T17:08:32.895Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/86/9ce12fbbfc365b7037666ffbc79ac93ba05690b22cac8fad8d2104577dfe/dora_rs-0.4.1-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:a315e7bfefa64c6082da31b5fa77375a485d5a8558c8e835ef98b389b6906aec", size = 17873861, upload-time = "2026-01-20T20:43:09.532Z" }, - { url = "https://files.pythonhosted.org/packages/bc/62/5f476d78a57d2557c76458049c55a408618c0ceb5d1fdd267cbc9fc333b2/dora_rs-0.4.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f903b2fc89807f9f56e31807c3e0fcf8a703c2accfe932b193a8898212c22a0", size = 17036942, upload-time = "2026-01-20T20:42:56.288Z" }, - { url = "https://files.pythonhosted.org/packages/30/46/ff8235c5086b6f124a3ae47ee52eafdb6bea0e589d9ab506ceb085253c2c/dora_rs-0.4.1-cp37-abi3-manylinux_2_28_armv7l.whl", hash = "sha256:3edbb5856668dd6d04e1c1fd941f20588acb7f16ba5c7d60d6487c07d3d1da2c", size = 15510340, upload-time = "2026-01-20T20:42:59.773Z" }, - { url = "https://files.pythonhosted.org/packages/08/06/e763a0305c396a29ea56a378e08a52a4f14403b3abb0c8d9004925d49da9/dora_rs-0.4.1-cp37-abi3-manylinux_2_28_i686.whl", hash = "sha256:fd5b5ceeec35e39f2007fd4fb20efa7d4c5c425ae85e9ea19357184830cf5fdb", size = 18873782, upload-time = "2026-01-20T20:43:03.331Z" }, - { url = "https://files.pythonhosted.org/packages/94/53/7dc142faa1719333d57c78cfcf419f2b176770b49ebef54e0bbfa34212ac/dora_rs-0.4.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7cec1754d300dafff1b2c930608700320c15903396cdb4d79b4396fe88c08f68", size = 17401111, upload-time = "2026-01-20T20:43:06.392Z" }, - { url = "https://files.pythonhosted.org/packages/50/73/15138c5dfb1e0d6237dfca436b866da7cc39c8d6e475d271c671cd9079bd/dora_rs-0.4.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:98ff55301959686d2050359066f869998f8ed3efc87f1f7fa0fd889cb8c04c61", size = 20807024, upload-time = "2026-01-20T20:43:13.036Z" }, - { url = "https://files.pythonhosted.org/packages/f0/80/0c22260559b440ed695093cc4da963353086fb86c6f7981812f4922a8b0a/dora_rs-0.4.1-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:49a8eb40e4836deee21958ffab6aa0cd715fa2230bbfd90447fb6917819ebaa9", size = 19532748, upload-time = "2026-01-20T20:43:15.532Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c0/df4f3c97160c1be1b120aa6e53ed3175a8ce988acbc2b78f66f4778a17ea/dora_rs-0.4.1-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:9b6d3ffac8f28999f6a073f024b8c4d11d39636f602af74c8fd54588ce260448", size = 20832400, upload-time = "2026-01-20T20:43:19.064Z" }, - { url = "https://files.pythonhosted.org/packages/68/53/a0f6595e43713883e229fabdd3f4cdf5712caa4b08d2cacd51bd3681eea6/dora_rs-0.4.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:03a260889efe13151f95a1869173fccaca98731c9b29b24b00187a6d3ee2cea6", size = 20594335, upload-time = "2026-01-20T20:43:21.469Z" }, - { url = "https://files.pythonhosted.org/packages/1c/d4/e8134ce7d977fd87f507b6951b53df3aa7ab91122e7d487707352336703b/dora_rs-0.4.1-cp37-abi3-win_amd64.whl", hash = "sha256:9a424dca038006f05fcc44eaaea1a7a124a694f7aa954f8261d0bbe98877fd5b", size = 15069944, upload-time = "2026-01-20T20:43:24.614Z" }, + { url = "https://files.pythonhosted.org/packages/28/4b/985aeaadb1e32c399f885b8ffc8151c2909bec35a9b27c153c2b82fafefa/dora_rs-1.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fbb7339c50b1b68f71b22fd1c6ac5179f7cb9578cbdcfd5479fa29e109fa8b7b", size = 24759998, upload-time = "2026-09-02T17:08:20.058Z" }, + { url = "https://files.pythonhosted.org/packages/82/11/573dea7fe286a2c4b81c618e6fd67179a7deb51188c6ffc6f3e8103179df/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f489214f83bef6e1eedb4b3a55a1711cd9ce4d99a76f910621b98b327d330feb", size = 24043434, upload-time = "2026-09-02T17:08:10.567Z" }, + { url = "https://files.pythonhosted.org/packages/f7/44/d314b08011980958f98ff2a454fcbaf6b9300ff0ce12c4f5c3daaf8a3d06/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_armv7l.whl", hash = "sha256:5e4de7e70349f79646b72027ccc770f497c0b3113364e63490b618cc18653e52", size = 22817459, upload-time = "2026-09-02T17:08:13.178Z" }, + { url = "https://files.pythonhosted.org/packages/01/c3/d292030f92944767649a13bdd4a53f12024d5420cf37d092fe9a865ef08d/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_i686.whl", hash = "sha256:1976d4f1975771d1e6e3671f27655dea2df20884da944c0929e939703cee2be7", size = 25209313, upload-time = "2026-09-02T17:08:15.295Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d0/1ee8fc58fee8a8c9e8893cda4cd92844a9076319b45564efc337633580e6/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:01389cb8e3726546c1b5d6f98e80bb0967ad0b282d3a1b6a0d4a5266af4f1447", size = 24874647, upload-time = "2026-09-02T17:08:17.771Z" }, + { url = "https://files.pythonhosted.org/packages/e5/26/61f2587b2a2c16e9798e466cb8b2387c9a357191ee5bef881dfbcdd7cba6/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:358a66ab4594123c9aeb6e4f0c196573d1d239e49f11ca351670ee61b85d689f", size = 29798385, upload-time = "2026-09-02T17:08:22.477Z" }, + { url = "https://files.pythonhosted.org/packages/1d/99/031a6b80acee32b4b2208dca153bbf920c5a753f69c2d0ba8349700e4938/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:2056f1b38ddff3e78c6e645517fabde343503dc0d7983cfa6da0770aa0b0b72e", size = 28159029, upload-time = "2026-09-02T17:08:25.925Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/8562b9b0163e9f8e8e79675e96095225474be0dd0be8604345873844c6ec/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_i686.whl", hash = "sha256:4641e022310534068dd279bce11071c6a3b88515672696a0b8afe523a8b6f5c5", size = 29264242, upload-time = "2026-09-02T17:08:28.482Z" }, + { url = "https://files.pythonhosted.org/packages/87/7c/426dab191f991a4090b0985964b1b98ffdf23b9fe0bf39906c8ed5eaaf45/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:87b1d10f355eca4c539e18dbad75ab4efa34b84e48e293941ec0f6b411c8762a", size = 30004641, upload-time = "2026-09-02T17:08:30.803Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ef/5a9979d051ce2e417c524ead23b6c471894880dd86b15576feb193fba05e/dora_rs-1.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:7d0224289ad79f6c233c343393786de81cf5008a420ee1352722181508c26bf5", size = 22395785, upload-time = "2026-09-02T17:08:34.553Z" }, ] [[package]] @@ -271,7 +272,7 @@ wheels = [ [[package]] name = "forge" -version = "1.0.0" +version = "2.0.0" source = { virtual = "." } dependencies = [ { name = "forge-common" }, @@ -333,7 +334,7 @@ provides-extras = ["least-squares"] [[package]] name = "forge-msgs" -version = "1.3.0" +version = "2.0.0" source = { editable = "packages/msgs" } dependencies = [ { name = "numpy" }, @@ -359,7 +360,7 @@ provides-extras = ["test"] [[package]] name = "forge-policy" -version = "1.0.1" +version = "2.0.0" source = { editable = "packages/policy" } dependencies = [ { name = "dora-rs" }, @@ -368,13 +369,13 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "dora-rs", specifier = "==0.4.1" }, + { name = "dora-rs", specifier = "==1.0.0" }, { name = "forge-msgs", editable = "packages/msgs" }, ] [[package]] name = "forge-robot" -version = "1.0.1" +version = "2.0.0" source = { editable = "packages/robot" } dependencies = [ { name = "dora-rs" }, @@ -383,13 +384,13 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "dora-rs", specifier = "==0.4.1" }, + { name = "dora-rs", specifier = "==1.0.0" }, { name = "forge-msgs", editable = "packages/msgs" }, ] [[package]] name = "forge-tool" -version = "1.0.0" +version = "2.0.0" source = { editable = "packages/tool" } [package.optional-dependencies] diff --git a/versions.toml b/versions.toml index ad5b401..07ce9eb 100644 --- a/versions.toml +++ b/versions.toml @@ -2,8 +2,11 @@ schema_version = 1 [packages] common = "1.0.1" -msgs = "1.3.0" -robot = "1.0.1" -policy = "1.0.1" +msgs = "2.0.0" +robot = "2.0.0" +policy = "2.0.0" kinematics = "1.0.1" -tool = "1.0.0" +tool = "2.0.0" + +[interfaces] +msgs = 1 From ca2301752583544d0d87ce28cbcfd51e02a3bfc7 Mon Sep 17 00:00:00 2001 From: chipunderblade Date: Fri, 4 Sep 2026 11:03:43 +0800 Subject: [PATCH 2/3] chore!: align Forge package families on 2.0 --- .github/workflows/publish-pypi.yml | 2 +- CHANGELOG.md | 14 ++++++++++++++ CONTRIBUTING.md | 8 ++++---- Cargo.lock | 2 +- README.md | 18 ++++++++++-------- RELEASING.md | 17 ++++++++++++----- cpp/forge_common/CMakeLists.txt | 2 +- crates/forge_common/Cargo.toml | 2 +- packages/common/pyproject.toml | 2 +- packages/kinematics/README.md | 2 +- packages/kinematics/pyproject.toml | 2 +- pyproject.toml | 2 +- scripts/check_release_versions.py | 2 +- uv.lock | 4 ++-- versions.toml | 4 ++-- 15 files changed, 53 insertions(+), 30 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 39373c5..eff3600 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: tag: - description: "Immutable family tag to publish (for example, forge-common-v1.0.1)" + description: "Immutable family tag to publish (for example, forge-common-v2.0.0)" required: true type: string diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d2ad82..56ad64c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ Forge package families are versioned independently. Python, Rust, and C++ implem ## Unreleased +## forge-common 2.0.0 - 2026-09-04 + +Protected tag: `forge-common-v2.0.0` + +- Align Common with the coordinated Forge 2.0 release train without changing its public utility APIs. +- Preserve the Python, Rust, and C++ logging contracts from the 1.x line. + +## forge-kinematics 2.0.0 - 2026-09-04 + +Protected tag: `forge-kinematics-v2.0.0` + +- Align Kinematics with the coordinated Forge 2.0 release train without changing its solver APIs or optional dependency model. +- Preserve the Pinocchio-based FK, Jacobian, and IK behavior from the 1.x line. + ## forge-policy 2.0.0 - 2026-09-03 Protected tag: `forge-policy-v2.0.0` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0de75f..47b782b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,9 @@ # Contributing to Forge -Thank you for your interest in contributing to Forge. The repository maintains -stable 1.x package families while developing the Tool alpha family, so focused -changes, compatibility analysis, and cross-language tests are especially -important. +Thank you for your interest in contributing to Forge. `master` carries the current +Forge 2.x line, while `stable/1.x` preserves the Dora 0.4-compatible Forge 1.x line +for critical fixes. Focused changes, compatibility analysis, and cross-language +tests are especially important. ## Development Setup diff --git a/Cargo.lock b/Cargo.lock index 9673a39..8c5ada2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,7 +233,7 @@ dependencies = [ [[package]] name = "forgelab_common" -version = "1.0.1" +version = "2.0.0" dependencies = [ "tracing", "tracing-subscriber", diff --git a/README.md b/README.md index 52c77eb..b945310 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,13 @@ packages, for example a separate `forge_robots` repository. ## Status -Forge tracks six independently versioned package families: Common, Msgs, Robot, -Policy, Kinematics, and Tool. Current releases are Common `1.0.1`, Msgs `1.3.0`, Robot -`1.0.1`, Policy `1.0.1`, Kinematics `1.0.1`, and Tool `0.1.0`. Implementations of one -family across Python, Rust, C++, and the language-neutral interface remain synchronized; -unrelated families may release at different rates. +Forge tracks six package families: Common, Msgs, Robot, Policy, Kinematics, and Tool. +The coordinated Dora 1.0 release train declares all six families as `2.0.0` while +allowing later family-specific patch releases. Implementations of one family across +Python, Rust, C++, and the language-neutral interface remain synchronized. + +`master` carries the latest Forge 2.x development line. `stable/1.x` preserves the +Dora 0.4-compatible Forge 1.x line for critical fixes during downstream migration. Each release is identified by a protected family tag such as `forge-msgs-v2.0.0`; Tool releases use `forge-tool-v`. Historical generic tags @@ -43,8 +45,8 @@ releases. The initial family releases define stable contracts for message schemas, serialization, shared utilities, kinematics, and robot/policy runners. Each -family's `1.x` line remains backward compatible; breaking that family contract -requires its next major version. See +family's current major line remains backward compatible; breaking that family +contract requires its next major version. See [`CHANGELOG.md`](CHANGELOG.md) for the release baselines and [`RELEASING.md`](RELEASING.md) for package-family boundaries, protected GitLab tags, and validation procedures. @@ -194,7 +196,7 @@ include(FetchContent) FetchContent_Declare( forge_common GIT_REPOSITORY https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git - GIT_TAG forge-common-v1.0.1 + GIT_TAG forge-common-v2.0.0 SOURCE_SUBDIR cpp/forge_common ) FetchContent_MakeAvailable(forge_common) diff --git a/RELEASING.md b/RELEASING.md index ca9c6cd..fd32812 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -8,11 +8,11 @@ Forge is a Monorepo with independently versioned logical package families. Imple ```toml [packages] -common = "1.0.1" +common = "2.0.0" msgs = "2.0.0" robot = "2.0.0" policy = "2.0.0" -kinematics = "1.0.1" +kinematics = "2.0.0" tool = "2.0.0" [interfaces] @@ -21,6 +21,13 @@ msgs = 1 The root `pyproject.toml` is a virtual uv workspace, not a published `forge` Python distribution. Its project version is workspace tooling metadata and is not a package-family release version. +## Release lines + +`master` is the current Forge 2.x development and release line. `stable/1.x` is the +Dora 0.4-compatible maintenance line and accepts only critical, security, and release +fixes. Develop changes on `master`; cherry-pick applicable fixes to `stable/1.x` rather +than merging the newer major line into the older one. + ## Family boundaries and tags | Family | Synchronized implementations | Protected tag pattern | @@ -39,11 +46,11 @@ Do not use or move historical generic tags such as `v1.0.0`. They belong to an e The initial five `1.0.0` tags may point to the same clean commit. Tool's first release is `forge-tool-v0.1.0`. Later releases can be independent, for example: ```text -forge-common-v1.0.1 +forge-common-v2.0.0 forge-msgs-v2.0.0 forge-robot-v2.0.0 forge-policy-v2.0.0 -forge-kinematics-v1.0.2 +forge-kinematics-v2.0.0 forge-tool-v2.0.0 ``` @@ -54,7 +61,7 @@ Use the tag for the exact family being consumed: ```toml [tool.uv.sources] forge-msgs = { git = "https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git", tag = "forge-msgs-v2.0.0", subdirectory = "packages/msgs" } -forge-common = { git = "https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git", tag = "forge-common-v1.0.1", subdirectory = "packages/common" } +forge-common = { git = "https://gitlab.ex-ai.cn/PhyAgentOS/framework/forge.git", tag = "forge-common-v2.0.0", subdirectory = "packages/common" } ``` A downstream `uv.lock` or `Cargo.lock` records the exact commit resolved from each protected tag. Protected release tags must never be moved. diff --git a/cpp/forge_common/CMakeLists.txt b/cpp/forge_common/CMakeLists.txt index 93feebe..70ff453 100644 --- a/cpp/forge_common/CMakeLists.txt +++ b/cpp/forge_common/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) -project(forge_common_cpp VERSION 1.0.1 LANGUAGES CXX) +project(forge_common_cpp VERSION 2.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/crates/forge_common/Cargo.toml b/crates/forge_common/Cargo.toml index dd3ce7a..dd2230d 100644 --- a/crates/forge_common/Cargo.toml +++ b/crates/forge_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forgelab_common" -version = "1.0.1" +version = "2.0.0" edition.workspace = true license.workspace = true authors.workspace = true diff --git a/packages/common/pyproject.toml b/packages/common/pyproject.toml index 8188493..c5c3b96 100644 --- a/packages/common/pyproject.toml +++ b/packages/common/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge-common" -version = "1.0.1" +version = "2.0.0" description = "Shared Python utilities for Forge packages." readme = "README.md" authors = [ diff --git a/packages/kinematics/README.md b/packages/kinematics/README.md index f02e076..9c02276 100644 --- a/packages/kinematics/README.md +++ b/packages/kinematics/README.md @@ -16,7 +16,7 @@ The package is a model and solver library. It does not depend on ROS, Dora, robo - `PinocchioDlsSolver` performs one deterministic seed-based solve. It does not perform random restarts or silently accept approximate results. - `PinocchioBoundedLeastSquaresSolver` minimizes the same weighted pose residual with analytic Pinocchio Jacobians, per-joint box constraints, optional neutral/seed regularization, and a strict function-evaluation budget. -Version 1 supports independent single-DoF revolute, continuous, and prismatic active joints. Floating, planar, mimic, collision-aware, and search IK are intentionally out of scope. +The current release supports independent single-DoF revolute, continuous, and prismatic active joints. Floating, planar, mimic, collision-aware, and search IK are intentionally out of scope. ## Install diff --git a/packages/kinematics/pyproject.toml b/packages/kinematics/pyproject.toml index 64d9d54..9c1774a 100644 --- a/packages/kinematics/pyproject.toml +++ b/packages/kinematics/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "forge-kinematics" -version = "1.0.1" +version = "2.0.0" description = "Deterministic Pinocchio-based forward and inverse kinematics for Forge." readme = "README.md" requires-python = ">=3.12" diff --git a/pyproject.toml b/pyproject.toml index 246077c..9ce0759 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ { name = "X-ERA" } ] dependencies = [ - "forge-common>=1.0.0,<2", + "forge-common>=2.0.0,<3", "forge-msgs>=2.0.0,<3", "forge-policy>=2.0.0,<3", "forge-robot>=2.0.0,<3", diff --git a/scripts/check_release_versions.py b/scripts/check_release_versions.py index 4ba06d0..6f12dc3 100755 --- a/scripts/check_release_versions.py +++ b/scripts/check_release_versions.py @@ -43,7 +43,7 @@ } EXPECTED_INTERNAL_REQUIREMENTS = { WORKSPACE_PROJECT: { - "forge-common>=1.0.0,<2", + "forge-common>=2.0.0,<3", "forge-msgs>=2.0.0,<3", "forge-policy>=2.0.0,<3", "forge-robot>=2.0.0,<3", diff --git a/uv.lock b/uv.lock index f8216d6..cc3f58e 100644 --- a/uv.lock +++ b/uv.lock @@ -307,12 +307,12 @@ dev = [ [[package]] name = "forge-common" -version = "1.0.1" +version = "2.0.0" source = { editable = "packages/common" } [[package]] name = "forge-kinematics" -version = "1.0.1" +version = "2.0.0" source = { editable = "packages/kinematics" } dependencies = [ { name = "numpy" }, diff --git a/versions.toml b/versions.toml index 07ce9eb..9d9b3b1 100644 --- a/versions.toml +++ b/versions.toml @@ -1,11 +1,11 @@ schema_version = 1 [packages] -common = "1.0.1" +common = "2.0.0" msgs = "2.0.0" robot = "2.0.0" policy = "2.0.0" -kinematics = "1.0.1" +kinematics = "2.0.0" tool = "2.0.0" [interfaces] From dd3501b327dc97cd778d00d4d26fe7f77a88b2f1 Mon Sep 17 00:00:00 2001 From: chipunderblade Date: Fri, 4 Sep 2026 11:32:11 +0800 Subject: [PATCH 3/3] fix: support Dora 1.x patch releases --- .github/workflows/ci.yml | 4 ++-- CHANGELOG.md | 4 ++-- README.md | 29 +++++++++++++------------ cpp/forge_robot/CMakeLists.txt | 2 +- cpp/forge_robot/README.md | 24 ++++++++++---------- cpp/forge_robot/cmake/DoraTargets.cmake | 8 +++---- packages/policy/pyproject.toml | 2 +- packages/robot/pyproject.toml | 2 +- scripts/check_python_distributions.py | 4 ++-- uv.lock | 28 ++++++++++++------------ 10 files changed, 55 insertions(+), 52 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4752142..44a72de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,13 +129,13 @@ jobs: shell: bash -el {0} run: ctest --test-dir cpp/forge_robot/build --output-on-failure - - name: Configure C++ forge_robot Dora v1.0.0 runner + - name: Configure C++ forge_robot Dora 1.x runner (v1.0.1) shell: bash -el {0} run: >- cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora -G Ninja -DFORGE_ROBOT_CPP_WITH_DORA=ON -DFORGE_ROBOT_CPP_BUILD_TESTS=ON - - name: Compile C++ forge_robot Dora v1.0.0 runner + - name: Compile C++ forge_robot Dora 1.x runner (v1.0.1) shell: bash -el {0} run: cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ad64c..66f5f09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,14 +22,14 @@ Protected tag: `forge-kinematics-v2.0.0` Protected tag: `forge-policy-v2.0.0` -- Migrate the Python Dora runner dependency from `dora-rs 0.4.1` to `1.0.0`. +- Migrate the Python Dora runner dependency from `dora-rs 0.4.1` to the compatible Dora 1.x line (`>=1.0,<2`), currently locked and validated with 1.0.1. - Require the Forge Msgs 2 carrier line. ## forge-robot 2.0.0 - 2026-09-03 Protected tag: `forge-robot-v2.0.0` -- Migrate the Python Dora runner dependency and optional C++ node bridge from Dora 0.4.1 to 1.0.0. +- Migrate the Python Dora runner dependency and optional C++ node bridge from Dora 0.4.1 to the compatible Dora 1.x line; Python is currently locked to 1.0.1 and the reproducible C++ source build is pinned to `v1.0.1`. - Require the Forge Msgs 2 carrier line while keeping the driver contract and node input/output semantics unchanged. ## forge-msgs 2.0.0 - 2026-09-03 diff --git a/README.md b/README.md index b945310..db0448b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ packages, for example a separate `forge_robots` repository. ## Status Forge tracks six package families: Common, Msgs, Robot, Policy, Kinematics, and Tool. -The coordinated Dora 1.0 release train declares all six families as `2.0.0` while +The coordinated Dora 1.x release train declares all six families as `2.0.0` while allowing later family-specific patch releases. Implementations of one family across Python, Rust, C++, and the language-neutral interface remain synchronized. @@ -91,11 +91,11 @@ forge/ - A C++20-capable compiler and CMake 3.20 or newer for C++ packages; `cpp/forge_msgs` and its dependents require C++20 - Apache Arrow C++ for `cpp/forge_msgs` -- Rust 1.95 or newer and network access, or a local Dora `v1.0.0` checkout, for the - optional C++ `forge_robot` Dora runner +- Rust 1.95 or newer and network access, or a compatible local Dora 1.x checkout, + for the optional C++ `forge_robot` Dora runner - [`uv`](https://docs.astral.sh/uv/) for Python dependency management -- Dora runtime 1.0.0 when running real nodes (`dora-rs==1.0.0` is used by the - Python node packages) +- A Dora 1.x runtime when running real nodes (the Python packages declare + `dora-rs>=1.0,<2`; the current lock file validates 1.0.1) ## Installation @@ -146,8 +146,8 @@ cmake -S cpp/forge_robot -B cpp/forge_robot/build cmake --build cpp/forge_robot/build ``` -Build and compile-link validate the C++ `forge_robot` Dora runner against Dora -`v1.0.0`: +Build and compile-link validate the C++ `forge_robot` Dora 1.x runner against +the current pinned baseline, Dora `v1.0.1`: ```bash cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ @@ -157,14 +157,15 @@ cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compil ``` The C++ Dora API headers are generated by Dora's CXX bridge. By default, -`cpp/forge_robot` downloads the Dora `v1.0.0` source archive with a pinned SHA256; -it does not use Dora `main`. To use a local Dora `v1.0.0` checkout: +`cpp/forge_robot` downloads the Dora `v1.0.1` source archive with a pinned +SHA256; it does not use Dora `main`. To use a compatible local Dora 1.x +checkout: ```bash -git clone --branch v1.0.0 https://github.com/dora-rs/dora.git /path/to/dora-v1.0.0 +git clone --branch v1.0.1 https://github.com/dora-rs/dora.git /path/to/dora-v1.0.1 cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.1 cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile ``` @@ -238,13 +239,13 @@ the public umbrella header: For packages that only implement driver logic, safety clipping, or Arrow validation, keep `FORGE_ROBOT_CPP_WITH_DORA` off. To compile a Dora runner in the downstream package, enable the option at configure time and either let CMake -download Dora `v1.0.0` or point `DORA_ROOT_DIR` at a local Dora `v1.0.0` -checkout: +download the pinned Dora `v1.0.1` baseline or point `DORA_ROOT_DIR` at a +compatible local Dora 1.x checkout: ```bash cmake -S . -B build \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.1 ``` ## Testing diff --git a/cpp/forge_robot/CMakeLists.txt b/cpp/forge_robot/CMakeLists.txt index 6ebde4d..4ab1398 100644 --- a/cpp/forge_robot/CMakeLists.txt +++ b/cpp/forge_robot/CMakeLists.txt @@ -35,7 +35,7 @@ if(FORGE_ROBOT_CPP_WITH_DORA) elseif(NOT DORA_CXX_BRIDGE_SOURCE) message(FATAL_ERROR "Pre-generated Dora CXX artifacts require DORA_CXX_BRIDGE_SOURCE. " - "Omit DORA_CXX_INCLUDE_DIR/DORA_CXX_LIBRARY to use the built-in Dora v1.0.0 helper." + "Omit DORA_CXX_INCLUDE_DIR/DORA_CXX_LIBRARY to use the built-in Dora v1.0.1 helper." ) endif() list(APPEND FORGE_ROBOT_CPP_SOURCES src/node_runner.cpp) diff --git a/cpp/forge_robot/README.md b/cpp/forge_robot/README.md index 9f3f3b4..77b882b 100644 --- a/cpp/forge_robot/README.md +++ b/cpp/forge_robot/README.md @@ -33,9 +33,9 @@ The optional Dora runner mirrors the Python `forge_robot` node loop: The driver interfaces, clipping helpers, and Arrow validation do not depend on Dora headers. `RunDoraRobotNode()` is compiled only when -`FORGE_ROBOT_CPP_WITH_DORA=ON`. The Dora C++ API is generated from Dora -`v1.0.0` with CXX bridge sources, so the default build path is pinned to that -tag instead of Dora `main`. +`FORGE_ROBOT_CPP_WITH_DORA=ON`. The runner supports the Dora 1.x API line. For +reproducibility, the default build generates CXX bridge sources from the +SHA256-pinned Dora `v1.0.1` archive instead of Dora `main`. ## Build @@ -47,7 +47,8 @@ cmake --build cpp/forge_robot/build ctest --test-dir cpp/forge_robot/build --output-on-failure ``` -Build and compile-link validate the Dora runner against Dora `v1.0.0`: +Build and compile-link validate the Dora 1.x runner against the current pinned +baseline, Dora `v1.0.1`: ```bash cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ @@ -56,15 +57,15 @@ cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile ``` -The command above downloads the SHA256-pinned Dora `v1.0.0` source archive and +The command above downloads the SHA256-pinned Dora `v1.0.1` source archive and builds `dora-node-api-cxx` with Cargo. To avoid downloading during -configure/build, provide a local Dora `v1.0.0` checkout: +configure/build, provide a compatible local Dora 1.x checkout: ```bash -git clone --branch v1.0.0 https://github.com/dora-rs/dora.git /path/to/dora-v1.0.0 +git clone --branch v1.0.1 https://github.com/dora-rs/dora.git /path/to/dora-v1.0.1 cmake -S cpp/forge_robot -B cpp/forge_robot/build-dora \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.1 cmake --build cpp/forge_robot/build-dora --target forge_robot_dora_runner_compile ``` @@ -112,11 +113,12 @@ interfaces, safety clipping, or Arrow validation. This avoids pulling in Rust/Cargo and the Dora C++ API build. When enabling the Dora runner from a consumer project, pass -`FORGE_ROBOT_CPP_WITH_DORA=ON`. The default path builds against Dora `v1.0.0`; -pass `DORA_ROOT_DIR=/path/to/dora-v1.0.0` to use an existing local checkout. +`FORGE_ROBOT_CPP_WITH_DORA=ON`. The default path builds against the pinned Dora +`v1.0.1` baseline; pass `DORA_ROOT_DIR` to use another compatible Dora 1.x +checkout. ```bash cmake -S . -B build \ -DFORGE_ROBOT_CPP_WITH_DORA=ON \ - -DDORA_ROOT_DIR=/path/to/dora-v1.0.0 + -DDORA_ROOT_DIR=/path/to/dora-v1.0.1 ``` diff --git a/cpp/forge_robot/cmake/DoraTargets.cmake b/cpp/forge_robot/cmake/DoraTargets.cmake index 05bad78..c27579c 100644 --- a/cpp/forge_robot/cmake/DoraTargets.cmake +++ b/cpp/forge_robot/cmake/DoraTargets.cmake @@ -1,4 +1,4 @@ -set(DORA_ROOT_DIR "" CACHE PATH "Path to the root of a local Dora v1.0.0 checkout") +set(DORA_ROOT_DIR "" CACHE PATH "Path to the root of a local Dora 1.x checkout") set(dora_c_include_dir "${CMAKE_CURRENT_BINARY_DIR}/include/c") set(dora_cxx_include_dir "${CMAKE_CURRENT_BINARY_DIR}/include/cxx") @@ -17,7 +17,7 @@ list(LENGTH node_bridge_headers node_bridge_header_count) list(LENGTH operator_bridge_sources operator_bridge_source_count) list(LENGTH operator_bridge_headers operator_bridge_header_count) if(node_bridge_source_count EQUAL 0 OR node_bridge_header_count EQUAL 0 OR operator_bridge_source_count EQUAL 0 OR operator_bridge_header_count EQUAL 0) - message(FATAL_ERROR "Could not find Dora v1.0.0 CXX bridge outputs in ${DORA_TARGET_DIR}") + message(FATAL_ERROR "Could not find Dora 1.x CXX bridge outputs in ${DORA_TARGET_DIR}") endif() list(GET node_bridge_sources 0 node_bridge_source) @@ -68,8 +68,8 @@ if(DORA_ROOT_DIR) else() ExternalProject_Add(Dora PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dora - URL https://codeload.github.com/dora-rs/dora/tar.gz/refs/tags/v1.0.0 - URL_HASH SHA256=2e84db8afde1e2d6e73fd03e62a1fbe6e43442a408a098c12f30484e367ab183 + URL https://codeload.github.com/dora-rs/dora/tar.gz/refs/tags/v1.0.1 + URL_HASH SHA256=e71ee32868a06941db8d382b8538403127b08cf3383a62d146c13f23a032f6fe DOWNLOAD_EXTRACT_TIMESTAMP TRUE BUILD_IN_SOURCE TRUE CONFIGURE_COMMAND "" diff --git a/packages/policy/pyproject.toml b/packages/policy/pyproject.toml index 723152d..de96197 100644 --- a/packages/policy/pyproject.toml +++ b/packages/policy/pyproject.toml @@ -10,7 +10,7 @@ authors = [ { name = "X-ERA" } ] dependencies = [ - "dora-rs==1.0.0", + "dora-rs>=1.0,<2", "forge-msgs>=2.0.0,<3", ] diff --git a/packages/robot/pyproject.toml b/packages/robot/pyproject.toml index efdf202..df0b1e8 100644 --- a/packages/robot/pyproject.toml +++ b/packages/robot/pyproject.toml @@ -10,7 +10,7 @@ authors = [ { name = "X-ERA" } ] dependencies = [ - "dora-rs==1.0.0", + "dora-rs>=1.0,<2", "forge-msgs>=2.0.0,<3", ] diff --git a/scripts/check_python_distributions.py b/scripts/check_python_distributions.py index 53d44bd..bfc7b16 100755 --- a/scripts/check_python_distributions.py +++ b/scripts/check_python_distributions.py @@ -27,8 +27,8 @@ _TOOL_EXTRAS = {"dora"} _TOOL_REQUIREMENTS = {"forge-msgs>=2.0.0,<3 ; extra == 'dora'"} _RUNTIME_REQUIREMENTS = { - "forge-policy": {"dora-rs==1.0.0", "forge-msgs>=2.0.0,<3"}, - "forge-robot": {"dora-rs==1.0.0", "forge-msgs>=2.0.0,<3"}, + "forge-policy": {"dora-rs>=1.0,<2", "forge-msgs>=2.0.0,<3"}, + "forge-robot": {"dora-rs>=1.0,<2", "forge-msgs>=2.0.0,<3"}, } diff --git a/uv.lock b/uv.lock index cc3f58e..48fcfde 100644 --- a/uv.lock +++ b/uv.lock @@ -225,25 +225,25 @@ wheels = [ [[package]] name = "dora-rs" -version = "1.0.0" +version = "1.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "pyarrow" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/81/3293648e08be7bf7710f3385dc94361ce941962bdf50f2b573f3417e0898/dora_rs-1.0.0.tar.gz", hash = "sha256:8fbf60c84f55c08504d43e93440b01580ea56940bc4297ff795b2a4acf4177b7", size = 1693532, upload-time = "2026-09-02T17:08:32.895Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/fc/9dd2e1cc4da1caf46496353da6c12f7b7c90512186d828f1d587dc6deddc/dora_rs-1.0.1.tar.gz", hash = "sha256:8cef7fa133d93e7ca46581a9efef6b45b5768cecef5ee6b9e22632978b8fe8a2", size = 1690155, upload-time = "2026-09-03T12:21:54.217Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/4b/985aeaadb1e32c399f885b8ffc8151c2909bec35a9b27c153c2b82fafefa/dora_rs-1.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fbb7339c50b1b68f71b22fd1c6ac5179f7cb9578cbdcfd5479fa29e109fa8b7b", size = 24759998, upload-time = "2026-09-02T17:08:20.058Z" }, - { url = "https://files.pythonhosted.org/packages/82/11/573dea7fe286a2c4b81c618e6fd67179a7deb51188c6ffc6f3e8103179df/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f489214f83bef6e1eedb4b3a55a1711cd9ce4d99a76f910621b98b327d330feb", size = 24043434, upload-time = "2026-09-02T17:08:10.567Z" }, - { url = "https://files.pythonhosted.org/packages/f7/44/d314b08011980958f98ff2a454fcbaf6b9300ff0ce12c4f5c3daaf8a3d06/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_armv7l.whl", hash = "sha256:5e4de7e70349f79646b72027ccc770f497c0b3113364e63490b618cc18653e52", size = 22817459, upload-time = "2026-09-02T17:08:13.178Z" }, - { url = "https://files.pythonhosted.org/packages/01/c3/d292030f92944767649a13bdd4a53f12024d5420cf37d092fe9a865ef08d/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_i686.whl", hash = "sha256:1976d4f1975771d1e6e3671f27655dea2df20884da944c0929e939703cee2be7", size = 25209313, upload-time = "2026-09-02T17:08:15.295Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/1ee8fc58fee8a8c9e8893cda4cd92844a9076319b45564efc337633580e6/dora_rs-1.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:01389cb8e3726546c1b5d6f98e80bb0967ad0b282d3a1b6a0d4a5266af4f1447", size = 24874647, upload-time = "2026-09-02T17:08:17.771Z" }, - { url = "https://files.pythonhosted.org/packages/e5/26/61f2587b2a2c16e9798e466cb8b2387c9a357191ee5bef881dfbcdd7cba6/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:358a66ab4594123c9aeb6e4f0c196573d1d239e49f11ca351670ee61b85d689f", size = 29798385, upload-time = "2026-09-02T17:08:22.477Z" }, - { url = "https://files.pythonhosted.org/packages/1d/99/031a6b80acee32b4b2208dca153bbf920c5a753f69c2d0ba8349700e4938/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:2056f1b38ddff3e78c6e645517fabde343503dc0d7983cfa6da0770aa0b0b72e", size = 28159029, upload-time = "2026-09-02T17:08:25.925Z" }, - { url = "https://files.pythonhosted.org/packages/55/4c/8562b9b0163e9f8e8e79675e96095225474be0dd0be8604345873844c6ec/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_i686.whl", hash = "sha256:4641e022310534068dd279bce11071c6a3b88515672696a0b8afe523a8b6f5c5", size = 29264242, upload-time = "2026-09-02T17:08:28.482Z" }, - { url = "https://files.pythonhosted.org/packages/87/7c/426dab191f991a4090b0985964b1b98ffdf23b9fe0bf39906c8ed5eaaf45/dora_rs-1.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:87b1d10f355eca4c539e18dbad75ab4efa34b84e48e293941ec0f6b411c8762a", size = 30004641, upload-time = "2026-09-02T17:08:30.803Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ef/5a9979d051ce2e417c524ead23b6c471894880dd86b15576feb193fba05e/dora_rs-1.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:7d0224289ad79f6c233c343393786de81cf5008a420ee1352722181508c26bf5", size = 22395785, upload-time = "2026-09-02T17:08:34.553Z" }, + { url = "https://files.pythonhosted.org/packages/28/8b/2040480f8393da850f544347a389dab6bf99c84131da9cb5a2273829a76f/dora_rs-1.0.1-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:56fb3daf26a978e6f535b0d6b04ac3abd362aff62de6771cd74c2dee06207cb8", size = 24759810, upload-time = "2026-09-03T12:21:42.346Z" }, + { url = "https://files.pythonhosted.org/packages/b9/4c/c563464b74cd31d801fe37c693751005717c80834210c1fa61cb44d7bd34/dora_rs-1.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:61fd33ba5a5cfa01ba4aed4c75bda490b5ad0e5d7180bde7b075d17e0c782486", size = 24061908, upload-time = "2026-09-03T12:21:29.714Z" }, + { url = "https://files.pythonhosted.org/packages/da/20/125f14f222c2eab928b23d310eeed61c93e9805d30575d21f05df285fb84/dora_rs-1.0.1-cp311-abi3-manylinux_2_28_armv7l.whl", hash = "sha256:6b0075de47b8310bf3801f2ce70b13b6925ebe1c8a7b04c9084bcd11688506ea", size = 22804362, upload-time = "2026-09-03T12:21:32.351Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1b/98e0ce52006fbd6d91f33037c5a76ab12edf8c74a01062af39c4dab4c403/dora_rs-1.0.1-cp311-abi3-manylinux_2_28_i686.whl", hash = "sha256:7f1377dda91435ca9d69ecce88a621052c172c2eb07f9c0aa0c1634d6bbfc057", size = 25245130, upload-time = "2026-09-03T12:21:37.702Z" }, + { url = "https://files.pythonhosted.org/packages/b8/80/f931008dec0806d3446de9d762cb2f16883530857e0941d36449b554b84b/dora_rs-1.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a28d634659a23dc8df9fbd40ad093f712e202821060f949f3dba5af8f7f36377", size = 24887127, upload-time = "2026-09-03T12:21:39.886Z" }, + { url = "https://files.pythonhosted.org/packages/cf/43/01a610cb1f696410698ffb9a6e6d5f2dd3c6ae22ad63aed366c00136b3ae/dora_rs-1.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3255d040778b44542f3d03288268a22f85253db45099d60d33776b7ef92ac1c6", size = 29797596, upload-time = "2026-09-03T12:21:44.594Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f5/6668702f8a107c2a701bc8368d14c18d1d36b620c8c7cbc5ac2d83c58cf7/dora_rs-1.0.1-cp311-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0febdd43c0c0b511c60def3691d83d69a54ed8543207af3bb238989f7a1f5c0b", size = 28151873, upload-time = "2026-09-03T12:21:46.781Z" }, + { url = "https://files.pythonhosted.org/packages/06/51/0141e6fe69a7444115d0e9e56bbed234cd86035d3d5588f61d56e0778a61/dora_rs-1.0.1-cp311-abi3-musllinux_1_2_i686.whl", hash = "sha256:f774a046e6d869b4e40b9c9fea5d1a46175c3d83179b44d1f3310c788562b72e", size = 29301986, upload-time = "2026-09-03T12:21:49.576Z" }, + { url = "https://files.pythonhosted.org/packages/04/b2/5032b628e1e46ef76180860a6f14e32b940d2979971e931630c6e10e3316/dora_rs-1.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d8c8affc29e401558ac83136055750b9de10ac3d3a98855b59866b0c08260dfa", size = 29999168, upload-time = "2026-09-03T12:21:51.803Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3b/bb7c131dd2778909f4ec4d3e0151a7fa342a38ea8fa3ca64d2ef87d93f2f/dora_rs-1.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:fbca33bf87e77fb9532e3bbeff023adb0e9b8e713d6f9106f114e0b0408666f5", size = 22396575, upload-time = "2026-09-03T12:21:55.601Z" }, ] [[package]] @@ -369,7 +369,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "dora-rs", specifier = "==1.0.0" }, + { name = "dora-rs", specifier = ">=1.0,<2" }, { name = "forge-msgs", editable = "packages/msgs" }, ] @@ -384,7 +384,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "dora-rs", specifier = "==1.0.0" }, + { name = "dora-rs", specifier = ">=1.0,<2" }, { name = "forge-msgs", editable = "packages/msgs" }, ]