Skip to content

Desktop release packages (macOS .app/.dmg, Windows NSIS, Linux .deb/.AppImage) and release-desktop workflow - #94

Closed
ymote wants to merge 10 commits into
mainfrom
release/desktop-packaging
Closed

ymote wants to merge 10 commits into
mainfrom
release/desktop-packaging

Conversation

@ymote

@ymote ymote commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Makes the desktop (octosense) self-contained and installable, with a tag-triggered workflow that produces unsigned packages. Signing has hooks gated on secrets (none are configured yet).

Includes the closed #85. Its desktop-kernel work is the first commit here: crates/kernel/src/launch.rs finds a packaged octos-kernel[.exe] beside the shell when OCTOS_APP_CORE_BIN is unset, and tools/build-desktop.py stages the locked kernel there. The packages ship that kernel.

Rebased onto main (2026-10-01) as a linear history (8d740e7..459c5bb), with the old merge commits gone. The conflicts and how they were resolved:

  • Cargo.toml / Cargo.lock: main's versions. Package the desktop Octos kernel and update hosted Rinx #85's hosted-Rinx revision 197d5170 is dropped, because main pins Rinx by tag v1.1.0 through native-apps.json. Its [patch."…/OctoSense.git"] redirect, which includes octosense-kernel, is already on main.
  • .gitignore: main's /.sources, plus /desktop/packaging/.release.generated.json.
  • crates/shell/src/octosense/paths.rs: main's private_dir and scope_linked_app_data are kept, followed by packaged() and its uses.
  • desktop/README*.md: main's OCTOSENSE_GLANCE_DEMO row is kept, and the OCTOS_APP_CORE_BIN row describes the packaged-sibling fallback.
  • New commit: main's ci-local drift check (tools/test_ci_local.py, in the desktop job) rejected release-desktop.yml. It is now listed in GITHUB_ONLY (tools/ci_local.py), so drift leaves it alone and ci-local-merge refuses a PR that triggers it. Such a PR waits for GitHub's run. A test and docs/local-ci.md cover this.

Checked after the rebase, in a fresh worktree with python3 tools/setup.py --no-hub. All of these pass:

  • setup.py --check --cargo, native_apps.py --check, python3 -m unittest discover -s tools -p 'test_*.py' (90 tests, including test_build_desktop, test_release_scan and test_ci_local), ci_local.py --check-drift, and rom/tests/test_no_local_paths.py
  • the desktop and phone cargo check --locked builds, and both check-shell-graph.sh runs
  • from phone/: the shell/Home/App Hub/AppCard/ai-host tests, plus the appcard and host_tools runs; cargo test --locked -p octosense-kernel
  • desktop/scripts/test_package.py, tools/build-desktop.py --plan, and desktop/scripts/package.py --print-env --no-kernel

No package was built or scanned after the rebase. The packaging results below are from before it.

What a package contains, and how it is found at run time

  • Resources: built with MAKEPAD_PACKAGE_DIR (MAKEPAD=apple_bundle on macOS), so Makepad reads every crate_resource from the package. desktop/scripts/package.py stages the resources/ of every linked git or path crate, found with cargo tree -p octosense: makepad_widgets (fonts, icons, textures, 61.7 MB), octosense_shell, octosense_app_hub_app, rinx, article_core/article_makepad. They land in Contents/Resources/<crate>/resources/ (macOS, via NSBundle), beside octosense.exe (NSIS, .), and in usr/lib/octosense/ (deb/AppImage, ../lib/octosense from usr/bin).
  • System apps and config: App Hub packs the system-app bundles into the binary at build time, so nothing from apps/ or system-apps.json is read at run time. A packaged build no longer looks for the checkout it was built in (paths::packaged()). As a result it has no source-built developer catalog; --apps with executable rows still works. Dev cargo run is unchanged.
  • Kernel: octos at the pinned revision, built via Package the desktop Octos kernel and update hosted Rinx #85's source_at/stage (the stage step checks --version against the pin). It ships as octos-kernel beside the executable, where Package the desktop Octos kernel and update hosted Rinx #85's kernel service finds it without OCTOS_APP_CORE_BIN. --no-kernel ships none, and the app then runs without an assistant.
  • Identity: product name OctoSense, identifier org.octosense.desktop (desktop/packaging/release.json), version taken from the desktop-v* tag. The icon is the OctoSense flower mark, rendered by desktop/packaging/make_icons.py (stdlib only). Android keeps dev.makepad.octosense.
  • No private paths: builds use --remap-path-prefix for home, CARGO_HOME and the checkout, and strip debug info. Crates also embed their manifest dirs as strings, which remapping cannot reach, so the workflow builds macOS under /private/tmp and puts Windows' CARGO_HOME on D:. tools/release-scan.py then scans the packages and their payloads (.app, .dmg via hdiutil, .deb, .AppImage, .zip, NSIS via 7-Zip) and fails on user dirs, non-runner homes, *.local hosts, private IPv4 addresses, the scanning account and host names, and RELEASE_SCAN_EXTRA.

