From a9c278e32a5885e5872acf38b233117a7e8a634c Mon Sep 17 00:00:00 2001 From: Sebastian <106036+schoeller@users.noreply.github.com> Date: Sun, 6 Sep 2026 11:22:01 +0200 Subject: [PATCH] ocs_doc_api: update docs + fix review-drift findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - lib.rs: export all 14 facade handles (add ArcCurve/Ellipse/Spline/Ray/XLine/Text/ MText/Dimension + Circle) — public surface matches collection return types. - build.rs: fix step-1 comment (enums are hand-maintained, not 'regenerated'); generic_reference_md: Clone (not Copy) + full 14-handle list (was stale 6). - ops.rs/query.rs: correct 'hand-maintained' module doc comments (were 'GENERATED'). - layouts.json: extend to all 22 Operation + 12 Query variants (was stale phase-1). - binding_schema.json regenerated (complete layouts + derived handles). - generate.py: inject 'id': self.id for SetTextContent/SetAttribute/SetViewportView/ Transform/Delete/AddVertex (was malformed id-less payloads); _apply_op/_apply_query accept want=None; extend PY_TYPES (String/&str/Vec returns/new handles). - README.md: Clone (not Copy) + full scope (2D curves, annotations, containers, viewports, media) replacing stale 'Not yet' list. - Plan (.kilo): mark implemented & published; pointer to live crate docs. --- crates/ocs_doc_api/README.md | 20 +++++++++++---- .../ocs_doc_api/bindings/python/generate.py | 25 ++++++++++++------- crates/ocs_doc_api/build.rs | 12 +++++---- crates/ocs_doc_api/src/gen/api_reference.md | 5 ++-- .../ocs_doc_api/src/gen/binding_schema.json | 21 ++++++++++++++-- crates/ocs_doc_api/src/gen/layouts.json | 21 ++++++++++++++-- crates/ocs_doc_api/src/lib.rs | 5 ++-- crates/ocs_doc_api/src/ops.rs | 7 +++--- crates/ocs_doc_api/src/query.rs | 6 +++-- 9 files changed, 90 insertions(+), 32 deletions(-) diff --git a/crates/ocs_doc_api/README.md b/crates/ocs_doc_api/README.md index 7da56b893..bbbc6c433 100644 --- a/crates/ocs_doc_api/README.md +++ b/crates/ocs_doc_api/README.md @@ -41,7 +41,7 @@ fn intersect_solids(api: &DocApi) -> ApiResult<()> { ([`InProcess`]) or over the `ocs_plugin_api` IPC channel ([`OcsPluginApiIpc`]); only the `Transport` differs. The host executes them through one crate-owned executor. -- **Stable across async IPC** — handles are `Copy`, `Send`, `Sync` `{ObjectId, +- **Stable across async IPC** — handles are `Clone`, `Send`, `Sync` `{ObjectId, Arc}` tokens, safe to share across plugin worker threads. A stale handle's methods return `ApiError::UnknownId`, never a panic. @@ -67,10 +67,20 @@ fn intersect_solids(api: &DocApi) -> ApiResult<()> { booleans (union/intersect/subtract), transform, and queries (bounds/volume/centroid). Host resolves bodies via the `solid_models` cache (lift-on-miss from ACIS SAT). -- **Minimal 2D** — line, circle, polyline, point (construction + bounds); used as - boolean/sweep inputs. -- Not yet: sweep/revolve profiles, `AddVertex`, non-solid transforms, annotations, - containers (insert/block), viewports, media. See `IMPLEMENTATION.md`. +- **Solids** — primitives (cuboid, sphere, cylinder, cone, torus, wedge), sweep + (`extrude`/`revolve` from profiles, `loft` multi-profile), booleans + (union/intersect/subtract), transform, and queries (bounds/volume/centroid). + Host resolves bodies via the `solid_models` cache (lift-on-miss from ACIS SAT). +- **2D curves** — line, circle, arc, polyline (`add_vertex`), point (incl. bulk), + ellipse, spline, ray, xline; construction + bounds + transform (solids & 2D via + `transform`/`transform_many`). +- **Annotations** — `Text`/`MText` (create + `content`/`set_content`), `Hatch` + (create + `boundary` query), linear `Dimension` (create + `measurement`). +- **Containers** — `create_insert` (block references) + `attributes`/`set_attribute` + + `block_entities` (read-only nested block traversal). +- **Paper-space** — `create_viewport` + `set_view` (retarget/re-zoom) + `viewport_view`. +- **Media** — `create_raster_image`; other media families read-only (`EntityView`). +- See `IMPLEMENTATION.md` for the full capability matrix and phased roadmap. ## Features diff --git a/crates/ocs_doc_api/bindings/python/generate.py b/crates/ocs_doc_api/bindings/python/generate.py index ba725ea21..b48acbc2f 100644 --- a/crates/ocs_doc_api/bindings/python/generate.py +++ b/crates/ocs_doc_api/bindings/python/generate.py @@ -62,8 +62,14 @@ class {handle}: PY_TYPES = { "Solid": "'Solid'", "Line": "'Line'", "Circle": "'Circle'", "Polyline": "'Polyline'", "Point": "'Point'", "Entity": "'Entity'", - "f64": "float", "bool": "bool", "usize": "int", - "[f64; 3]": "tuple", "ObjectId": "ObjectId", "()": "None", "None": "None", + "ArcCurve": "'ArcCurve'", "Ellipse": "'Ellipse'", "Spline": "'Spline'", + "Ray": "'Ray'", "XLine": "'XLine'", "Text": "'Text'", "MText": "'MText'", + "Dimension": "'Dimension'", + "f64": "float", "bool": "bool", "usize": "int", "i32": "int", + "[f64; 3]": "tuple", "[f64; 2]": "tuple", "ObjectId": "ObjectId", + "String": "str", "&str": "str", "()": "None", "None": "None", + "Vec<(String, String)>": "list", "Vec>": "list", + "([f64; 3], f64)": "tuple", "Vec": "list", "Vec": "list", } def py_type(rust_ty: str) -> str: @@ -115,16 +121,17 @@ def render_method(m: Dict[str, Any]) -> str: if args: body_items.append(f"'b': {args[0]['name']}.id") body_items.append(f"'erase_sources': {py_lit((m.get('fixed') or {}).get('erase_sources', True))}") - elif variant in ("GetVolume", "GetCentroid", "GetBounds", "GetEntity"): + elif variant in ("GetVolume", "GetCentroid", "GetBounds", "GetEntity", "GetTextContent", "GetHatchBoundary", "GetDimensionMeasurement", "GetAttributes", "GetViewportView"): body_items.append("'id': self.id") + elif variant in ("SetTextContent", "SetAttribute", "SetViewportView", "Transform", "Delete", "AddVertex"): + # Op variants that carry the receiver ObjectId: inject it first. + body_items.append("'id': self.id") + for a in args: + body_items.append(f"'{a['name']}': {a['name']}") elif variant == "GetIntersects": body_items.append("'a': self.id") if args: body_items.append(f"'b': {args[0]['name']}.id") - elif variant == "AddVertex": - body_items.append("'id': self.id") - for a in args: - body_items.append(f"'{a['name']}': {a['name']}") else: for a in args: body_items.append(f"'{a['name']}': {a['name']}") @@ -151,11 +158,11 @@ class Document: _transport: Any _tab: int - def _apply_op(self, op, want): + def _apply_op(self, op, want=None): env = DocApiEnvelope(ENVELOPE_VERSION, ("Op", op)) return self._transport.apply(env) - def _apply_query(self, q, want): + def _apply_query(self, q, want=None): env = DocApiEnvelope(ENVELOPE_VERSION, ("Queries", [q])) return self._transport.apply(env) diff --git a/crates/ocs_doc_api/build.rs b/crates/ocs_doc_api/build.rs index 084227843..d76626f5e 100644 --- a/crates/ocs_doc_api/build.rs +++ b/crates/ocs_doc_api/build.rs @@ -110,9 +110,10 @@ fn main() { let gen_dir = manifest_dir.join("src/gen"); fs::create_dir_all(&gen_dir).unwrap(); - // 1. Regenerate the ops/query enum snapshots (deterministic; these are the - // curated v1 variants — the spec drives docs/schema, the enums are the - // stable wire vocabulary appended at end only). + // 1. Emit the HAND-MAINTAINED ops/query enum snapshots verbatim. The enums are + // NOT derived from the spec here — they are the canonical append-only wire + // vocabulary; the spec's `op`/`query` names must map to variants (asserted + // by a test). `write_if_changed` is effectively a no-op round-trip. write_if_changed(&gen_dir.join("ops_gen.rs"), &ops_gen_src()); write_if_changed(&gen_dir.join("query_gen.rs"), &query_gen_src()); @@ -149,8 +150,9 @@ fn fmt_args(args: &[Arg]) -> String { fn generic_reference_md() -> String { r#"## Generic methods (every handle) -Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `Entity`) is a -`Copy`, `Send`, `Sync` token `{ ObjectId, session }` and supports: +Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `ArcCurve`, +`Ellipse`, `Spline`, `Ray`, `XLine`, `Text`, `MText`, `Dimension`, `Entity`) is a +`Clone`, `Send`, `Sync` token `{ ObjectId, session }` and supports: - **`id()` -> `ObjectId`** — the stable entity identity. - **`bounds()` -> `Aabb`** — coarse bounding box (solids lift-on-miss; 2D entities diff --git a/crates/ocs_doc_api/src/gen/api_reference.md b/crates/ocs_doc_api/src/gen/api_reference.md index b4f17ebd6..6adefe030 100644 --- a/crates/ocs_doc_api/src/gen/api_reference.md +++ b/crates/ocs_doc_api/src/gen/api_reference.md @@ -178,8 +178,9 @@ Table (read-only): GetEntity kind; generic delete. No typed create/bounds in v1. ## Generic methods (every handle) -Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `Entity`) is a -`Copy`, `Send`, `Sync` token `{ ObjectId, session }` and supports: +Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `ArcCurve`, +`Ellipse`, `Spline`, `Ray`, `XLine`, `Text`, `MText`, `Dimension`, `Entity`) is a +`Clone`, `Send`, `Sync` token `{ ObjectId, session }` and supports: - **`id()` -> `ObjectId`** — the stable entity identity. - **`bounds()` -> `Aabb`** — coarse bounding box (solids lift-on-miss; 2D entities diff --git a/crates/ocs_doc_api/src/gen/binding_schema.json b/crates/ocs_doc_api/src/gen/binding_schema.json index a405f67cb..69a2d72a2 100644 --- a/crates/ocs_doc_api/src/gen/binding_schema.json +++ b/crates/ocs_doc_api/src/gen/binding_schema.json @@ -410,7 +410,18 @@ "Delete { id: ObjectId }", "CreateMany(Vec)", "TransformMany { ids: Vec, placement: PlacementSpec }", - "DeleteMany(Vec)" + "DeleteMany(Vec)", + "CreateInsert(InsertSpec)", + "CreateViewport(ViewportSpec)", + "CreateText(TextSpec)", + "CreateMText(MTextSpec)", + "SetTextContent { id: ObjectId, value: String }", + "CreateHatch(HatchSpec)", + "CreateDimensionLinear(DimensionSpec)", + "SetAttribute { id: ObjectId, tag: String, value: String }", + "SetViewportView { id: ObjectId, view_target: [f64; 3], view_height: f64 }", + "CreateRasterImage(RasterImageSpec)", + "Loft { profiles: Vec }" ] }, "Query": { @@ -420,7 +431,13 @@ "GetCentroid { id: ObjectId }", "GetVolume { id: ObjectId }", "GetIntersects { a: ObjectId, b: ObjectId }", - "GetGeometryRevision" + "GetGeometryRevision", + "GetTextContent { id: ObjectId }", + "GetHatchBoundary { id: ObjectId }", + "GetDimensionMeasurement { id: ObjectId }", + "GetAttributes { id: ObjectId }", + "GetBlockEntities { block_name: String }", + "GetViewportView { id: ObjectId }" ] } }, diff --git a/crates/ocs_doc_api/src/gen/layouts.json b/crates/ocs_doc_api/src/gen/layouts.json index 4f78f25a3..4a9edb9d5 100644 --- a/crates/ocs_doc_api/src/gen/layouts.json +++ b/crates/ocs_doc_api/src/gen/layouts.json @@ -12,7 +12,18 @@ "Delete { id: ObjectId }", "CreateMany(Vec)", "TransformMany { ids: Vec, placement: PlacementSpec }", - "DeleteMany(Vec)" + "DeleteMany(Vec)", + "CreateInsert(InsertSpec)", + "CreateViewport(ViewportSpec)", + "CreateText(TextSpec)", + "CreateMText(MTextSpec)", + "SetTextContent { id: ObjectId, value: String }", + "CreateHatch(HatchSpec)", + "CreateDimensionLinear(DimensionSpec)", + "SetAttribute { id: ObjectId, tag: String, value: String }", + "SetViewportView { id: ObjectId, view_target: [f64; 3], view_height: f64 }", + "CreateRasterImage(RasterImageSpec)", + "Loft { profiles: Vec }" ] }, "Query": { @@ -22,7 +33,13 @@ "GetCentroid { id: ObjectId }", "GetVolume { id: ObjectId }", "GetIntersects { a: ObjectId, b: ObjectId }", - "GetGeometryRevision" + "GetGeometryRevision", + "GetTextContent { id: ObjectId }", + "GetHatchBoundary { id: ObjectId }", + "GetDimensionMeasurement { id: ObjectId }", + "GetAttributes { id: ObjectId }", + "GetBlockEntities { block_name: String }", + "GetViewportView { id: ObjectId }" ] } } diff --git a/crates/ocs_doc_api/src/lib.rs b/crates/ocs_doc_api/src/lib.rs index 45a2c205a..5521d1578 100644 --- a/crates/ocs_doc_api/src/lib.rs +++ b/crates/ocs_doc_api/src/lib.rs @@ -46,8 +46,9 @@ pub use revision::GeometryRevision; pub use envelope::{DocApiEnvelope, EnvelopeBody, OpOutcome, Receipt}; pub use facade::{ - CurveCollection, DocApi, Document, Entity, EntityCollection, HasId, Line, OpGroup, Point, - Polyline, QueryBatch, QueryResults, Solid, SolidCollection, + ArcCurve, Circle, CurveCollection, Dimension, DocApi, Document, Ellipse, Entity, + EntityCollection, HasId, Line, MText, OpGroup, Point, Polyline, QueryBatch, QueryResults, Ray, + Solid, SolidCollection, Spline, Text, XLine, }; pub use ops::{BoolOp, Curve2Spec, EntitySpec, Operation, PlacementSpec, SolidPrimitive}; pub use query::{Aabb, EntityView, Query, QueryResult}; diff --git a/crates/ocs_doc_api/src/ops.rs b/crates/ocs_doc_api/src/ops.rs index e041f89b0..a1f47bf00 100644 --- a/crates/ocs_doc_api/src/ops.rs +++ b/crates/ocs_doc_api/src/ops.rs @@ -1,7 +1,8 @@ //! Write operations — the typed, transport-agnostic vocabulary for changing the -//! document (plan §5). The `Operation` enum itself is GENERATED into -//! `crate::gen` by `build.rs` from `spec/entities.toml`; this module re-exports -//! it and holds the hand-written payload mirrors. +//! document (plan §5). The `Operation` enum is **hand-maintained** (append-only) +//! in `src/gen/ops_gen.rs` — it is NOT derived from the spec by build.rs; the +//! spec's `op` names must each map to a variant here (asserted by a test). This +//! module re-exports it and holds the hand-written payload mirrors. use serde::{Deserialize, Serialize}; diff --git a/crates/ocs_doc_api/src/query.rs b/crates/ocs_doc_api/src/query.rs index 4b9f82076..b65702149 100644 --- a/crates/ocs_doc_api/src/query.rs +++ b/crates/ocs_doc_api/src/query.rs @@ -1,6 +1,8 @@ //! Read queries — typed, transport-agnostic reads of entity state (plan §5). -//! The `Query` enum is GENERATED into `crate::gen` by `build.rs`; this module -//! re-exports it and holds the hand-written result DTOs. +//! The `Query` enum is **hand-maintained** (append-only) in `src/gen/query_gen.rs` +//! — NOT derived from the spec by build.rs (the spec's `query` names must map to +//! a variant here, asserted by a test). This module re-exports it and holds the +//! hand-written result DTOs. use serde::{Deserialize, Serialize};