From 08c07604d0045edcffcf84d2defa1bb30e1c7a7f Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Sun, 17 May 2026 00:01:35 +0800 Subject: [PATCH] chore(ci): re-point tooling + CI workflows at the op-host-* crates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 7.3 strangler reorg — update every reference to the renamed / dissolved crates across the boundary scripts and CI workflows. tools/: - check-wasm-bundle.sh: openpencil-shell-web -> op-host-web; the wasm-bindgen output filenames follow the op_host_web lib name - check-jian-boundaries.sh: shell-native -> op-host-native, shell-web -> op-host-web - check-widget-boundary.sh: WEB_SRC + path-exclusion regexes -> crates/op-host-web; openpencil_shell_core::widgets -> op_editor_ui::widgets (the dissolved shim's real source crate) .github/workflows/: - rust-multiplatform.yml: wasm + mobile-check jobs -> op-host-web / op-host-native; the mobile shell-core clean check -> op-editor-ui - rust-release.yml: cargo build -p openpencil-desktop -> -p op-host-desktop (the shipped executable name is unchanged) - wasm-bundle-check.yml: -p openpencil-shell-web -> -p op-host-web Cargo.toml skia-patch comment updated. Boundary checks pass; the wasm-bundle gate cleanly skips while EMSDK is unset. --- .github/workflows/rust-multiplatform.yml | 15 +++--- .github/workflows/rust-release.yml | 10 ++-- .github/workflows/wasm-bundle-check.yml | 2 +- Cargo.toml | 2 +- tools/check-jian-boundaries.sh | 23 +++++---- tools/check-wasm-bundle.sh | 14 +++--- tools/check-widget-boundary.sh | 64 ++++++++++++------------ 7 files changed, 66 insertions(+), 64 deletions(-) diff --git a/.github/workflows/rust-multiplatform.yml b/.github/workflows/rust-multiplatform.yml index e74879253..dd6d0dc3c 100644 --- a/.github/workflows/rust-multiplatform.yml +++ b/.github/workflows/rust-multiplatform.yml @@ -115,11 +115,11 @@ jobs: if: matrix.cross == false && matrix.check_only != true && runner.os != 'Linux' run: cargo test --workspace --target ${{ matrix.target }} # Desktop binary artifact upload is intentionally not wired here yet. - # The real desktop binary lives in the `openpencil-desktop` crate; a + # The real desktop binary lives in the `op-host-desktop` crate; a # build + upload step can be added once release packaging is finalized. wasm-web: - name: wasm32-unknown-unknown / openpencil-shell-web (compile guard) + name: wasm32-unknown-unknown / op-host-web (compile guard) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -140,7 +140,7 @@ jobs: # (brew emscripten install + EMSDK + .wasm.a symlink hack + # wasm-bindgen + wasm-opt) lands. Until then this job only proves # the public surface compiles wasm32-clean. - - run: cargo build -p openpencil-shell-web --target wasm32-unknown-unknown --release --no-default-features --features web + - run: cargo build -p op-host-web --target wasm32-unknown-unknown --release --no-default-features --features web # Artifact upload deliberately removed: the stub `.wasm` from this # path would mislead downstream consumers into thinking the shell can # render. Restore the upload step once the skia-enabled build runs on @@ -179,11 +179,12 @@ jobs: with: key: mobile-${{ matrix.target }} # Step 1a spec §11 mobile invariants verify on iOS / Android cargo check: - # - shell-core wasm32/ios/android-clean (no platform deps). - # - shell-native compiles on mobile targets with EaglProvider / + # - op-editor-ui wasm32/ios/android-clean (no platform deps) — the + # widget facade / editor-UI composition crate. + # - op-host-native compiles on mobile targets with EaglProvider / # AndroidEglProvider stubs (`unimplemented!("Step 1f")`); desktop GL # stack (glutin / winit) is target-gated to desktop in Cargo.toml + # GlutinProvider source is cfg-gated to desktop OS only. Real SDK # linking and iOS/Android runtime is Step 1f. - - run: cargo check -p openpencil-shell-core --target ${{ matrix.target }} - - run: cargo check -p openpencil-shell-native --target ${{ matrix.target }} + - run: cargo check -p op-editor-ui --target ${{ matrix.target }} + - run: cargo check -p op-host-native --target ${{ matrix.target }} diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index 34340d405..e9344ad05 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -2,9 +2,9 @@ name: Rust release artifacts # Triggered on tag push (v*) — builds release binaries across desktop targets # and assembles a GitHub Release draft. The `build` job builds the real -# `openpencil-desktop` crate (winit + skia-safe runner that drives the Rust -# shell); the deleted `openpencil-app` placeholder crate is gone (Phase 1 -# Task 1.2). Full DMG / AppImage / EXE installer packaging lands in Step 1f. +# `op-host-desktop` crate (winit + skia-safe runner that drives the Rust +# editor); its shipped executable keeps the stable `openpencil-desktop` +# name. Full DMG / AppImage / EXE installer packaging lands in Step 1f. # The wasm web bundle is currently DEFERRED (see comment block below); when # the CI-side C-hard pipeline (emscripten install + EMSDK + symlink hack + # wasm-bindgen + wasm-opt) lands it will re-enter the matrix. @@ -76,10 +76,10 @@ jobs: run: cargo install cross --locked --version 0.2.5 - name: Build (host) if: matrix.cross != true - run: cargo build -p openpencil-desktop --target ${{ matrix.target }} --release + run: cargo build -p op-host-desktop --target ${{ matrix.target }} --release - name: Build (cross) if: matrix.cross == true - run: cross build -p openpencil-desktop --target ${{ matrix.target }} --release + run: cross build -p op-host-desktop --target ${{ matrix.target }} --release - name: Package archive (unix) if: matrix.archive == 'tar.gz' shell: bash diff --git a/.github/workflows/wasm-bundle-check.yml b/.github/workflows/wasm-bundle-check.yml index c6faae8af..44be709a2 100644 --- a/.github/workflows/wasm-bundle-check.yml +++ b/.github/workflows/wasm-bundle-check.yml @@ -29,7 +29,7 @@ jobs: - name: Forward — bucket A crates compile on wasm32 run: | cargo check --target wasm32-unknown-unknown \ - -p openpencil-shell-web --no-default-features --features web + -p op-host-web --no-default-features --features web wasm32-deny: name: cargo-deny --target wasm32-unknown-unknown check bans diff --git a/Cargo.toml b/Cargo.toml index 8373469a6..6cb419f72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ tracing = "0.1" # # IMPORTANT: `[patch.crates-io]` is workspace-global, NOT target-scoped. # Every `skia-safe` / `skia-bindings` consumer in this workspace — -# including `openpencil-shell-native` (macOS / Linux / Windows desktop, +# including `op-host-native` (macOS / Linux / Windows desktop, # `gl` feature) — now resolves through this fork on every target. # Cargo does not natively support per-target patches, so this is the # accepted blast radius. diff --git a/tools/check-jian-boundaries.sh b/tools/check-jian-boundaries.sh index 385c20c03..20aac57bc 100755 --- a/tools/check-jian-boundaries.sh +++ b/tools/check-jian-boundaries.sh @@ -4,10 +4,11 @@ # Verifies the following Jian crate boundary invariants from outside the # Rust build system. Run from the repo root. # -# (The former Invariant 1 — "openpencil-app must not depend directly on +# (The former Invariant 1 — "the app crate must not depend directly on # any jian-* crate" — was dropped in Phase 1 Task 1.2 along with the -# `openpencil-app` placeholder crate. Step 1f reintroduces a real app -# crate; reinstate an equivalent facade check against it then.) +# old placeholder crate. The Phase 7.3 reorg reintroduced a real +# composition-root crate, `op-app`; reinstate an equivalent facade +# check against it if/when op-app grows beyond a thin re-export.) # # Invariant 2 (§11.1, §12.3 — REVISED 2026-05-10): mobile targets # (`aarch64-linux-android`, `aarch64-apple-ios`) must NOT pull @@ -21,12 +22,12 @@ # Step 1f via the existing `EaglProvider` / `AndroidEglProvider` # plugin point. # -# Invariant 3 (§11.1, §1.2): wasm32 builds of `openpencil-shell-web` +# Invariant 3 (§11.1, §1.2): wasm32 builds of `op-host-web` # must NOT pull `jian-host-desktop` or `jian-skia` (skia-safe build.rs # fails on wasm32; Jian-core is wasm32-clean per P0.5 and is the only # Jian crate allowed in the bundle). # -# Invariant 4 (§1.2): `openpencil-shell-web` must NOT depend on +# Invariant 4 (§1.2): `op-host-web` must NOT depend on # `jian-host-desktop` at all — even as a non-default optional dep. # # Exit codes: @@ -52,7 +53,7 @@ fi # because it pulls winit / glutin / desktop GLContextProvider impls # that have no mobile equivalent. for target in aarch64-linux-android aarch64-apple-ios; do - tree_mobile="$(cargo tree -p openpencil-shell-native \ + tree_mobile="$(cargo tree -p op-host-native \ --target "$target" \ --prefix none \ --edges normal,build 2>/dev/null || true)" @@ -68,7 +69,7 @@ done # ── Invariant 3: wasm32 has no jian-host-desktop / jian-skia. ────────── # `jian-core` IS allowed (P0.5 wasm32-clean). -tree_wasm="$(cargo tree -p openpencil-shell-web \ +tree_wasm="$(cargo tree -p op-host-web \ --target wasm32-unknown-unknown \ --prefix none \ --edges normal,build 2>/dev/null || true)" @@ -76,22 +77,22 @@ forbidden_wasm="$(echo "$tree_wasm" \ | grep -oE '\bjian-(host-desktop|skia)\b' \ | sort -u || true)" if [ -n "$forbidden_wasm" ]; then - echo "INVARIANT 3 FAILED: wasm32 openpencil-shell-web pulls forbidden Jian crates:" >&2 + echo "INVARIANT 3 FAILED: wasm32 op-host-web pulls forbidden Jian crates:" >&2 echo "$forbidden_wasm" >&2 exit 1 fi -# ── Invariant 4: openpencil-shell-web has no jian-host-desktop dep. ─── +# ── Invariant 4: op-host-web has no jian-host-desktop dep. ─── # Distinct from invariant 3 (which checks the resolved closure on the # wasm32 target): this checks the manifest itself across all targets. # `cargo tree --all-targets` would include dev-deps; we explicitly # filter `--edges normal,build` for the manifest-level invariant. -shell_web_deps="$(cargo tree -p openpencil-shell-web \ +shell_web_deps="$(cargo tree -p op-host-web \ --prefix none \ --edges normal,build 2>/dev/null \ | grep -E '\bjian-host-desktop\b' || true)" if [ -n "$shell_web_deps" ]; then - echo "INVARIANT 4 FAILED: openpencil-shell-web depends on jian-host-desktop:" >&2 + echo "INVARIANT 4 FAILED: op-host-web depends on jian-host-desktop:" >&2 echo "$shell_web_deps" >&2 exit 1 fi diff --git a/tools/check-wasm-bundle.sh b/tools/check-wasm-bundle.sh index d0b97100e..bcdbe3927 100755 --- a/tools/check-wasm-bundle.sh +++ b/tools/check-wasm-bundle.sh @@ -7,9 +7,9 @@ # + wasm-aware clang (build-time only; emscripten runtime is NOT # linked into the bundle — see spec §2.2). # 2. cargo build → wasm-bindgen → wasm-opt -Oz pipeline produces -# crates/openpencil-shell-web/pkg/openpencil_shell_web_bg.wasm. +# crates/op-host-web/pkg/op_host_web_bg.wasm. # 3. Post-bindgen bundle has 0 env.* imports -# (i.e. all imports come from `./openpencil_shell_web_bg.js`, +# (i.e. all imports come from `./op_host_web_bg.js`, # the wasm-bindgen JS shim). Any env.* import = LinkError at # load time → regression → fail. # 4. Post wasm-opt -Oz gzip size ≤ STEP1B_SHELL_WASM_GZIP_LIMIT_BYTES @@ -31,11 +31,11 @@ set -euo pipefail -CRATE_DIR="crates/openpencil-shell-web" +CRATE_DIR="crates/op-host-web" PKG_DIR="${CRATE_DIR}/pkg" -WASM_RAW="${PKG_DIR}/openpencil_shell_web_bg.wasm" -WASM_OPT="${PKG_DIR}/openpencil_shell_web_bg.opt.wasm" -TARGET_WASM="target/wasm32-unknown-unknown/release/openpencil_shell_web.wasm" +WASM_RAW="${PKG_DIR}/op_host_web_bg.wasm" +WASM_OPT="${PKG_DIR}/op_host_web_bg.opt.wasm" +TARGET_WASM="target/wasm32-unknown-unknown/release/op_host_web.wasm" # Spec §6 row "Per-component ceiling — shell-web wasm (cdylib) gzip" # = 1 MiB. Override via env for experiments only. @@ -54,7 +54,7 @@ need gzip [ -n "${EMSDK:-}" ] || { printf 'EMSDK env var unset (needed for emsdk libcxx headers + wasm-aware clang)\n' >&2; exit 2; } step 2 5 "Build shell-web wasm32-unknown-unknown with --features skia" -cargo build -p openpencil-shell-web \ +cargo build -p op-host-web \ --target wasm32-unknown-unknown --features skia --release >/dev/null step 3 5 "wasm-bindgen --target web → ${PKG_DIR}/" diff --git a/tools/check-widget-boundary.sh b/tools/check-widget-boundary.sh index 30f783234..81519af35 100755 --- a/tools/check-widget-boundary.sh +++ b/tools/check-widget-boundary.sh @@ -3,7 +3,7 @@ # # Per spec §1.4: widget logic (Widget impls, layout/paint/access_node) # lives in `crates/op-editor-ui/src/widgets/` (Phase 7 reorg moved it -# out of openpencil-shell-core). shell-web's +# out of the old openpencil-shell-core). The op-host-web crate's # widget glue is scoped to a single module — `widget_host.rs` plus # its sibling submodules under `widget_host/` (spec amendment # 2026-05-11: the original "one file" constraint conflicted with @@ -12,35 +12,35 @@ # span multiple sibling files inside the `widget_host/` directory). # The `// glue:` marker on the paint signature is still the only # `fn paint(` allowed to drive widgets from this crate. -# Any function or file in shell-web that pulls -# `openpencil_shell_core::widgets::*` must live in the widget_host -# module (the spec's "any function pulling shell-core widgets" clause). +# Any function or file in op-host-web that pulls +# `op_editor_ui::widgets::*` must live in the widget_host +# module (the spec's "any function pulling the widget facade" clause). # # Reverse direction: op-editor-ui/src/widgets/ MUST contain four impl # files (tree, prop_row, dropdown, text_input) AND each file must # carry a real `impl Widget for X` — a stale file with the impl -# removed must not silently pass. (Phase 7 reorg: the widget facade -# moved out of openpencil-shell-core into the op-editor-ui crate; -# shell-web still pulls `openpencil_shell_core::widgets` via the -# shell-core re-export shim, so the forward F4 path is unchanged.) +# removed must not silently pass. (Phase 7.3 reorg: the +# openpencil-shell-core re-export shim was dissolved; op-host-web +# now pulls `op_editor_ui::widgets` directly from the real source +# crate, so the forward F4 path is unchanged.) # # Exit semantics: # 0 PASS — both invariants hold. -# 1 FAIL — widget logic leaked into shell-web OR shell-core -# widget impl files are missing / empty. +# 1 FAIL — widget logic leaked into op-host-web OR the +# op-editor-ui widget impl files are missing / empty. set -euo pipefail -WEB_SRC="crates/openpencil-shell-web/src" +WEB_SRC="crates/op-host-web/src" CORE_WIDGETS="crates/op-editor-ui/src/widgets" fail_lines=() # --------------------------------------------------------------------- # Forward F1: no `impl Widget for X` (with optional generic params and -# arbitrary namespace segments) anywhere under shell-web/src/. +# arbitrary namespace segments) anywhere under op-host-web/src/. # Even widget_host.rs is not allowed to host a Widget impl — all real -# impls live in shell-core. The `// glue:` exemption is for the paint +# impls live in op-editor-ui. The `// glue:` exemption is for the paint # signature only, not for Widget trait impls (codex B4 R2 CONCERN-2). # --------------------------------------------------------------------- # `impl(<...>)?[[:space:]]+(ns::)*Widget[[:space:]]+for[[:space:]]`: @@ -54,12 +54,12 @@ impl_hits="$(grep -RInE \ 'impl(<[^>]+>)?[[:space:]]+([[:alnum:]_]+::)*Widget[[:space:]]+for[[:space:]]' \ "${WEB_SRC}" 2>/dev/null || true)" if [ -n "${impl_hits}" ]; then - fail_lines+=("Forward F1: Widget trait impl in shell-web (must live in shell-core):" "${impl_hits}") + fail_lines+=("Forward F1: Widget trait impl in op-host-web (must live in op-editor-ui):" "${impl_hits}") fi # --------------------------------------------------------------------- # Forward F2: no `fn layout(` / `fn access_node(` anywhere under -# shell-web/src/. These are widget-trait method signatures and have +# op-host-web/src/. These are widget-trait method signatures and have # no business in the platform crate. (Note: `fn paint(` is allowed # only on the `// glue:` marked line in widget_host.rs — handled by # F3 below to keep the exemption tight.) @@ -73,11 +73,11 @@ trait_method_hits="$(grep -RInE \ 'fn[[:space:]]+(layout|access_node)\(' \ "${WEB_SRC}" 2>/dev/null || true)" if [ -n "${trait_method_hits}" ]; then - fail_lines+=("Forward F2: Widget trait method (layout / access_node) in shell-web:" "${trait_method_hits}") + fail_lines+=("Forward F2: Widget trait method (layout / access_node) in op-host-web:" "${trait_method_hits}") fi # --------------------------------------------------------------------- -# Forward F3: `fn paint(` under shell-web is allowed ONLY when the +# Forward F3: `fn paint(` under op-host-web is allowed ONLY when the # line ALSO carries the `// glue:` marker AND the file is # widget_host.rs. Tight exemption (codex B4 R2 CONCERN-2 — broad # `// glue:` exemption could hide leaked impl/method lines if anyone @@ -118,13 +118,13 @@ if [ -n "${paint_hits}" ]; then } { prev_was_glue = 0 } ' "${WEB_SRC}/widget_host.rs" "${WEB_SRC}/widget_host"/*.rs 2>/dev/null || true)" - # `outside_module_files` — files in shell-web/src/ that + # `outside_module_files` — files in op-host-web/src/ that # define `fn paint(` but are NOT in the widget_host module # at all. These violate F3 unconditionally. outside_module_files="$(grep -RIlE \ 'fn[[:space:]]+paint[[:space:]]*[<(]' \ "${WEB_SRC}" 2>/dev/null \ - | grep -vE '^crates/openpencil-shell-web/src/widget_host(\.rs|/[^/]+\.rs)$' \ + | grep -vE '^crates/op-host-web/src/widget_host(\.rs|/[^/]+\.rs)$' \ | LC_ALL=C sort -u || true)" outside_module_hits="" if [ -n "${outside_module_files}" ]; then @@ -142,29 +142,29 @@ if [ -n "${paint_hits}" ]; then fi fi if [ -n "${combined_paint}" ]; then - fail_lines+=("Forward F3: fn paint( in shell-web without a '// glue:' marker on the immediately preceding line, OR outside the widget_host module (allowed locations: widget_host.rs and widget_host/* sibling files):" "${combined_paint}") + fail_lines+=("Forward F3: fn paint( in op-host-web without a '// glue:' marker on the immediately preceding line, OR outside the widget_host module (allowed locations: widget_host.rs and widget_host/* sibling files):" "${combined_paint}") fi fi # --------------------------------------------------------------------- -# Forward F4: only widget_host.rs may import `openpencil_shell_core:: +# Forward F4: only widget_host.rs may import `op_editor_ui:: # widgets` in any form. Catches: -# - `use openpencil_shell_core::widgets;` (direct) -# - `use openpencil_shell_core::widgets::Foo;` (direct) -# - `use openpencil_shell_core::{widgets};` (grouped) -# - `use openpencil_shell_core::{widgets::Foo};` (grouped) -# - `openpencil_shell_core::widgets::call()` (path expr) +# - `use op_editor_ui::widgets;` (direct) +# - `use op_editor_ui::widgets::Foo;` (direct) +# - `use op_editor_ui::{widgets};` (grouped) +# - `use op_editor_ui::{widgets::Foo};` (grouped) +# - `op_editor_ui::widgets::call()` (path expr) # - Multi-line grouped imports are NOT caught (single-line # scope only — code review enforces single-line use stmts in this # crate; the cost-benefit doesn't justify a multi-line parser). # # Codex B4 R2 BLOCK-fix introduced F4; R3 BLOCK refined for grouped # import forms — the previous regex required a literal `::widgets` -# right after `openpencil_shell_core`, missing the brace form. -# Solution: any line mentioning `openpencil_shell_core` AND `widgets` +# right after `op_editor_ui`, missing the brace form. +# Solution: any line mentioning `op_editor_ui` AND `widgets` # is a hit (single grep pass picks both patterns up). # --------------------------------------------------------------------- -core_ref_hits="$(grep -RIn 'openpencil_shell_core' "${WEB_SRC}" 2>/dev/null || true)" +core_ref_hits="$(grep -RIn 'op_editor_ui' "${WEB_SRC}" 2>/dev/null || true)" if [ -n "${core_ref_hits}" ]; then # Filter to lines that ALSO mention `widgets`, then drop the # widget_host.rs allowance. @@ -172,10 +172,10 @@ if [ -n "${core_ref_hits}" ]; then # `widget_host/` (spec amendment 2026-05-11). illegal_imports="$(printf '%s\n' "${core_ref_hits}" \ | grep 'widgets' \ - | grep -vE '^crates/openpencil-shell-web/src/widget_host(\.rs|/[^/]+\.rs):' \ + | grep -vE '^crates/op-host-web/src/widget_host(\.rs|/[^/]+\.rs):' \ || true)" if [ -n "${illegal_imports}" ]; then - fail_lines+=("Forward F4: openpencil_shell_core::widgets reference outside widget_host.rs (covers direct + grouped use forms):" "${illegal_imports}") + fail_lines+=("Forward F4: op_editor_ui::widgets reference outside widget_host.rs (covers direct + grouped use forms):" "${illegal_imports}") fi fi @@ -189,7 +189,7 @@ fi # not silently satisfy the check. The stripping uses sed to drop # `//`-prefixed content (after optional leading whitespace) before # grepping; block comments (`/* … */`) are not handled because the -# Rust style in shell-core/src/widgets/ uses line comments only. +# Rust style in op-editor-ui/src/widgets/ uses line comments only. # --------------------------------------------------------------------- required_widgets=("tree" "prop_row" "dropdown" "text_input") for w in "${required_widgets[@]}"; do