Skip to content

Desktop: find the packaged octos kernel and refuse one of another revision - #256

Merged
ymote merged 1 commit into
mainfrom
feat/desktop-kernel-finder
Oct 2, 2026
Merged

ymote merged 1 commit into
mainfrom
feat/desktop-kernel-finder

Conversation

@ymote

@ymote ymote commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

The desktop's kernel service needed OCTOS_APP_CORE_BIN. It now finds a packaged octos-kernel that travels with the shell, and refuses one that is not the octos revision this build pins. Replaces the kernel part of #85.

What changes

  • Finder (crates/kernel/src/launch.rs, desktop_program). The kernel is chosen in this order: Options::program, then OCTOS_APP_CORE_BIN, then octos-kernel[.exe] beside the canonicalized shell executable (in a macOS .app, Contents/MacOS or Contents/Resources). It never looks in the working directory or on PATH. An override still wins and is not checked, and a broken override is an error rather than a fallback.
  • Revision check (new, from review). A packaged kernel runs only when its receipt octos-kernel.json names the octos revision this build pins and its SHA-256 matches the binary.
    • The receipt sits beside the kernel, in the .app's Contents/Resources, or in a Linux package's usr/lib/octosense.
    • crates/kernel/build.rs reads the pinned revision from Cargo.lock (the same octos-cli revision tools/kernel-artifact.py reads).
    • A stale target/release/octos-kernel left from an earlier pin, a kernel without a receipt, or a swapped binary is refused, and the person sees why. For example: refusing the packaged kernel …: it is octos 60cf96e6c871 but this build pins ae230ce04d57 (set OCTOSENSE_KERNEL_ANY_REVISION=1 to run it anyway while developing). Rebuild it with python3 tools/kernel-artifact.py --host --stage <dir> or name a kernel with OCTOS_APP_CORE_BIN.
    • OCTOSENSE_KERNEL_ANY_REVISION=1 is the development override. It accepts another revision, but a receipt and a matching hash are still required.
  • Where the hash is checked. Resolving reads only the small receipt, because Core::launch() also answers status queries on the UI thread at startup. In the first local run, hashing the 117 MB kernel there caused a 669 ms [ui-hang]. The SHA-256 is now checked in launch::prepare, on the kernel's runtime before each start, and the result is cached by size and mtime. A mismatch fails closed, like the tool-policy refusal does.
  • Building it (tools/kernel-artifact.py, no new script). --host --stage <dir> builds the pinned revision for this machine and stages it as octos-kernel plus the receipt (source, revision, version, sha256). It refuses a binary whose --version does not name the pinned revision, and leaves any earlier kernel in place. --kernel <path> --stage <dir> stages a prebuilt one. The host build now passes --target-dir instead of an env wrapper, so the same plan runs on Windows.
  • Docs. desktop/README.md "Build and run" (+ zh-CN) now reads python3 tools/kernel-artifact.py --host --stage target/release then cargo run --release -p octosense. Also updated: the root README (+ zh-CN), the kernel and ai-host READMEs, docs/ai-services.md and docs/architecture.md (+ zh-CN; the "Package the desktop Octos kernel and update hosted Rinx #85 in progress" notes are gone).

Compared with #85

  • tools/build-desktop.py is not ported; kernel-artifact.py --host --stage covers it.
  • The runtime check of the receipt revision and SHA-256 is new. Package the desktop Octos kernel and update hosted Rinx #85 checked --version only when staging.
  • The Rinx pin bump and the [patch."…OctoSense.git"] change are dropped. Main pins Rinx v1.1.0 and takes the app contract from crates.io. The only Cargo.lock change is sha2 (already in the graph) added to octosense-kernel.
  • examples/packaged_probe.rs is not committed. I ran it locally (below).

