diff --git a/.github/actions/headless-host/action.yml b/.github/actions/headless-host/action.yml index b6a8ba0..45b4ae0 100644 --- a/.github/actions/headless-host/action.yml +++ b/.github/actions/headless-host/action.yml @@ -1,12 +1,17 @@ name: Headless browser host description: > - Build chuzz-headless and install ps-qa, so a site's built output can be driven - through a real browser engine with no window. + Download the released chuzz-headless browser and install ps-qa, so a site's + built output can be driven through a real browser engine with no window. inputs: chuzz-ref: - description: The chuzz revision to build the host from. + description: The chuzz revision to build only when no released binary exists. default: master + chuzz-version: + description: > + Released browser version. Empty reads the version from the action's own + Cargo.toml, keeping callers on the binary released with this action. + default: "" token: description: > A token that can read pathscale/chuzz. Optional: chuzz is public, so the @@ -22,24 +27,65 @@ inputs: default: "" ps-qa-version: description: > - The driver's version requirement. A floor rather than "latest": a check - file can use a field an older driver does not know, and the failure then - reads as a broken workflow rather than a driver that is too old. - - 0.7.1 uses the shared control protocol and rejects checks that silently - inherit another file's page. Keep the driver on the same protocol line - as the headless host. - default: "^0.7.1" + The driver's compatible protocol line. Cargo installs the newest + published 0.7 release, keeping the driver and headless host on the same + protocol line without pinning a patch release. + default: "^0.7" outputs: host: - description: Path to the built chuzz-headless binary. - value: ${{ steps.build.outputs.host }} + description: Path to the verified chuzz-headless binary. + value: ${{ steps.acquire.outputs.host }} runs: using: composite steps: - - name: Check out chuzz + - name: Acquire released browser + id: acquire + shell: bash + env: + REQUESTED_VERSION: ${{ inputs.chuzz-version }} + ACTION_ROOT: ${{ github.action_path }}/../../.. + run: | + if [ "$(uname -s)" != "Linux" ] || [ "$(uname -m)" != "x86_64" ]; then + echo "::error::the released chuzz-headless host supports Linux x86_64" + exit 1 + fi + version="$REQUESTED_VERSION" + if [ -z "$version" ]; then + version=$(sed -n 's/^version = "\([^"]*\)"/\1/p' "$ACTION_ROOT/Cargo.toml" | head -1) + fi + case "$version" in + ''|*[!0-9A-Za-z.+-]*) + echo "::error::invalid chuzz version '$version'" + exit 1 + ;; + esac + + asset=chuzz-headless-x86_64-unknown-linux-gnu.tar.gz + release=https://github.com/pathscale/chuzz/releases/download/headless-v$version + directory="$RUNNER_TEMP/chuzz-headless-$version" + mkdir -p "$directory" + + if curl -fsSL --retry 3 --retry-delay 2 "$release/$asset" -o "$directory/$asset" && \ + curl -fsSL --retry 3 --retry-delay 2 "$release/$asset.sha256" -o "$directory/$asset.sha256" && \ + (cd "$directory" && sha256sum -c "$asset.sha256"); then + tar -xzf "$directory/$asset" -C "$directory" + chmod +x "$directory/chuzz-headless" + if [ "$(cat "$directory/VERSION")" != "$version" ]; then + echo "::error::released browser version does not match $version" + exit 1 + fi + echo "released=true" >> "$GITHUB_OUTPUT" + echo "using released chuzz-headless $version" + else + echo "::warning::no verified chuzz-headless $version release; building ${{ inputs.chuzz-ref }} from source" + echo "released=false" >> "$GITHUB_OUTPUT" + fi + echo "host=$directory/chuzz-headless" >> "$GITHUB_OUTPUT" + + - name: Check out chuzz source fallback + if: steps.acquire.outputs.released != 'true' uses: actions/checkout@v4 with: repository: pathscale/chuzz @@ -56,26 +102,30 @@ runs: shell: bash run: | sudo apt-get update - sudo apt-get install -y pkg-config libfontconfig1-dev fonts-dejavu-core + packages=(fontconfig fonts-dejavu-core) + if [ "${{ steps.acquire.outputs.released }}" != "true" ]; then + packages+=(pkg-config libfontconfig1-dev) + fi + sudo apt-get install -y "${packages[@]}" - uses: Swatinem/rust-cache@v2 + if: steps.acquire.outputs.released != 'true' with: workspaces: .qa-host # A failing check must not make the corrective run rebuild a browser # engine from zero. cache-on-failure: true - # The driver links no renderer, so it installs from the registry. The host - # is built here because it is the browser, and the browser is not a crate a - # site can install. + # The driver links no renderer, so it installs from the registry. The + # browser is a versioned release asset built once by Chuzz's release job. - name: Install ps-qa shell: bash env: CARGO_TARGET_DIR: .qa-host/target/qa-tools run: cargo install ps-qa --version "${{ inputs.ps-qa-version }}" - - name: Build the host - id: build + - name: Build source fallback + if: steps.acquire.outputs.released != 'true' shell: bash run: | # `--no-default-features` drops `gui`, and with it `tauri`, `muda -> gtk` @@ -84,4 +134,4 @@ runs: cargo build --release --manifest-path .qa-host/Cargo.toml \ --bin chuzz-headless --no-default-features \ --features capture,javascript,scrollbars,webp,system-fonts - echo "host=$PWD/.qa-host/target/release/chuzz-headless" >> "$GITHUB_OUTPUT" + cp .qa-host/target/release/chuzz-headless "${{ steps.acquire.outputs.host }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33a3e9d..042acc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,6 +71,52 @@ jobs: - name: Test run: cargo test -p chuzz-control --all-features + # The fleet's website QA consumes this exact feature set as a prebuilt Linux + # release asset. Build and drive it here once, in the repository that owns + # the browser, before a version can reach the release workflow. + headless: + runs-on: ubicloud-standard-4 + steps: + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: Install native font dependencies + run: | + sudo apt-get update + sudo apt-get install -y pkg-config libfontconfig1-dev fonts-dejavu-core + + - name: Cache cargo build + uses: Swatinem/rust-cache@v2 + with: + shared-key: chuzz-linux-headless-ci + cache-targets: true + + - name: Build and package the headless browser + run: scripts/package-headless.sh + + - name: Test the packaged feature set + run: | + cargo test --release -p chuzz \ + --no-default-features \ + --features capture,javascript,scrollbars,webp,system-fonts \ + --test serves_inspection + + - name: Verify the release archive + run: | + cd target/headless-release + sha256sum -c chuzz-headless-x86_64-unknown-linux-gnu.tar.gz.sha256 + tar -tzf chuzz-headless-x86_64-unknown-linux-gnu.tar.gz + + - name: Keep the candidate for review + uses: actions/upload-artifact@v4 + with: + name: chuzz-headless-x86_64-unknown-linux-gnu + path: target/headless-release/chuzz-headless-x86_64-unknown-linux-gnu.tar.gz* + if-no-files-found: error + retention-days: 7 + # The frontend, which is where most changes actually land. Independent of the # Rust jobs, so a TypeScript error does not wait on a cargo build. # @@ -121,12 +167,9 @@ jobs: - name: Test run: bun run test:run - # The app itself, on the platform it targets. This is the job that proves a - # change compiles against the pinned engine, which no Linux runner can do. - # - # `build-app.sh` is deliberately not used: bundling, signing and stamping are - # the release job's business. A PR only needs to know the code compiles and - # its tests pass. + # The app itself, on the platform it targets. The visible gate drives the + # same signed bundle a release would publish, including browser chrome, + # settings, theme controls, identity switching and the redraw stress page. app: runs-on: namespace-profile-agency-tahoe steps: @@ -159,3 +202,25 @@ jobs: - name: Test run: cargo test --workspace + + - name: Install the native QA harness + run: cargo install ps-qa --version '^0.7' + + - name: Build the review bundle + run: | + cargo build --release -p chuzz-qa-fixture + apps/chuzz/build-app.sh release + + - name: Drive the visible application + env: + QA_ARTIFACT_DIR: ${{ runner.temp }}/chuzz-visible-qa + run: scripts/qa-visible-app.sh + + - name: Keep visible QA evidence + if: always() + uses: actions/upload-artifact@v4 + with: + name: chuzz-visible-qa + path: ${{ runner.temp }}/chuzz-visible-qa + if-no-files-found: warn + retention-days: 7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb6f0cc..7abee0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,6 +55,7 @@ jobs: outputs: version: ${{ steps.decide.outputs.version }} publish: ${{ steps.decide.outputs.publish }} + headless_publish: ${{ steps.decide.outputs.headless_publish }} steps: - name: Checkout uses: actions/checkout@v4 @@ -101,6 +102,73 @@ jobs: echo "Live is already $LIVE; nothing to do. Bump [workspace.package] version to release." fi + HEADLESS=https://github.com/pathscale/chuzz/releases/download/headless-v$VERSION/chuzz-headless-x86_64-unknown-linux-gnu.tar.gz + if [ "${{ inputs.force }}" = "true" ]; then + echo "headless_publish=true" >> "$GITHUB_OUTPUT" + elif curl -fsSIL --max-time 30 "$HEADLESS" >/dev/null 2>&1 && \ + curl -fsSIL --max-time 30 "$HEADLESS.sha256" >/dev/null 2>&1; then + echo "headless_publish=false" >> "$GITHUB_OUTPUT" + echo "The Linux headless asset for $VERSION is already published." + else + echo "headless_publish=true" >> "$GITHUB_OUTPUT" + echo "The Linux headless asset for $VERSION is missing; publishing it." + fi + + # Build the Linux QA browser once per Chuzz release. Fleet repositories use + # the checksum-verified asset through the composite headless-host action; + # they no longer each compile the same renderer and browser graph. + headless: + needs: check + if: needs.check.outputs.headless_publish == 'true' + runs-on: ubicloud-standard-4 + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: Install native font dependencies + run: | + sudo apt-get update + sudo apt-get install -y pkg-config libfontconfig1-dev fonts-dejavu-core + + - name: Cache cargo build + uses: Swatinem/rust-cache@v2 + with: + shared-key: chuzz-linux-headless-release + cache-targets: true + + - name: Build and package the headless browser + run: scripts/package-headless.sh + + - name: Test the packaged feature set + run: | + cargo test --release -p chuzz \ + --no-default-features \ + --features capture,javascript,scrollbars,webp,system-fonts \ + --test serves_inspection + + - name: Publish the versioned headless asset + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ needs.check.outputs.version }} + run: | + tag="headless-v$VERSION" + if ! gh release view "$tag" >/dev/null 2>&1; then + gh release create "$tag" \ + --target "$GITHUB_SHA" \ + --title "Chuzz headless $VERSION" \ + --notes "Linux x86_64 native ps-qa host with capture, JavaScript, scrollbars, WebP, and system-font discovery." \ + --prerelease + fi + gh release upload "$tag" \ + target/headless-release/chuzz-headless-x86_64-unknown-linux-gnu.tar.gz \ + target/headless-release/chuzz-headless-x86_64-unknown-linux-gnu.tar.gz.sha256 \ + --clobber + release: needs: check if: needs.check.outputs.publish == 'true' @@ -121,7 +189,7 @@ jobs: # day a new engine package was added, because a path dependency resolves # against whatever is on disk and no local build could notice. # - # `Cargo.toml` now takes ps-blitz, tauri-runtime-blitz and endpoint-libs + # `Cargo.toml` now takes ps-blitz, izumo and endpoint-libs # from crates.io on a caret, and no lockfile is committed, so this job # resolves the newest published versions that satisfy the ranges. An # ordinary `cargo build` on any machine resolves the same thing. See @@ -171,6 +239,9 @@ jobs: with: targets: aarch64-apple-darwin + - name: Install the native QA harness + run: cargo install ps-qa --version '^0.7' + - name: Cache cargo build uses: Swatinem/rust-cache@v2 with: @@ -207,6 +278,22 @@ jobs: exit 1 fi + - name: Drive the exact release bundle + env: + QA_ARTIFACT_DIR: ${{ runner.temp }}/chuzz-visible-qa + run: | + cargo build --release -p chuzz-qa-fixture + scripts/qa-visible-app.sh "$BUNDLE_DIR/Chuzz.app" + + - name: Keep visible QA evidence + if: always() + uses: actions/upload-artifact@v4 + with: + name: chuzz-visible-qa-release-${{ needs.check.outputs.version }} + path: ${{ runner.temp }}/chuzz-visible-qa + if-no-files-found: warn + retention-days: 14 + # Tauri produces this tarball as a side effect of its bundler. Chuzz has no # Tauri, so it is packed here. COPYFILE_DISABLE stops bsdtar writing an # AppleDouble `._` sidecar beside every file carrying an extended diff --git a/.gitignore b/.gitignore index 039ce90..8a7d94e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,6 @@ node_modules/ apps/chuzz/dist/ -# Handover notes are session state, tracked locally and never committed. -docs/HANDOVER-*.md - # Local-only renderer patch, see the file itself. .cargo/config.toml .cargo/config.toml.disabled @@ -22,11 +19,15 @@ apps/chuzz/gen/ # exist on one machine. See scripts/local-engine.sh. .cargo/local-engine.toml +# Handover and session notes are working state, not repository content. +HANDOVER*.md +docs/HANDOVER*.md + # Lockfiles are not committed here. Every dependency is a caret range on a # published version, so a build resolves the newest thing that satisfies it and # a broken upstream release fails the build that introduced it. A committed lock # turns that into a pin nobody chose: it kept the workspace on ps-blitz 0.4.4 -# and tauri-runtime-blitz 0.3.6 for as long as those satisfied the caret, so +# and tauri-runtime-blitz 0.3.6 (now izumo) for as long as those satisfied the caret, so # fixes that had already shipped were invisible to every build and to CI. Cargo.lock bun.lock diff --git a/AGENTS.md b/AGENTS.md index 672ea10..99c0b0e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,12 +25,12 @@ Do not reach for `rev` or `=` either: a git revision cannot be published and an exact pin is a range of one, so both split the graph the same way. A git `endpoint-libs` alongside the registry copy is precisely how this repository - ended up with two of it. There are no exceptions left: `tauri-runtime-blitz` - was the last git dependency, and it is `^0.1.0` from crates.io like the rest. + ended up with two of it. There are no exceptions left: `izumo` + was the last git dependency, and it is `^0.4` from crates.io like the rest. - **No lockfiles are committed. Not `Cargo.lock`, not `bun.lock`.** They were, and a lockfile is the one thing that can hold a caret dependency still: any version already recorded satisfies `^`, so cargo never reconsiders it. This - workspace sat on `ps-blitz` 0.4.4 and `tauri-runtime-blitz` 0.3.6 that way + workspace sat on `ps-blitz` 0.4.4 and `tauri-runtime-blitz` 0.3.6 (now izumo) that way while 0.4.5 and 0.3.7 were published, carrying fixes chuzz needed, and neither a local build nor CI could see it. A stale-but-valid pin is the dangerous kind; a stale-and-invalid one repairs itself, which is why the boa dependency @@ -48,7 +48,7 @@ points at directories that exist on one machine and the next plain `cargo build` would silently reuse it. Patch only the crates you are actually changing; every entry is a pin that stops being tested. -- When you move the engine version, move `tauri-runtime-blitz`'s to match. Both +- When you move the engine version, move `izumo`'s to match. Both resolve a ps-blitz, and two different ones put two engines in the graph, which surfaces as missing methods and unrelated `PaintScene` traits rather than as a version error. A caret on both sides makes the shared range the thing that @@ -56,6 +56,27 @@ - Work on a branch and ship through a pull request. Do not commit to `main`. - Run `cargo fmt --all -- --check`, `cargo clippy --workspace --all-targets --all-features -- -D warnings`, and `cargo test --workspace --all-features` before delivery. +## Invariants (do not break these) + +- **No Python.** Not a script, not `python3 -c`, not a heredoc. Do not swap it + for another ad hoc parser or assume `jq` is present: it does not ship with + macOS. Ask the tool that owns the answer for structured output. A fixed-shape + field can use one `sed -nE` line; logic that needs real parsing belongs in + this repository's Rust code, where it can be tested. + +## Handover documents are never committed + +Never commit a handover, status or session-summary document to this repository. +They are working notes for the owner and belong in the conversation. If one is +tracked, untrack it rather than editing it. + +## Merged is not fixed + +Only the owner closes a bug. A merged PR means the change shipped. Call it +finished only after the owner confirms it or after the exact reported path has +been driven on a running build. When that cannot be verified here, state what +remains unverified. + ## Git workflow - **Always specify the branch when pushing**: `git push origin branch-name` diff --git a/Cargo.toml b/Cargo.toml index 6a2a012..fa7a3e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["apps/chuzz", "crates/chuzz-control"] +members = ["apps/chuzz", "crates/chuzz-control", "crates/chuzz-qa-fixture"] resolver = "3" [workspace.package] -version = "0.1.38" +version = "0.1.39" edition = "2024" rust-version = "1.91" license = "MIT OR Apache-2.0" @@ -20,7 +20,7 @@ homepage = "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/pathscale/chuzz" # nothing reconciled: the pin sat 44 commits behind while local builds moved on. # A revision fixed that and introduced its own tax, because a git dependency is # not a version: every engine release meant editing eight lines here and a -# matching set in `tauri-runtime-blitz`, and the day those disagreed cargo put +# matching set in `izumo`, and the day those disagreed cargo put # two engines in the graph and reported it as # # expected `blitz_script::document::ScriptDocument`, found `ScriptDocument` @@ -32,21 +32,22 @@ homepage = "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/pathscale/chuzz" # the same range gets the same crate rather than a second copy. To build against # a working checkout, see `scripts/local-engine.sh`; it is opt-in so the default # exercises what a release actually resolves. -blitz-dom = { package = "ps-blitz-dom", version = "^0.4.9" } -blitz-html = { package = "ps-blitz-html", version = "^0.4.9" } -blitz-net = { package = "ps-blitz-net", version = "^0.4.9" } -blitz-script = { package = "ps-blitz-script", version = "^0.4.9" } -blitz-traits = { package = "ps-blitz-traits", version = "^0.4.9" } +blitz-dom = { package = "ps-blitz-dom", version = "^0.4" } +blitz-html = { package = "ps-blitz-html", version = "^0.4" } +blitz-net = { package = "ps-blitz-net", version = "^0.4" } +blitz-script = { package = "ps-blitz-script", version = "^0.4" } +blitz-traits = { package = "ps-blitz-traits", version = "^0.4" } # The wasmi host binding over blitz-dom-api, so a WebAssembly guest can build a # document with no JavaScript and no URL in the path. -blitz-wasm = { package = "ps-blitz-wasm", version = "^0.4.9" } -dioxus-native = { package = "ps-dioxus-native", version = "^0.7.3", default-features = false } +blitz-wasm = { package = "ps-blitz-wasm", version = "^0.4" } +dioxus-native = { package = "ps-dioxus-native", version = "^0.7", default-features = false } # The MCP framing the control server speaks, same source and feature as -# tauri-runtime-blitz uses for its agent-control surface. +# izumo uses for its agent-control surface. # The one control surface: wire vocabulary, the document core, and both -# transports. It used to be reached through `tauri-runtime-blitz`, which meant a +# transports. It used to be reached through `izumo`, which meant a # headless browser compiled a Tauri runtime with the runtime switched off. -blitz-control-protocol = { version = "^0.5.1", default-features = false } +blitz-control-protocol = { version = "^0.5", default-features = false } + endpoint-libs = { version = "^3", default-features = false, features = ["agent-control"] } brotli = { version = "8", default-features = false, features = ["std"] } image = { version = "^0.25.6", default-features = false } @@ -68,7 +69,7 @@ image = { version = "^0.25.6", default-features = false } # Both sides take it by version now, so cargo unifies them instead of two people # remembering to. A caret is also what ps-blitz declares, so the ranges agree by # construction rather than by coincidence. -anyrender = { package = "ps-anyrender", version = "^0.13.0" } +anyrender = { package = "ps-anyrender", version = "^0.13" } # `filters` is off by default in the backend, and with it off `push_layer` # discards both the element's `filter:` and its `backdrop-filter:`. # @@ -79,8 +80,8 @@ anyrender = { package = "ps-anyrender", version = "^0.13.0" } # every backdrop inside a layer, which is every backdrop on a real page; the # revision below closes the stack, snapshots, and reopens it, so glass renders # in the CPU paths as well as on the GPU. -anyrender_vello_cpu = { package = "ps-anyrender-vello-cpu", version = "^0.17.0", features = ["filters"] } -blitz-paint = { package = "ps-blitz-paint", version = "^0.4.9" } +anyrender_vello_cpu = { package = "ps-anyrender-vello-cpu", version = "^0.17", features = ["filters"] } +blitz-paint = { package = "ps-blitz-paint", version = "^0.4" } png = "=0.18.1" # Naming `wasmi::Linker` is unavoidable: `blitz_wasm::add_to_linker` takes one, # and blitz-wasm does not re-export the runtime. This must stay on the same @@ -110,9 +111,14 @@ rustls = { version = "0.23", default-features = false, features = [ "aws-lc-rs", "std", ] } +cursor-icon = "^1" +cookie_store = "^0.22.1" +psl = "^2" futures-util = { version = "0.3", default-features = false, features = ["sink"] } +nagoya = "^0.1" tokio = "1" url = "2.5" +worktable = "^1.10.0-beta1" tauri = { version = "^2.11.5", default-features = false } # `diagnostics`, always, rather than behind a cargo feature. # @@ -130,7 +136,7 @@ tauri = { version = "^2.11.5", default-features = false } # explaining. A window that would not paint could not be photographed by the # one thing that could photograph it, because the capability had been optimised # out of the binary that needed it. -tauri-runtime-blitz = { version = "^0.4.0", default-features = false, features = [ +izumo = { version = "^0.4", default-features = false, features = [ "agent-control", "diagnostics", ] } diff --git a/README.md b/README.md index 935bcd7..160185f 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,8 @@ Events are not wired up yet: the page renders and does not respond. ## Rendering without a window -For interactive website QA, build the headless host with fonts and use ps-qa -0.7.1 or newer: +For interactive website QA, build the headless host with fonts and use the +compatible ps-qa 0.7 line: ```sh cargo build --release --bin chuzz-headless --no-default-features \ @@ -106,10 +106,13 @@ ps-qa --app ../worktables.dev/tests/ps-qa/ps-qa.ron qa-hosted \ --checks ../worktables.dev/tests/ps-qa/checks ``` -Linux needs `pkg-config`, `libfontconfig1-dev`, and a font catalogue such as -`fonts-dejavu-core`; the shared headless-host CI action installs these. No desktop -server is needed. The `system-fonts` feature is optional for embedders supplying -their own fonts, but rendered website checks need real glyphs. +Linux source builds need `pkg-config`, `libfontconfig1-dev`, and a font catalogue +such as `fonts-dejavu-core`. The shared headless-host action normally downloads +the versioned Linux x86_64 release asset, verifies its published SHA-256, and +installs only the runtime font catalogue. If that asset is unavailable, the +action builds the same feature set from source. No desktop server is needed. The +`system-fonts` feature is optional for embedders supplying their own fonts, but +rendered website checks need real glyphs. The host dispatches input through the shared `DocumentControl` implementation, including pointer gestures, key-down/up, and scrolling. Once an action has been diff --git a/apps/chuzz/Cargo.toml b/apps/chuzz/Cargo.toml index 1865edb..9761e8f 100644 --- a/apps/chuzz/Cargo.toml +++ b/apps/chuzz/Cargo.toml @@ -55,9 +55,9 @@ default = [ # rasteriser and the inspection socket, which is everything ps-qa drives. gui = [ "dep:tauri", - "dep:tauri-runtime-blitz", + "dep:izumo", "dep:tauri-build", - "tauri-runtime-blitz/runtime", + "izumo/runtime", # The window paints glyphs, so it wants real faces. On Linux this reaches # parley's enumeration and therefore fontconfig, which is why it is here and # not in the base dependencies. Rendered QA opts in through the same feature. @@ -158,16 +158,29 @@ dioxus-native = { workspace = true, optional = true, features = [ "prelude", "svg", ] } -tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] } +nagoya.workspace = true +# Tokio remains the I/O boundary for Tauri, HTTP, TCP and WebSocket. Portable +# timers use Nagoya, so this list names only the runtime/synchronisation surface +# those concrete I/O types require. +# Every tokio API this crate calls, declared here rather than borrowed from +# whatever else in the graph happens to enable it. `rt-multi-thread` is +# `new_multi_thread` and `block_in_place` (serve.rs, script_fetch.rs), `net` and +# `io-util` the page server's sockets. The headless build has no Tauri to switch +# them on, and it stopped compiling once chuzz-control no longer pulled tokio in. +tokio = { workspace = true, features = ["io-util", "macros", "net", "rt", "rt-multi-thread", "sync"] } url.workspace = true serde.workspace = true serde_json.workspace = true tauri = { workspace = true, optional = true } rustls.workspace = true +cursor-icon.workspace = true +cookie_store.workspace = true +psl.workspace = true blitz-control-protocol = { workspace = true, features = ["engine", "server", "capture"] } -tauri-runtime-blitz = { workspace = true, optional = true } +izumo = { workspace = true, optional = true } tokio-tungstenite.workspace = true futures-util.workspace = true +worktable.workspace = true [dev-dependencies] # `flavor = "multi_thread"` in the script-fetch test: the blocking fetch takes @@ -182,7 +195,6 @@ tokio = { workspace = true, features = [ "rt", "rt-multi-thread", "sync", - "time", ] } # Assembles `fixtures/panel.wat` into a module in-process, so the capture test # owns its guest instead of borrowing blitz-wasm's demo, and so it needs no diff --git a/apps/chuzz/frontend/local-ui/bundle/package.json b/apps/chuzz/frontend/local-ui/bundle/package.json index b512770..db3b913 100644 --- a/apps/chuzz/frontend/local-ui/bundle/package.json +++ b/apps/chuzz/frontend/local-ui/bundle/package.json @@ -21,7 +21,7 @@ "**/*" ], "peerDependencies": { - "@pathscale/ui": "^3.1.0", + "@pathscale/ui": "^3.2.3", "solid-js": ">=2.0.0-rc.0", "solid-layouts": "^0.2.1" }, diff --git a/apps/chuzz/frontend/local-ui/package.json b/apps/chuzz/frontend/local-ui/package.json index 86cf80b..5b6cf68 100644 --- a/apps/chuzz/frontend/local-ui/package.json +++ b/apps/chuzz/frontend/local-ui/package.json @@ -9,7 +9,7 @@ "**/*.css" ], "peerDependencies": { - "@pathscale/ui": "^3.1.0", + "@pathscale/ui": "^3.2.3", "solid-js": ">=2.0.0-rc.0", "solid-layouts": "^0.2.1" } diff --git a/apps/chuzz/frontend/local-ui/src/components/panel-handle/PanelHandle.layout.tsx b/apps/chuzz/frontend/local-ui/src/components/panel-handle/PanelHandle.layout.tsx index 5610e5c..f1391e6 100644 --- a/apps/chuzz/frontend/local-ui/src/components/panel-handle/PanelHandle.layout.tsx +++ b/apps/chuzz/frontend/local-ui/src/components/panel-handle/PanelHandle.layout.tsx @@ -3,6 +3,7 @@ import type { Layout } from "solid-layouts"; import { panelHandle } from "./PanelHandle.recipe"; export type PanelHandleProps = { + id: string; title: string; collapsed?: boolean; onClick: JSX.EventHandlerUnion; @@ -18,6 +19,7 @@ export type PanelHandleProps = { */ const PanelHandle: Layout = () => ( + + + + + ); +} diff --git a/apps/chuzz/frontend/src/features/settings/DiagnosticsSection.tsx b/apps/chuzz/frontend/src/features/settings/DiagnosticsSection.tsx index f4179b2..e9d1a64 100644 --- a/apps/chuzz/frontend/src/features/settings/DiagnosticsSection.tsx +++ b/apps/chuzz/frontend/src/features/settings/DiagnosticsSection.tsx @@ -33,6 +33,7 @@ export function DiagnosticsSection(): JSX.Element {