Workflow: .github/workflows/release-desktop.yml

It runs on macos-14 (arm64), windows-2022 and ubuntu-22.04 (x86_64). Each job does: setup.py → setup.py --check --cargo + check-shell-graph.sh → package.py → scan → artifacts. A desktop-v* tag also attaches all packages, receipts and SHA256SUMS to a draft, --latest=false release. workflow_dispatch (with a dry_run input) and pull requests that touch the packaging run the same jobs but release nothing. No x86_64 macOS build is made, because the runner is arm64.

Signing secrets still needed, each step skipped while its secret is absent: APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORD, APPLE_SIGNING_IDENTITY, APPLE_API_KEY, APPLE_API_ISSUER, APPLE_API_KEY_P8, WINDOWS_CERTIFICATE, WINDOWS_CERTIFICATE_PASSWORD. RELEASE_SCAN_EXTRA is optional. The signing paths are unverified.

Verified locally (macOS arm64)

  • package.py built OctoSense.app (278 MB) and OctoSense_0.1.0_aarch64.dmg (131 MB) from a checkout outside any home directory. Kernel: octos 2.0.3-rc.13 at the then-pinned a6ea850.
  • I copied the .app outside the repository, renamed both the build tree and .sources out of reach, and ran it with MAKEPAD_HIDE_WINDOWS=1 and the remote bridge, OCTOS_APP_CORE_BIN unset. desktop/scripts/system_apps_remote.sh (with OCTOSENSE_BIN set to the packaged binary) passed its functional checks: desktop up, launcher lists all six system apps, Photos draws, Mail's host sign-in sheet opens, AI providers opens, bundles unpacked. Its last check failed only because it matches [ui-hang] frames by symbol name, and that build had symbols stripped. The release build now strips debug info only, so symbol names stay.
  • A second run through /d, /snap and /click showed the bar, dock and Liquid Glass frames, and App Hub listing News, Maps, Photos and Camera in its preview catalog. The log had no resource-load errors and said "octos: kernel service ready", meaning it found the packaged kernel. /gq quit the app.
  • Scan: the shell binary and staged resources were clean. The a6ea850 kernel was refused, because it embedded a developer's absolute paths from octos' project templates. octos#2583 removed them, and chore(octos): pin octos main 60cf96e6 (octos#2583) #88 has since moved the pin to 60cf96e, which this branch includes.
  • actionlint is clean. Tool tests pass (tools/, desktop/scripts/test_package.py), and so does rom/tests/test_no_local_paths.py.

A second local build on the current pins (octos 60cf96e) produced OctoSense.app (339 MB, of which the kernel is 117 MB) and a 140 MB .dmg. The scan of the .app, .dmg, staged resources and kernel came back clean. I ran it again outside the repository with the sources hidden: every functional check passed, and there were no resource errors. The script's [ui-hang] check flagged only these two things:

  • packaged resource and font loads on the UI thread at startup and first use. These are now in its known list.
  • one 314 ms shader compile, which has nothing to do with packaging.

CI dry run (pull_request trigger, run 36391231861): all green

