diff --git a/crates/op-cli/src/app_control_cli.rs b/crates/op-cli/src/app_control_cli.rs index 8059d2353..f4ac980df 100644 --- a/crates/op-cli/src/app_control_cli.rs +++ b/crates/op-cli/src/app_control_cli.rs @@ -9,7 +9,11 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; const PID_FILE_NAME: &str = "openpencil-mcp-server.pid"; const PORT_FILE_NAME: &str = "openpencil-mcp-server.port"; const TOKEN_FILE_NAME: &str = "openpencil-mcp-server.token"; -const MINIMAL_DOCUMENT: &str = "{\n \"version\": \"0.8.0\",\n \"name\": \"OpenPencil CLI Session\",\n \"children\": []\n}\n"; +const MINIMAL_DOCUMENT: &str = concat!( + "{\n \"version\": \"", + env!("CARGO_PKG_VERSION"), + "\",\n \"name\": \"OpenPencil CLI Session\",\n \"children\": []\n}\n" +); /// Rust live-canvas discovery file (`~/.openpencil/.op-mcp-port`), written /// by the running editor when its `McpLiveServer` binds. Deliberately diff --git a/crates/op-cli/src/tests.rs b/crates/op-cli/src/tests.rs index 9cf2bca9b..a4b9301cc 100644 --- a/crates/op-cli/src/tests.rs +++ b/crates/op-cli/src/tests.rs @@ -103,7 +103,10 @@ fn start_document_file_is_minimal_op_when_missing() { assert_eq!( std::fs::read_to_string(&path).expect("read document"), - "{\n \"version\": \"0.8.0\",\n \"name\": \"OpenPencil CLI Session\",\n \"children\": []\n}\n" + format!( + "{{\n \"version\": \"{}\",\n \"name\": \"OpenPencil CLI Session\",\n \"children\": []\n}}\n", + env!("CARGO_PKG_VERSION") + ) ); let _ = std::fs::remove_dir_all(&dir); } diff --git a/crates/op-editor-core/src/host_support.rs b/crates/op-editor-core/src/host_support.rs index fe117baf6..ed3b321e2 100644 --- a/crates/op-editor-core/src/host_support.rs +++ b/crates/op-editor-core/src/host_support.rs @@ -35,7 +35,7 @@ impl EditorState { /// [`EditorState::starter`] (a single empty Frame) instead. pub fn sample() -> Self { let src = r##"{ - "version": "0.8.0", + "version": "__OPENPENCIL_VERSION__", "children": [ {"type":"frame","id":"n10","name":"Frame", "x":40,"y":40,"width":360,"height":240, @@ -56,7 +56,8 @@ impl EditorState { ]} ] }"##; - let doc = jian_ops_schema::load_str(src) + let src = src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION")); + let doc = jian_ops_schema::load_str(&src) .expect("EditorState::sample() fixture parses") .value; let mut state = Self::from_document(doc); @@ -69,7 +70,7 @@ impl EditorState { /// document geometry. No default selection and no demo decoration. pub fn starter() -> Self { let src = r##"{ - "version": "0.8.0", + "version": "__OPENPENCIL_VERSION__", "children": [ {"type":"frame","id":"n10","name":"Frame", "x":0,"y":0,"width":1200,"height":800, @@ -77,7 +78,8 @@ impl EditorState { "children":[]} ] }"##; - let doc = jian_ops_schema::load_str(src) + let src = src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION")); + let doc = jian_ops_schema::load_str(&src) .expect("EditorState::starter() fixture parses") .value; Self::from_document(doc) @@ -644,6 +646,7 @@ mod tests { #[test] fn sample_has_the_demo_tree_and_anchors_selection() { let s = EditorState::sample(); + assert_eq!(s.doc.version, env!("CARGO_PKG_VERSION")); assert_eq!(s.doc.children.len(), 1); assert_eq!(s.selection.anchor, NodeId::new("n11")); // The frame + its two children are present. @@ -653,6 +656,7 @@ mod tests { #[test] fn starter_is_a_single_empty_frame_with_nothing_selected() { let s = EditorState::starter(); + assert_eq!(s.doc.version, env!("CARGO_PKG_VERSION")); // Exactly one top-level node — the starter Frame. The // `max_node_id() == 10` check proves no demo children: // the n11..n14 sample tree would lift it to 14. @@ -754,14 +758,15 @@ mod tests { #[test] fn replace_paths_with_polyline_inherits_first_source_style() { let src = r##"{ - "version": "0.8.0", + "version": "__OPENPENCIL_VERSION__", "children": [ {"type":"rectangle","id":"n10","x":0,"y":0,"width":20,"height":20, "fill":[{"type":"solid","color":"#ff0000"}]}, {"type":"rectangle","id":"n11","x":10,"y":0,"width":20,"height":20} ] }"##; - let doc = jian_ops_schema::load_str(src) + let src = src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION")); + let doc = jian_ops_schema::load_str(&src) .expect("fixture parses") .value; let mut s = EditorState::from_document(doc); diff --git a/crates/op-editor-core/src/state.rs b/crates/op-editor-core/src/state.rs index 996f25149..c3cbb4e09 100644 --- a/crates/op-editor-core/src/state.rs +++ b/crates/op-editor-core/src/state.rs @@ -165,7 +165,7 @@ impl EditorState { } /// Build an editor state around an empty single-page document. - /// `version` is set to the current `.op` format version literal; + /// `version` is set to the current Cargo package version; /// `children` is empty (no nodes) and `pages` is left `None` so /// the document uses the default single-page fallback. pub fn new() -> Self { @@ -327,7 +327,7 @@ impl Default for EditorState { /// An empty canonical document — `version` set, no nodes, no pages. fn empty_document() -> jian_ops_schema::PenDocument { jian_ops_schema::PenDocument { - version: "0.8.0".to_string(), + version: env!("CARGO_PKG_VERSION").to_owned(), name: None, themes: None, variables: None, @@ -352,6 +352,7 @@ mod tests { #[test] fn new_state_is_empty_and_quiescent() { let s = EditorState::new(); + assert_eq!(s.doc.version, env!("CARGO_PKG_VERSION")); assert!(s.doc.children.is_empty()); assert!(s.doc.pages.is_none()); // Persisted variables/themes live on `doc`, not duplicated. diff --git a/crates/op-host-desktop/Cargo.toml b/crates/op-host-desktop/Cargo.toml index 34273bfab..a0cc9b02f 100644 --- a/crates/op-host-desktop/Cargo.toml +++ b/crates/op-host-desktop/Cargo.toml @@ -62,7 +62,7 @@ role = "Editor" # Phase 7.3 reorg: openpencil-shell-core dissolved — widget facade / # render-backend / layout scene paths resolve through op-editor-ui. op-editor-ui = { path = "../op-editor-ui" } -op-host-native = { path = "../op-host-native", version = "0.8.1", features = ["gl-host"] } +op-host-native = { path = "../op-host-native", features = ["gl-host"] } # Phase 2: the headless daemon crate. The `--serve-web` closure migrates here # over Phases 2-5; op-host-desktop's serve-web dispatch + GUI residuals call into # it via `op_host_services::*`.