Skip to content

Review only: skeptical review of fork UI and architecture (do not merge) - #18

Draft
matthewhand wants to merge 562 commits into
mainfrom
cursor/skeptical-review-ui-architecture-7027
Draft

Review only: skeptical review of fork UI and architecture (do not merge)#18
matthewhand wants to merge 562 commits into
mainfrom
cursor/skeptical-review-ui-architecture-7027

Conversation

@matthewhand

Copy link
Copy Markdown
Owner

Review only — do not merge

This PR adds a single document, docs/reviews/2026-08-26-skeptical-review-ui-architecture.md, containing a skeptical review of this fork's UI and architecture. It changes no code, performs no rebase onto upstream, and does not touch any draft PR's conflicts. It exists so the findings are readable in one place; close it without merging once read, or merge it if you want the document kept in-repo.

Scope

Headline findings

  1. Branch topology blocks everything else. Fork main carries no original work and is 464 commits behind upstream — and older than four of its own feature branches' bases (04e2fe7). PRs Add OpenAI-compatible TTS provider #14/Add first-class custom HTTP/SSE MCP servers #15/Add opt-in LAN auth with Bearer and EventSource token #16 therefore show ~79k-line diffs that are 98.7% upstream drift and are unreviewable/unmergeable as opened. Advancing main to the branches' common base collapses them to their real ~1k-line diffs.
  2. LAN auth (Add opt-in LAN auth with Bearer and EventSource token #16) is careful code on a thin threat model: a single static bearer token over cleartext HTTP is the entire perimeter of an API whose purpose is running shell-executing agents; the token lives in localStorage in an app that renders agent output; CORS_ORIGIN=* is supported and defaulted by Install OpenMausBot as a Windows NSSM service #17's installer.
  3. NSSM service (Install OpenMausBot as a Windows NSSM service #17): unverified download of 2014-era nssm.zip run as admin, service defaults to LocalSystem + 0.0.0.0 + CORS *, token echoed to console.
  4. Custom MCP servers (Add first-class custom HTTP/SSE MCP servers #15) is the strongest branch, but blanket-allowlists every tool of a user-entered server, bypassing the approval broker.
  5. Predicted integration bug: Do not open loopback computer URLs from a LAN tab #11's new raw fetch() screenshot polling carries no Bearer token, so merging Do not open loopback computer URLs from a LAN tab #11 + Add opt-in LAN auth with Bearer and EventSource token #16 breaks "Watch screen" over LAN — the exact scenario Do not open loopback computer URLs from a LAN tab #11 targets. Root cause is the inherited untyped api(): Promise<any> boundary with scattered raw fetches.
  6. Environment trap: under Node 22 the suite fails with 85 misleading errors; engines >=24 is only a pnpm warning. A runtime preflight is recommended.

Full detail, evidence (file:line, measured diffs, test runs), per-branch reviews, and prioritized recommendations are in the document.

Open in Web Open in Cursor 

milind-soni and others added 30 commits August 24, 2026 23:37
* feat: add secure credential request cards

* fix: make credential card resume recoverable

* fix: surface room credential resume failures

* fix: drain credential resumes after terminal failures

* fix: isolate room credential requests and decline retries
* feat: add section-scoped shared context

* fix: guard unsaved section context
* feat: preview image attachments in app

* fix: keep attachment preview keyboard-safe
* feat: add chat find and flat replies

* fix: resolve reply quotes across branch history
milind-soni#425 made sidebar mascots mount paused — and exposed that the parked
loop never draws: the SVG layers hold no expression until the first
draw() positions them, so an idle bot's avatar rendered blank. The
paused branch now paints the still face once, re-painting only when
what it shows changes (state, pinned expression, gradient), then parks
on the same 4Hz wake-poll. Animation stays opt-in; the resting pose is
simply visible again.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Add portable BotMRR package installs

* Keep package link tests out of Vitest discovery

* Add universal BotMRR Markdown imports

* Document portable team playbooks
…i#346)

* fix(linux): fail closed on unsafe local control startup

* fix(desktop): keep optional connected apps off startup path

* fix(linux): repair inherited DEB upgrade permissions

* docs(linux): document the local-control safety hold

* fix(ci): configure dependencies in DEB upgrade smoke

* fix(linux): configure DEB Chromium sandbox

* fix(linux): restore safe Xorg local control

* fix(desktop): close review security and refresh races

* fix(linux): isolate local control safety opt-in

* docs(linux): explain private CUA cursor behavior

* fix(linux): clean CUA runtime on termination signals

* fix(linux): reap stale AppImage CUA stages

* docs(linux): clarify release CUA coverage

* test(linux): preserve packaged smoke diagnostics

* ci(linux): normalize runner package parent

* fix(linux): close final Ubuntu review gaps

* fix(ci): fail closed before Ubuntu package install

* fix(composio): enforce broker URL parity
…lind-soni#447)

* Let Antigravity models control computers (mount the computer MCP)

agy has no per-turn MCP flag and provably no project-level MCP config
(1.1.19: embedded docs list only the global
~/.gemini/config/mcp_config.json and per-plugin files; agy mcp list
ignores .gemini/{settings,mcp_config}.json in the cwd). So each turn
upserts one key — openmausbot-computer — into the global file right
before the spawn, preserving every other byte of the user's config and
tolerating malformed JSON, and removes that key on the next
computer-less turn so tools and box/control tokens cannot leak into
later turns or the user's own agy sessions.

Cloud boxes mount OpenMausBot's REST-to-MCP computer proxy (resolved
via SPAWNED_PROXIES — never relative to the module, the 0.1.24
lesson); Local VM and VPS connections pass through as the stdio Cua
command they already are.

computerMcp is advertised only by full-auto instances: print mode has
no interactive approval channel, and outside
--dangerously-skip-permissions agy auto-denies tools that would
prompt, so a non-fullAuto mount could never fire. localComputerMcp
stays unset — the host desktop requires per-action human approval,
which print mode cannot deliver in any mode.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: isolate Antigravity computer mounts

* fix: reap settled Antigravity children

* fix: keep MCP lease until child exit

* fix: preserve Antigravity MCP ownership

* fix: clear failed Antigravity turns

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…k actions (milind-soni#441)

* feat(electron): right-click context menu with clipboard and spellcheck actions

Adds a context-menu handler wiring Undo/Redo/Cut/Copy/Paste/
Paste-and-Match-Style/Select All plus spellcheck suggestions
and copy-link, so text fields behave like native macOS apps.

* refactor(electron): skip context menu when nothing is actionable; popup targets the source frame

---------

Co-authored-by: Milind Soni <46266943+milind-soni@users.noreply.github.com>
…milind-soni#442)

* feat(ui): composer attach button and per-bot permission mode selector

Adds a paperclip button that opens a file picker feeding the shared
attachment pipeline, and an Approve-for-me / Ask-for-approval pill that
toggles autoApprove per bot without opening settings. The composer is
restructured into two rows — text on top, controls below — matching
common chat-app layouts.

* feat(ui): remove the Always allow button from approval cards

The per-bot permission mode selector in the composer (Ask for approval /
Approve for me) is the single mechanism for reducing approval prompts;
the per-program Always-allow grant duplicated it with a worse model.
Allow-once and Deny remain.

* Paint the resting face when a mascot mounts paused (milind-soni#444)

milind-soni#425 made sidebar mascots mount paused — and exposed that the parked
loop never draws: the SVG layers hold no expression until the first
draw() positions them, so an idle bot's avatar rendered blank. The
paused branch now paints the still face once, re-painting only when
what it shows changes (state, pinned expression, gradient), then parks
on the same 4Hz wake-poll. Animation stays opt-in; the resting pose is
simply visible again.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(composio): preload connected account state (milind-soni#445)

* chore(release): bump version to 0.1.33 (milind-soni#446)

* Add portable BotMRR Markdown playbooks (milind-soni#426)

* Add portable BotMRR package installs

* Keep package link tests out of Vitest discovery

* Add universal BotMRR Markdown imports

* Document portable team playbooks

* fix(composio): accept empty authorization bodies (milind-soni#451)

* ci: stop retaining disposable Linux packages (milind-soni#452)

* fix(linux): harden Ubuntu upgrades and Xorg local control (milind-soni#346)

* fix(linux): fail closed on unsafe local control startup

* fix(desktop): keep optional connected apps off startup path

* fix(linux): repair inherited DEB upgrade permissions

* docs(linux): document the local-control safety hold

* fix(ci): configure dependencies in DEB upgrade smoke

* fix(linux): configure DEB Chromium sandbox

* fix(linux): restore safe Xorg local control

* fix(desktop): close review security and refresh races

* fix(linux): isolate local control safety opt-in

* docs(linux): explain private CUA cursor behavior

* fix(linux): clean CUA runtime on termination signals

* fix(linux): reap stale AppImage CUA stages

* docs(linux): clarify release CUA coverage

* test(linux): preserve packaged smoke diagnostics

* ci(linux): normalize runner package parent

* fix(linux): close final Ubuntu review gaps

* fix(ci): fail closed before Ubuntu package install

* fix(composio): enforce broker URL parity

* Let Antigravity models control computers (mount the computer MCP) (milind-soni#447)

* Let Antigravity models control computers (mount the computer MCP)

agy has no per-turn MCP flag and provably no project-level MCP config
(1.1.19: embedded docs list only the global
~/.gemini/config/mcp_config.json and per-plugin files; agy mcp list
ignores .gemini/{settings,mcp_config}.json in the cwd). So each turn
upserts one key — openmausbot-computer — into the global file right
before the spawn, preserving every other byte of the user's config and
tolerating malformed JSON, and removes that key on the next
computer-less turn so tools and box/control tokens cannot leak into
later turns or the user's own agy sessions.

Cloud boxes mount OpenMausBot's REST-to-MCP computer proxy (resolved
via SPAWNED_PROXIES — never relative to the module, the 0.1.24
lesson); Local VM and VPS connections pass through as the stdio Cua
command they already are.

computerMcp is advertised only by full-auto instances: print mode has
no interactive approval channel, and outside
--dangerously-skip-permissions agy auto-denies tools that would
prompt, so a non-fullAuto mount could never fire. localComputerMcp
stays unset — the host desktop requires per-action human approval,
which print mode cannot deliver in any mode.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: isolate Antigravity computer mounts

* fix: reap settled Antigravity children

* fix: keep MCP lease until child exit

* fix: preserve Antigravity MCP ownership

* fix: clear failed Antigravity turns

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Milind Soni <46266943+milind-soni@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Kesley David <39314443+KesleyDavid@users.noreply.github.com>
Co-authored-by: milind-soni <milindsoni201@gmail.com>
…tools only

Every permission event was stamped approvalScope=local-computer whenever a
bot had This computer enabled — including plain Bash/Edit asks. The server
suppresses allowKey when a scope is set, so the Always-allow button never
rendered for any tool on such bots. Now only mcp__computer* tools carry the
scope; request.resolved looks the tool up from the pending ask.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ew-live-desktop

feat(computer): open live desktop from preview
…y-foundation

fix(ios): pair through every trusted route
…nion-endpoints

feat(companion): carry secure endpoints from desktop to iOS
Max and others added 28 commits August 28, 2026 01:23
Clicking a task closed the menu before a double-click could start the
advertised inline rename. Delay that dismiss so the second click can
land, honor right-click and a hover pencil, and apply the new title
locally so the row does not snap back during the server round-trip.
…-status-skin-tokens

fix(onboarding): use the success and warning tokens for status badges
…-rename

fix(tasks): let the header picker actually rename
…-vm-20260822

Local VM: add secure two-up workspace and Chief status awareness
feat(channels): add separate task conversations
Review routine approvals without crossing provider boundaries
feat(mcp): add Model Context Protocol (MCP) server for external agent orchestration
Users can explicitly ask a bot to list, schedule, update, pause, resume, run, or delete routines in chat. Every mutation remains inert until a durable, exact-detail confirmation card is confirmed, with ownership, stale-state, cloud-readiness, redaction, audit, recovery, and voice safeguards.
…a, model-shaped coercion, guiding errors (milind-soni#544)

Field report (0.1.38, hours after milind-soni#540 shipped): a bot's propose_routine
failed on every attempt — the model tried a 30-minute interval, was told no,
fell back to "daily", failed again, then gave up ("the routine proposal tool
is returning errors every time — it's not accepting any input").

Reproduced the whole pipeline against a live server: the endpoint and proxy
are correct for valid payloads. What actually breaks in the field is the
tool's advertised schema: schedule was a oneOf of two const-discriminated
branches — exactly the JSON-Schema keywords several agent CLIs flatten or
drop when converting MCP tools into their provider's function-call format
(codex only began preserving oneOf in June 2026; other drivers still
simplify). A model that never saw the branches guesses shapes forever, and
every guess failed with a message that never taught it the right one.

Three changes, all proxy-side — the harness dialect is untouched:

- The schedule schema is now one flat object (type enum once|weekly|daily +
  at/time/weekdays), free of oneOf/const/format, so it survives any
  conversion. Rules live in descriptions and are enforced with words.
- normalizeScheduleInput coerces what models actually send: "daily" becomes
  weekly-on-all-seven-days on the wire, JSON-string schedules are parsed,
  weekday names are case-folded and short names (mon..sun) expanded.
- Unsupported shapes now answer with instructions instead of a wall: a
  sub-day interval is named as unsupported with the closest alternatives,
  weekly-without-weekdays points at "daily", unknown types list the three
  supported shapes with examples.

Verified end-to-end against a live server: daily / stringified / short-cap
payloads now produce confirmation cards, interval and missing-weekdays get
guiding errors, and the valid-weekly path is byte-identical. Mutation check:
disabling the daily alias fails the new tests.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(chat): dock the composer over the transcript

Bubbles scroll into the pill instead of clipping on a black bar.
The pill has no hairline; app-ground under it keeps text from
painting below the dock.

* docs(chat): before/after captures for the composer dock

---------

Co-authored-by: Max <ajsdaksfjhs@gmail.com>
…sion eats composition keywords (milind-soni#547)

Codified from the milind-soni#544 field failure: schedule was a oneOf of const-branches,
several engines' MCP-to-provider converters flattened it, and models guessed
shapes forever. The rule, the coercion posture, and the errors-must-teach
posture now live next to the driver SPI guidance so the next tool surface
doesn't relearn it in production.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…m-9dfe

Co-authored-by: mhand <matthewhand@users.noreply.github.com>
Fork main is now even with milind-soni/OpenMausBot main (plus this
delta doc and prior merge commits). Feature work stays on the open
draft PRs.

Co-authored-by: mhand <matthewhand@users.noreply.github.com>
…-ui-architecture-7027

Co-authored-by: mhand <matthewhand@users.noreply.github.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.