Platform Packages Scan
macos-14 OctoSense_0.1.0_aarch64.dmg (147 MB), OctoSense_0.1.0_macos_aarch64.app.zip (147 MB) clean, 595 files
windows-2022 octosense_0.1.0_x64-setup.exe (108 MB) clean, 598 files
ubuntu-22.04 octosense_0.1.0_amd64.deb (157 MB), octosense_0.1.0_x86_64.AppImage (149 MB) clean, 637 files

Fixes the dry runs forced:

  • core.autocrlf false: Windows CRLF checkouts broke the runtime patch digest.
  • PYTHONUTF8=1: Windows Python read cargo's JSON as cp1252.
  • C:\Users\runneradmin is treated as a CI path, like /home/runner. The prebuilt NSIS plugin cargo-packager bundles carries it.
  • .local hosts must be one label, and XDG .local/… paths are excluded. Rust packs string literals back to back, so otherwise octos' strings read as host names.

Windows and Linux packages are built and scanned in CI only; nobody has run them on a machine yet, so they are unverified. No desktop-v tag was created.

🤖 Generated with Claude Code

@ymote

ymote commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Note from #98 (Talk to Octos): #98 no longer uses a downstream octos overlay. octos serve --host-managed is upstream in octos-org/octos#2591. Once that merges and the workspace octos pin moves to the merged commit, this PR's desktop packaging needs nothing beyond that pin: building the pinned octos is enough. The #98 head (d5e20d9) merges with this branch without textual conflicts. The files both change are Cargo.toml/Cargo.lock, crates/kernel/src/{launch,lib}.rs, crates/kernel/tests/core.rs, crates/kernel/README.md, crates/ai-host/src/lib.rs and the desktop READMEs.

🤖 Generated with Claude Code

ymote added a commit that referenced this pull request Sep 28, 2026
… process on macOS and Windows