Tested (macOS arm64)

  • cargo test --locked -p octosense-kernel: 36 unit, 13 core and 7 real-kernel tests pass. The real-kernel tests used the pinned ae230ce kernel via OCTOS_CORE_TEST_KERNEL. cargo clippy --locked -p octosense-kernel --all-targets -- -D warnings passes for the host, aarch64-linux-android, x86_64-pc-windows-msvc and x86_64-unknown-linux-gnu.
  • New unit tests cover: override precedence, a broken override never falling back, finding the kernel again after the directory moves, the .app (MacOS and Resources) and Linux usr/bin + usr/lib/octosense layouts, a non-bundle Contents/MacOS, a stale revision, a missing or malformed receipt, a hash mismatch caught by prepare (also under the override), a non-executable kernel, and PINNED_REVISION matching Cargo.lock.
  • python3 -m unittest discover -s tools -p 'test_*.py' passes (82 tests on this branch). The new stage tests cover the version check, the receipt, nothing being replaced on a wrong revision, and the CLI.
  • End to end with a real kernel: kernel-artifact.py --kernel <ae230ce octos> --stage next to Package the desktop Octos kernel and update hosted Rinx #85's packaged probe (run locally, not committed), OCTOS_APP_CORE_BIN unset. Result: PASS: sibling runtime, shared kernel, provider profile and restart; no LLM request. With the receipt's revision changed, the probe got the refusal above; OCTOSENSE_KERNEL_ANY_REVISION=1 ran it; with no receipt it was refused.
  • These pass: cargo check --locked -p octosense-shell -p octosense, -p octosense --features mobile-apps, tools/check-shell-graph.sh -p octosense, tools/setup.py --check --cargo and tools/test_ci_local.py.
  • The packaged-app run (the .app finding its kernel in Contents/MacOS with the receipt in Resources) is in the stacked packaging PR.

Not run here: Windows and Linux at run time (compiled and clippy-checked only).

🤖 Generated with Claude Code

…ision

The desktop's kernel service needed OCTOS_APP_CORE_BIN. It now also finds
a packaged `octos-kernel[.exe]` beside the shell executable (in a macOS .app,
Contents/MacOS or Contents/Resources), never in the working directory or on
PATH. Options::program and OCTOS_APP_CORE_BIN still win, unchecked, and a
broken override is an error rather than a fallback.

The packaged kernel runs only when its receipt `octos-kernel.json` names the
octos revision this build pins (crates/kernel/build.rs reads it from
Cargo.lock) and the binary's SHA-256 matches. A stale
target/release/octos-kernel from an earlier pin, a missing receipt or a
swapped binary is refused, and the reason reaches the person.
OCTOSENSE_KERNEL_ANY_REVISION=1 accepts another revision while developing;
the receipt and hash are still required. Resolving reads only the receipt
(it also answers status queries on the UI thread); the hash is checked in
launch::prepare on the kernel's runtime before each start, cached by size
and modification time.

tools/kernel-artifact.py --host --stage <dir> builds the pinned kernel and
stages it with that receipt, refusing a binary whose --version is not the
pinned revision (--kernel stages a prebuilt one). The host build passes
--target-dir instead of an `env` wrapper, so it runs on Windows too.

Replaces the kernel part of #85. Its Rinx pin and [patch] changes are
dropped: main pins Rinx v1.1.0 and the app contract from crates.io.

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

ymote commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Local CI passed on 5f2db0c (tools/ci-local.sh --only all, 12m53s, Darwin arm64).

GitHub would run for this PR: desktop.yml, phone.yml, apps.yml, rom.yml. Merged on this local pass (macOS runner queue); GitHub CI runs on the merge commit on main.

Job Step Result Time
ci-local / drift The local mapping fits the workflows PASS -
desktop.yml / desktop Prepare the pinned framework sources PASS 1s
desktop.yml / desktop Compile the desktop with the shared runtime PASS 1m15s
desktop.yml / desktop One copy of every shell source PASS -
desktop.yml / desktop Desktop tools and scripts PASS 9s
desktop.yml / desktop One Makepad, App Hub, octos and Rinx in the locked graph PASS 3s
desktop.yml / desktop The native apps' generated places match native-apps.json PASS 0s
phone.yml / home Prepare pinned sources and the reviewed runtime patch PASS 0s
phone.yml / home Compile Home and its bundled modules PASS 1m43s
phone.yml / home Verify the single runtime graph PASS 2s
phone.yml / home The native apps' generated places match native-apps.json PASS 0s
phone.yml / home The pinned octos revision PASS -
phone.yml / home Build octos (unless cached) PASS -
phone.yml / home Build Home, App Hub admission and runtime policy tests PASS 41s
phone.yml / home Test Home, App Hub admission and runtime policy PASS 2m54s
phone.yml / home Two-lane scenario (real kernel, scripted model) PASS 49s
apps.yml / services python3 tools/setup.py PASS 1s
apps.yml / services Kernel service PASS 20s
apps.yml / services App peers PASS 32s
apps.yml / services AI providers config PASS 6s
apps.yml / services L0 in-card chat (sys.chat, host side) PASS 13s
apps.yml / services System toolbox (workflow templates) PASS 2m08s
apps.yml / kernel-security python3 tools/setup.py PASS 0s
apps.yml / kernel-security The pinned octos revision PASS 0s
apps.yml / kernel-security Build octos (unless cached) PASS -
apps.yml / kernel-security Real-kernel tests PASS 27s
apps.yml / apps python3 tools/setup.py PASS 0s
apps.yml / apps Host services (Mail, AI providers, News) PASS 17s
apps.yml / apps Shell AI services (crates/ai-host) PASS 10s
apps.yml / apps AppCard runtime setup safeguards PASS 0s
apps.yml / apps AppCard clippy (own crates; shared runtime compiles) PASS 1s
apps.yml / apps AppCard transport and store PASS 5s
apps.yml / apps One Makepad, App Hub, octos and Rinx in the locked graph PASS 2s
rom.yml / product python3 -m unittest discover -s tests -v PASS 38s
rom.yml / product Check generated Agent Binder client PASS 0s
rom.yml / product bash -n scripts/stage-forks.sh scripts/publish-release.sh scripts/apply-to-tree.sh scripts/build-rom.sh PASS -
rom.yml / web-installer npm ci --ignore-scripts --no-audit --no-fund PASS 4s
rom.yml / web-installer npm test PASS 1s
rom.yml / web-installer npx playwright install --with-deps chromium PASS 3s
rom.yml / web-installer npm run test:browser PASS 4s
rom.yml / web-installer python3 -m unittest discover -s tests -p test_installer_manifest.py -v PASS 0s
rom.yml / web-installer bash -n scripts/release.sh PASS -

Notes:

  • GitHub runs Python 3.12; this run used Python 3.9.6
  • apps.yml:services runs on ubuntu-latest in GitHub; here on macOS, so #[cfg(target_os = "linux")] code in it is not exercised (--linux-host runs it on Linux)
  • apps.yml:kernel-security runs on ubuntu-latest in GitHub; here on macOS, so #[cfg(target_os = "linux")] code in it is not exercised (--linux-host runs it on Linux)

@ymote
ymote merged commit 91063e3 into main Oct 2, 2026
6 of 7 checks passed
@ymote

ymote commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

The Linux-host steps also passed on this same head, 5f2db0c. Run 1 started 2026-10-02T12:58:12 (tools/ci-local.sh --only all --linux-host): 36 steps passed. That includes apps services, kernel-security and linux-host / sandbox (Landlock, seccomp) on the Linux build host.

Its only skips were the 8 rom.yml steps, because the Linux host has no JDK, Android SDK or node. Those ran and passed in run 2, the Mac-only --only all run with the rom toolchain set. Its summary is here: #256 (comment)

ymote added a commit that referenced this pull request Oct 2, 2026
#275 rewrote the intro, the kernel and session text and the worked
example, and #256 the desktop kernel row; those stay. On top of them
this corrects what still disagrees with main's code: which apps have an
agent and their tools, the notice card, toasts and dismissal, the glance
panel's L0 taps, where questions show, agents.ask, the approval router
and every approval going to it, terminal.run, the toolbox, the process
launch, the Linux sandbox and the follow-ups that are now fixed. English
and Chinese now say the same; the Chinese page had fallen behind.

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