Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ jobs:
args: --workspace
- name: spatialrust-serde
args: -p spatialrust --features serde
- name: spatialrust-records-receipt-json
args: -p spatialrust-records --features receipt-json
- name: spatialrust-records-receipt-json-meta
args: -p spatialrust --features records-receipt-json
- name: spatialrust-io-streaming-all
args: -p spatialrust-io --no-default-features --features io-pcd,io-ply,io-las,io-laz,io-copc-http,streaming
- name: spatialrust-pipeline-streaming
args: -p spatialrust-pipeline --no-default-features --features pipeline-streaming
- name: spatialrust-pipeline-streaming-meta
args: -p spatialrust --no-default-features --features pipeline-streaming
- name: spatialrust-streaming-cli
args: -p spatialrust --no-default-features --features streaming-cli
- name: spatialrust-io-pcd
args: -p spatialrust-io --features io-pcd
- name: spatialrust-io-pcd-meta
Expand Down Expand Up @@ -290,6 +302,26 @@ jobs:
cargo run -p spatialrust --no-default-features --features platform --example vision_2_release_gate
cargo run -p spatialrust --no-default-features --features image-io-standard,vision-video --example video_tracking_e2e

streaming-platform-conformance:
name: Streaming 1.2 conformance (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Test bounded-streaming contracts and release gate
run: |
cargo test -p spatialrust-records --features receipt-json
cargo test -p spatialrust-io --no-default-features --features io-pcd,io-ply,io-las,io-laz,io-copc-http,streaming
cargo test -p spatialrust-pipeline --no-default-features --features pipeline-streaming
cargo test -p spatialrust --no-default-features --features streaming-cli --test streaming_cli
cargo test -p spatialrust-platform streaming
cargo run -p spatialrust --no-default-features --features platform,pipeline-streaming --example streaming_1_2_release_gate

bench:
name: Benchmark compile
runs-on: ubuntu-latest
Expand Down
34 changes: 33 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ removed no sooner than the next major (see `docs/API_STABILITY.md`).

## [Unreleased]

## [1.2.0] — 2026-07-27

### Added

- **SpatialRust 1.2 bounded-streaming contract (Epic 121)**:
Expand All @@ -38,8 +40,37 @@ removed no sooner than the next major (see `docs/API_STABILITY.md`).
ownership-preserving `PointCloud::into_parts` inverse and mutable column
iteration needed to clear recycled storage without allocating field names.

- **Bounded point-cloud IO and spool contracts (Epic 123)**: feature-gated
PCD, PLY, LAS/LAZ, and deterministic local/HTTP COPC sources emit leased
chunks without whole-cloud materialization. Exact-count and open-ended sinks,
source-driven COPC output, bounded ASCII records, and extent-limited
temporary storage fail before exceeding their declared limits.

- **Chunk-safe streaming operations (Epic 124)**: shared-budget crop and affine
transform adapters, compensated global position reductions, and
deterministic external voxel centroids compose outside
`spatialrust-core`. Voxel output is invariant to source chunk and sort-run
size, with explicit spill/run/file-handle limits.

- **Rust, CLI, and Python streaming workflows (Epic 125)**:
`StreamingPipeline` provides a type-erased metered iterator and sink drain;
`spatialrust-stream` converts local/HTTP inputs to open-ended LAS/LAZ with
Ctrl-C cancellation and JSON receipts; Python `PointCloudStream` wraps the
same Rust iterator with cancellation and live receipts.

- **SpatialRust 1.2 release gate (Epic 126)**: a dedicated Linux/Windows/macOS
matrix and `Streaming12ReleaseGate` enforce memory, spool, cleanup, copy,
transfer, determinism, and file-handle budgets. The runnable release receipt,
migration guide, stability registry, and feature-isolation gates complete
the bounded-streaming program.

### Changed

- **Prefetch admission under load**: the bounded prefetch preflight now
accounts for the producer lease held while a full queue blocks in addition
to queued and consumer leases. This removes a scheduler-dependent
end-of-stream error while preserving fail-closed memory behavior.

- **GPU voxel dispatch and truthful Auto policy**: headless wgpu compute now
prefers a high-performance adapter while retaining an explicit low-power
option. Batched bitonic-sort/prefix-scan command recording and device-side
Expand Down Expand Up @@ -579,7 +610,8 @@ stubtest CI.
- COPC partial reads (bounds + LOD) in the library and `spatialrust-mvp` CLI.
- wgpu voxel downsampling with automatic CPU/GPU policy selection.

[Unreleased]: https://github.com/rsasaki0109/SpatialRust/compare/v1.1.0...HEAD
[Unreleased]: https://github.com/rsasaki0109/SpatialRust/compare/v1.2.0...HEAD
[1.2.0]: https://github.com/rsasaki0109/SpatialRust/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/rsasaki0109/SpatialRust/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/rsasaki0109/SpatialRust/releases/tag/v1.0.0
[0.1.0]: https://github.com/rsasaki0109/SpatialRust/releases/tag/v0.1.0
62 changes: 31 additions & 31 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ exclude = ["crates/spatialrust-py"]
resolver = "2"

[workspace.package]
version = "1.1.0"
version = "1.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
authors = ["SpatialRust Contributors"]
Expand All @@ -47,36 +47,36 @@ rust-version = "1.75"
description = "Next-generation spatial computing framework for Rust"

[workspace.dependencies]
spatialrust-core = { path = "crates/spatialrust-core", version = "1.1.0" }
spatialrust-math = { path = "crates/spatialrust-math", version = "1.1.0" }
spatialrust-io = { path = "crates/spatialrust-io", version = "1.1.0" }
spatialrust-gpu = { path = "crates/spatialrust-gpu", version = "1.1.0" }
spatialrust-search = { path = "crates/spatialrust-search", version = "1.1.0" }
spatialrust-filtering = { path = "crates/spatialrust-filtering", version = "1.1.0" }
spatialrust-features = { path = "crates/spatialrust-features", version = "1.1.0" }
spatialrust-segmentation = { path = "crates/spatialrust-segmentation", version = "1.1.0" }
spatialrust-registration = { path = "crates/spatialrust-registration", version = "1.1.0" }
spatialrust-pipeline = { path = "crates/spatialrust-pipeline", version = "1.1.0" }
spatialrust-metrics = { path = "crates/spatialrust-metrics", version = "1.1.0", default-features = false }
spatialrust-transform = { path = "crates/spatialrust-transform", version = "1.1.0", default-features = false }
spatialrust-voxelize = { path = "crates/spatialrust-voxelize", version = "1.1.0", default-features = false }
spatialrust-image = { path = "crates/spatialrust-image", version = "1.1.0" }
spatialrust-image-io = { path = "crates/spatialrust-image-io", version = "1.1.0", default-features = false }
spatialrust-tensor = { path = "crates/spatialrust-tensor", version = "1.1.0", default-features = false }
spatialrust-ai = { path = "crates/spatialrust-ai", version = "1.1.0", default-features = false }
spatialrust-camera = { path = "crates/spatialrust-camera", version = "1.1.0" }
spatialrust-vision = { path = "crates/spatialrust-vision", version = "1.1.0", default-features = false }
spatialrust-records = { path = "crates/spatialrust-records", version = "1.1.0" }
spatialrust-arrow = { path = "crates/spatialrust-arrow", version = "1.1.0", default-features = false }
spatialrust-sync = { path = "crates/spatialrust-sync", version = "1.1.0", default-features = false }
spatialrust-mapping = { path = "crates/spatialrust-mapping", version = "1.1.0", default-features = false }
spatialrust-scene = { path = "crates/spatialrust-scene", version = "1.1.0", default-features = false }
spatialrust-semantic = { path = "crates/spatialrust-semantic", version = "1.1.0" }
spatialrust-episode = { path = "crates/spatialrust-episode", version = "1.1.0" }
spatialrust-runtime = { path = "crates/spatialrust-runtime", version = "1.1.0", default-features = false }
spatialrust-interchange = { path = "crates/spatialrust-interchange", version = "1.1.0", default-features = false }
spatialrust-distribute = { path = "crates/spatialrust-distribute", version = "1.1.0" }
spatialrust-platform = { path = "crates/spatialrust-platform", version = "1.1.0" }
spatialrust-core = { path = "crates/spatialrust-core", version = "1.2.0" }
spatialrust-math = { path = "crates/spatialrust-math", version = "1.2.0" }
spatialrust-io = { path = "crates/spatialrust-io", version = "1.2.0" }
spatialrust-gpu = { path = "crates/spatialrust-gpu", version = "1.2.0" }
spatialrust-search = { path = "crates/spatialrust-search", version = "1.2.0" }
spatialrust-filtering = { path = "crates/spatialrust-filtering", version = "1.2.0" }
spatialrust-features = { path = "crates/spatialrust-features", version = "1.2.0" }
spatialrust-segmentation = { path = "crates/spatialrust-segmentation", version = "1.2.0" }
spatialrust-registration = { path = "crates/spatialrust-registration", version = "1.2.0" }
spatialrust-pipeline = { path = "crates/spatialrust-pipeline", version = "1.2.0" }
spatialrust-metrics = { path = "crates/spatialrust-metrics", version = "1.2.0", default-features = false }
spatialrust-transform = { path = "crates/spatialrust-transform", version = "1.2.0", default-features = false }
spatialrust-voxelize = { path = "crates/spatialrust-voxelize", version = "1.2.0", default-features = false }
spatialrust-image = { path = "crates/spatialrust-image", version = "1.2.0" }
spatialrust-image-io = { path = "crates/spatialrust-image-io", version = "1.2.0", default-features = false }
spatialrust-tensor = { path = "crates/spatialrust-tensor", version = "1.2.0", default-features = false }
spatialrust-ai = { path = "crates/spatialrust-ai", version = "1.2.0", default-features = false }
spatialrust-camera = { path = "crates/spatialrust-camera", version = "1.2.0" }
spatialrust-vision = { path = "crates/spatialrust-vision", version = "1.2.0", default-features = false }
spatialrust-records = { path = "crates/spatialrust-records", version = "1.2.0" }
spatialrust-arrow = { path = "crates/spatialrust-arrow", version = "1.2.0", default-features = false }
spatialrust-sync = { path = "crates/spatialrust-sync", version = "1.2.0", default-features = false }
spatialrust-mapping = { path = "crates/spatialrust-mapping", version = "1.2.0", default-features = false }
spatialrust-scene = { path = "crates/spatialrust-scene", version = "1.2.0", default-features = false }
spatialrust-semantic = { path = "crates/spatialrust-semantic", version = "1.2.0" }
spatialrust-episode = { path = "crates/spatialrust-episode", version = "1.2.0" }
spatialrust-runtime = { path = "crates/spatialrust-runtime", version = "1.2.0", default-features = false }
spatialrust-interchange = { path = "crates/spatialrust-interchange", version = "1.2.0", default-features = false }
spatialrust-distribute = { path = "crates/spatialrust-distribute", version = "1.2.0" }
spatialrust-platform = { path = "crates/spatialrust-platform", version = "1.2.0" }

bytemuck = { version = "1", features = ["derive"] }
las = "0.9"
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,12 @@ The fail-closed [Vision 2 release receipt](docs/VISION_2_RELEASE_RECEIPT.md)
and [migration guide](docs/VISION_2_MIGRATION.md) record the canonical
performance/resource budgets and explicit CPU/GPU ownership guidance.

SpatialRust 1.2 adds deterministic bounded-memory point-cloud execution across
local/HTTP IO, chunk-safe operations, Rust/CLI/Python workflows, and explicit
spill. See the [streaming release receipt](docs/STREAMING_RELEASE_RECEIPT.md)
and [migration guide](docs/STREAMING_MIGRATION.md) for limits, stability, and
reproduction commands.

## Workspace crates

One dataflow, focused crates — each pipeline stage maps to the crate that implements it, all sitting on a small math/core/search foundation:
Expand Down
5 changes: 4 additions & 1 deletion crates/spatialrust-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ mod format;
mod options;
#[cfg(feature = "streaming")]
mod spool;
#[cfg(feature = "streaming")]
#[cfg(all(
feature = "streaming",
any(feature = "io-pcd", feature = "io-ply", feature = "io-las", feature = "io-copc")
))]
mod streaming;
mod traits;

Expand Down
2 changes: 2 additions & 0 deletions crates/spatialrust-platform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod gate;
mod lts;
mod security;
mod stability;
mod streaming;
mod vision;
mod vision2;

Expand All @@ -20,5 +21,6 @@ pub use gate::{ReleaseGate, ReleaseGateDecision};
pub use lts::{LtsPolicy, SupportWindow};
pub use security::{SecurityAuditItem, SecurityChecklist};
pub use stability::{ApiStabilityClass, ApiSurfaceItem, StabilityRegistry};
pub use streaming::{Streaming12Measurements, Streaming12ReleaseEvidence, Streaming12ReleaseGate};
pub use vision::{Vision1Measurements, Vision1ReleaseEvidence, Vision1ReleaseGate};
pub use vision2::{Vision2Measurements, Vision2ReleaseEvidence, Vision2ReleaseGate};
47 changes: 47 additions & 0 deletions crates/spatialrust-platform/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,39 @@ impl StabilityRegistry {
registry
}

/// Seeds the SpatialRust 1.2 bounded-streaming release surface.
#[must_use]
pub fn bounded_streaming_v1_2_surface() -> Self {
let mut registry = Self::new();
for path in [
"spatialrust-records::MemoryBudget",
"spatialrust-records::MemoryTracker",
"spatialrust-records::CancellationToken",
"spatialrust-records::StreamOptions",
"spatialrust-records::StreamingReceipt",
"spatialrust-records::SpatialRecordChunk",
"spatialrust-records::BoundedSpatialRecordSource",
"spatialrust-records::BoundedSpatialRecordSink",
] {
registry.register(path, ApiStabilityClass::Stable);
}
for path in [
"spatialrust-io::PcdChunkSource",
"spatialrust-io::PlyChunkSource",
"spatialrust-io::LasChunkSource",
"spatialrust-io::CopcChunkSource",
"spatialrust-io::BoundedSpool",
"spatialrust-pipeline::ChunkMapSource",
"spatialrust-pipeline::StreamingVoxelSource",
"spatialrust-pipeline::StreamingPipeline",
"spatialrust::spatialrust-stream",
"spatialrust-py::PointCloudStream",
] {
registry.register(path, ApiStabilityClass::Provisional);
}
registry
}

/// Seeds the north-star crate surface used by Epic 100 gates.
#[must_use]
pub fn north_star_surface() -> Self {
Expand Down Expand Up @@ -220,4 +253,18 @@ mod tests {
);
assert_eq!(registry.experimental_count(), 0);
}

#[test]
fn streaming_surface_freezes_contracts_but_not_adapters() {
let registry = StabilityRegistry::bounded_streaming_v1_2_surface();
assert_eq!(
registry.lookup("spatialrust-records::StreamingReceipt").unwrap().class,
ApiStabilityClass::Stable
);
assert_eq!(
registry.lookup("spatialrust-pipeline::StreamingPipeline").unwrap().class,
ApiStabilityClass::Provisional
);
assert_eq!(registry.experimental_count(), 0);
}
}
Loading
Loading