ADR 0004 §2 and §10 (#110). A linked native app the person has not
switched is now hosted as its manifest entry declares for this target
(native_apps.rs, `NativeApp::on_this_target`), replacing the hard-coded
"robrix | finance | terminal are modules" rule (robrix and finance are not
linked by any build):

- Terminal: its own process on macOS and Windows; on Linux only with a
  Vulkan build (`MAKEPAD=vulkan`, new `makepad_vulkan` cfg in the shell's
  build.rs) in a Wayland session; in-process on phones. A crash in it no
  longer takes the shell down.
- A declared process falls back to in-process where it has no process
  form (`apps::process_form`: its launcher row resolves neither to a
  checkout to `cargo run` from nor to a sibling binary).
- App Hub, Rinx and AppCard are modules everywhere; Reference and Sheets
  keep their process default on the desktop.
- `terminal: Module|Process` (and any `<id>: ...`) in wm/apps.splash and
  `--module <id>` still win.

The process is found the way every catalog app is (clients.rs): out of a
checkout, `cargo run --release --manifest-path .sources/makepad/Cargo.toml
-p makepad-terminal --bin terminal --target-dir <home>/build/makepad`;
otherwise the `terminal` binary beside `octosense`. Release packages do
not ship that binary yet: that depends on OctoSense #94; until then a
packaged build falls back to the in-process Terminal.

The standalone terminal binary publishes `run` on the AI services bus.
The bus now withholds it (ai_bus::WITHHELD_TOOLS, keyed by the app id the
shell launched the client as): stripped from the registration and replay,
and a call to it is dropped, so the assistant gets read_screen and
read_scrollback only in either hosting.

Behaviour changes: Terminal opens as a process on macOS/Windows; Rinx
(default) and AppCard (opt-in) now open in-process without `--module`
(they have no process form, so before they were not launchable on the
desktop without the flag).

Verified on macOS: cargo build --locked -p octosense;
tools/check-shell-graph.sh -p octosense and -p octosense-home;
cargo test --locked -p octosense-shell --features app-terminal: 348
passed; from phone/: cargo check --locked -p octosense-home --features
mobile-apps, cargo test --locked --features mobile-apps -p
octosense-shell: 358 passed; native_apps.py --check; tools unittests.
Hidden desktop (MAKEPAD_HIDE_WINDOWS, MAKEPAD_REMOTE, scratch
OCTOSENSE_HOME, MAKEPAD_WM_TEST_APP=terminal): "launched terminal as
client 1" (a process, not "in-process"), cargo built the `terminal` bin
into the scratch home, first frame drawn in the tile, zsh running under
it, typed text reached it; /quit ended both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymote added a commit that referenced this pull request Sep 28, 2026
… process on macOS and Windows

ADR 0004 §2 and §10 (#110). A linked native app the person has not
switched is now hosted as its manifest entry declares for this target
(native_apps.rs, `NativeApp::on_this_target`), replacing the hard-coded
"robrix | finance | terminal are modules" rule (robrix and finance are not
linked by any build):

- Terminal: its own process on macOS and Windows; on Linux only with a
  Vulkan build (`MAKEPAD=vulkan`, new `makepad_vulkan` cfg in the shell's
  build.rs) in a Wayland session; in-process on phones. A crash in it no
  longer takes the shell down.
- A declared process falls back to in-process where it has no process
  form (`apps::process_form`: its launcher row resolves neither to a
  checkout to `cargo run` from nor to a sibling binary).
- App Hub, Rinx and AppCard are modules everywhere; Reference and Sheets
  keep their process default on the desktop.
- `terminal: Module|Process` (and any `<id>: ...`) in wm/apps.splash and
  `--module <id>` still win.

The process is found the way every catalog app is (clients.rs): out of a
checkout, `cargo run --release --manifest-path .sources/makepad/Cargo.toml
-p makepad-terminal --bin terminal --target-dir <home>/build/makepad`;
otherwise the `terminal` binary beside `octosense`. Release packages do
not ship that binary yet: that depends on OctoSense #94; until then a
packaged build falls back to the in-process Terminal.

The standalone terminal binary publishes `run` on the AI services bus.
The bus now withholds it (ai_bus::WITHHELD_TOOLS, keyed by the app id the
shell launched the client as): stripped from the registration and replay,
and a call to it is dropped, so the assistant gets read_screen and
read_scrollback only in either hosting.

Behaviour changes: Terminal opens as a process on macOS/Windows; Rinx
(default) and AppCard (opt-in) now open in-process without `--module`
(they have no process form, so before they were not launchable on the
desktop without the flag).

Verified on macOS: cargo build --locked -p octosense;
tools/check-shell-graph.sh -p octosense and -p octosense-home;
cargo test --locked -p octosense-shell --features app-terminal: 348
passed; from phone/: cargo check --locked -p octosense-home --features
mobile-apps, cargo test --locked --features mobile-apps -p
octosense-shell: 358 passed; native_apps.py --check; tools unittests.
Hidden desktop (MAKEPAD_HIDE_WINDOWS, MAKEPAD_REMOTE, scratch
OCTOSENSE_HOME, MAKEPAD_WM_TEST_APP=terminal): "launched terminal as
client 1" (a process, not "in-process"), cargo built the `terminal` bin
into the scratch home, first frame drawn in the tile, zsh running under
it, typed text reached it; /quit ended both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymote and others added 10 commits October 1, 2026 09:00
The desktop kernel service finds a packaged `octos-kernel[.exe]` beside
the shell executable when `OCTOS_APP_CORE_BIN` is unset
(crates/kernel/src/launch.rs), and tools/build-desktop.py builds the
locked kernel and stages it there.

Rebased onto main: the old hosted-Rinx revision is dropped (main pins
Rinx by tag v1.1.0 through native-apps.json) and so is the Cargo.toml
patch redirect, which main already carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…AppImage

desktop/scripts/package.py builds octosense in Makepad's packaged-resource
mode (MAKEPAD_PACKAGE_DIR, apple_bundle on macOS), stages the resources/
of every linked git or path crate beside the binary, builds the locked
octos kernel with tools/build-desktop.py's checkout and version check and
ships it as octos-kernel beside the executable, then runs cargo-packager
from desktop/packaging/release.json (identifier org.octosense.desktop,
product OctoSense, version from a desktop-v tag). Paths are remapped
(home, CARGO_HOME, checkout) and debug info stripped. A packaged build no
longer looks for the checkout it was built in.

tools/release-scan.py refuses artifacts (inside .app, .dmg, .deb,
.AppImage, .zip, NSIS) that carry user directories, homes other than
/home/runner, .local hosts, private IPv4 addresses, the scanning machine's
names or RELEASE_SCAN_EXTRA patterns.

.github/workflows/release-desktop.yml: desktop-v* tags build, scan and
attach the packages and SHA256SUMS to a draft, not-latest release;
workflow_dispatch and packaging pull requests dry-run. Apple codesign,
notarytool and stapler, and Windows signtool, run only when their secrets
exist.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…aths; packaged resource loads are a known startup hang

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…runner

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… them

Rust packs string literals back to back, so octos' ".local" + "/share" +
"kde-open" reads as one run of text; the path check no longer needs a word
boundary after the directory name, and the one-off utf-8.local excuse goes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Main's ci-local drift check (tools/test_ci_local.py, in the desktop job)
requires every workflow to be one ci-local runs. The release workflow
packages and signs on macOS, Windows and Linux runners (a matrix,
secrets, artifacts), which this machine cannot stand in for. List it in
`GITHUB_ONLY`: the drift check leaves it alone, and ci-local-merge
refuses a PR that triggers it, so such a PR waits for GitHub's run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote

ymote commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Replaced by two fresh PRs on current main:

🤖 Generated with Claude Code

@ymote ymote closed this Oct 1, 2026
ymote added a commit that referenced this pull request Oct 2, 2026
…t of the build

Port of #94 onto the packaged-kernel lookup of the previous commit, with
its review findings fixed.

desktop/scripts/package.py builds the desktop in Makepad's packaged-resource
mode with remapped paths, stages every linked crate's resources, builds the
pinned octos kernel with tools/kernel-artifact.py --host and stages it with
its receipt (the kernel beside the executable, the receipt with the
resources, where crates/kernel looks), and packages it with cargo-packager:
macOS .app/.dmg, Windows NSIS, Linux .deb/.AppImage. It needs no secret and
always builds unsigned: it strips cargo-packager's signing variables from
the build environment. tools/release-scan.py refuses private paths and names
inside the packages (new: --dmg-bytes-only, for the Linux release job).

A packaged build never looks for an OctoSense checkout: not where it was
built, not its working directory, not its executable's ancestors
(paths::packaged()), so starting it inside someone else's checkout cannot
make it build and run that code. Its theme sheets come from the binary.

.github/workflows/release-desktop.yml:
- plan resolves what to build. A tag push or a manual run naming a tag
  checks out that tag (not the branch the run started from), and every job
  verifies HEAD is the planned commit; the release job verifies it is the
  tag's commit before attaching.
- package (macOS, Windows, Linux) builds and scans unsigned packages with no
  secrets and uploads them as artifacts.
- sign-macos and sign-windows run in the protected `release` environment,
  only for a tag push or a manual run from main. They download the packages
  and run codesign/notarytool/signtool only; nothing checks out or builds
  code there. The kernel's receipt is updated to its signed bytes before
  the app is sealed. The Windows certificate is used from a file, never
  imported; the keychain, the .p12 and AuthKey.p8 are deleted in always()
  steps. Without the secrets they pass the packages through unsigned.
- Pull requests get plan and package only: no secrets, no signing.
- Every action is pinned to a full commit SHA, and Rust to 1.97.1.

tools/ci_local.py lists release-desktop.yml in NOT_LOCAL with its reason,
so --check-drift skips it (and fails if the entry goes stale); the desktop
job runs the packaging tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ymote added a commit that referenced this pull request Oct 2, 2026
…t of the build

Port of #94 onto the packaged-kernel lookup of the previous commit, with
its review findings fixed.

desktop/scripts/package.py builds the desktop in Makepad's packaged-resource
mode with remapped paths, stages every linked crate's resources, builds the
pinned octos kernel with tools/kernel-artifact.py --host and stages it with
its receipt (the kernel beside the executable, the receipt with the
resources, where crates/kernel looks), and packages it with cargo-packager:
macOS .app/.dmg, Windows NSIS, Linux .deb/.AppImage. It needs no secret and
always builds unsigned: it strips cargo-packager's signing variables from
the build environment. tools/release-scan.py refuses private paths and names
inside the packages (new: --dmg-bytes-only, for the Linux release job).

A packaged build never looks for an OctoSense checkout: not where it was
built, not its working directory, not its executable's ancestors
(paths::packaged()), so starting it inside someone else's checkout cannot
make it build and run that code. Its theme sheets come from the binary.

.github/workflows/release-desktop.yml:
- plan resolves what to build. A tag push or a manual run naming a tag
  checks out that tag (not the branch the run started from), and every job
  verifies HEAD is the planned commit; the release job verifies it is the
  tag's commit before attaching.
- package (macOS, Windows, Linux) builds and scans unsigned packages with no
  secrets and uploads them as artifacts.
- sign-macos and sign-windows run in the protected `release` environment,
  only for a tag push or a manual run from main. They download the packages
  and run codesign/notarytool/signtool only; nothing checks out or builds
  code there. The kernel's receipt is updated to its signed bytes before
  the app is sealed. The Windows certificate is used from a file, never
  imported; the keychain, the .p12 and AuthKey.p8 are deleted in always()
  steps. Without the secrets they pass the packages through unsigned.
- Pull requests get plan and package only: no secrets, no signing.
- Every action is pinned to a full commit SHA, and Rust to 1.97.1.

tools/ci_local.py lists release-desktop.yml in NOT_LOCAL with its reason,
so --check-drift skips it (and fails if the entry goes stale); the desktop
job runs the packaging tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tyreseluo pushed a commit to tyreseluo/OctoSense that referenced this pull request Oct 4, 2026
…s, CEF profile under MAKEPAD_HOME)

Moves the runtime from makepad 39a9de88 to makepad main c155f61d,
through Octoscript-Makepad 2cc5ef37 (OctoSense-org#71). New in makepad:
- OctoSense-org#94 Files, Task and Browser: an empty library beside each binary
- OctoSense-org#95 Calculator, Clock, Notes, Reminders, Weather: each module opens its
  own agent's link and answers its tools there
- OctoSense-org#96 hosted Notes and Reminders start empty
- OctoSense-org#97 Files' chat panel only reads
- OctoSense-org#98 CEF keeps its stable profile under MAKEPAD_HOME when that is set

Root Cargo.toml (every makepad revision, octoscript-makepad and
octoscript-node), the Sheets and Terminal revisions in native-apps.json,
both native-runtime.lock.json files, and runtime-patches.lock.json: base
c155f61d, the five patches reapply unchanged (none touches a changed
file), new tree 3eadf628. Cargo.lock does not change. The phone docs
that name the pinned hashes move with it; rom/docs/home-build.md gets
its own follow-up, as with OctoSense-org#289.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tyreseluo pushed a commit to tyreseluo/OctoSense that referenced this pull request Oct 6, 2026
- architecture.md item 11 said the in-process Terminal still offers
  `run` to the AI pane. It doesn't: the shell announces the module's
  read-only manifest, and the pane and `AiBus::shell_call` call only
  declared tools. The real gap is that only the system agent's
  `terminal.run` checks `sandbox::launch_sandboxed`. A process
  Terminal offers the AI pane its own `run` either way, and developer
  mode grants `terminal.run` to every covered app agent. On Windows
  there is no sandbox.
- architecture.md item 8 said `terminal.run` is never offered on
  Windows. That holds for the system agent only.
- README: OpenGL does not mean a CPU copy. Makepad exports DMA_BUFs
  through EGL and copies only when that fails. The shell runs the
  Terminal as a process on Linux only in a Vulkan build in a Wayland
  session. Task, with no module, is a process either way.
- desktop/README app-terminal row:
  - the AI pane types only into a process Terminal;
  - outside developer mode it waits for a host sheet;
  - the limit is 4 KiB;
  - the shell uses `cargo build`, not `cargo run`;
  - phone builds don't link the Terminal;
  - OctoSense-org#94 closed unmerged.

English and Chinese change together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant