Independent review of the PR head found the control boundary only held inside one process and several claims the code did not back. Each item below was reproduced, fixed, covered by an invariant test proven red without the fix, and re-verified live on a real Xvnc/Xfce screen. - Lease authority on disk. `lease.json` under an fcntl lock in the profile's bot-desktop dir; every read goes to the file. `hermes serve` (viewer bridge), the messaging gateway, a CLI turn and isolated workers now agree. Live: a takeover in process A made `computer_use capture` in process B return human_has_control; release in C made B work again. - Takeover fences admitted actions. `handle_computer_use` re-checks the lease under the dispatch lock and discards a result produced after the lease epoch changed, so an action admitted before a takeover cannot picture what the human typed during approval / backend start-up waits. - Sudo reply pinned to its origin. `SudoRequest.origin` records the (connection, profile) the card came from; SudoDialog answers through `requestGatewayForAgent` on that socket, never the foreground gateway. A password typed for host A can no longer reach host B. `sudo.expire` and `display.install.sudo.expire` now tear the card down (the Desktop never handled sudo.expire). - Dock Browser IS the bot's browser. `tools/bot_desktop/browser.py` resolves one identity — the Chromium agent-browser drives + a persistent per-profile user-data-dir (`bot-desktop/browser-profile`) — and both sides use it: the agent env gets AGENT_BROWSER_EXECUTABLE_PATH / AGENT_BROWSER_PROFILE, the dock launcher gets the same exe + --user-data-dir. Live: the bot wrote localStorage on http://127.0.0.1:8765 through agent-browser; a dock click and a typed URL on the screen showed BOT-WROTE-THIS in Chrome for Testing. - Safe display reuse. Allocation under a host-wide lock; a recorded number is reused only when no live server holds it; the launcher never unlinks a lock whose pid is alive. Live: A stopped, B took :20, A restarted on :21, B kept running. - Install worker keeps the caller's profile scope (copy_context carries the HERMES_HOME override and the transport); the done event carries the requested profile's status. - Honest scope: `bot_desktop.auto_start` defaults to false (opt-in; Start lives in the Screen pane); request_handoff no longer claims a Telegram/Discord message was sent — the model relays the ask in its reply; docs match.
Website
This website is built using Docusaurus, a modern static website generator.
Installation
yarn
Local Development
yarn start
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
Build
yarn build
This command generates static content into the build directory and can be served using any static contents hosting service.
Deployment
Using SSH:
USE_SSH=true yarn deploy
Not using SSH:
GIT_USER=<Your GitHub username> yarn deploy
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the gh-pages branch.
Diagram Linting
CI runs ascii-guard to lint docs for ASCII box diagrams. Use Mermaid (````mermaid`) or plain lists/tables instead of ASCII boxes to avoid CI failures.