- Support invite code discovery in main chat and redemption in settings menu - Add Settings RPA primitives with Radix UI mouse dispatch and retry polling for async DOM - Attribute 'has_redeemed' binary from the Additional tokens ticker / entrypoint visibility - Unblock agent @646 by repairing warp-def/dev tunnels and redeeming REDCJ7 via dev (+1B tokens) - Implement 'box onboard' pipeline to provision infra, authenticate, and auto-redeem queued codes - Add 'box onboard feed-matrix' ranking all agents by work done over time, job count, and role - Register 'InputType.SALVAGE' in loop modulation (CRITICAL priority, 600s timeout, 3 nudges to opm) - Ingest recurring balance audits into canonical HEARTBEAT.md and TOOLS.md
3.7 KiB
hatch_menu — Modular Settings-Menu Navigation + Toggles
bin/hatch_menu/ drives the muse.ai Settings menu in the agent
browsers. One module per part: a site change means patching one file.
Exposed as box chromebox permissions ...; bin/invite.py usage
reads ride the same tree.
Layout
bin/hatch_menu/
__init__.py package surface (dialog + mouse + toggles fns)
mouse.py trusted input: real_click, escape, close, MouseError
dialog.py open_settings (retried), goto_tab, click_row,
describe_rows, go_back, dialog_text, TAB_NAMES
controls.py radio/switch list + set (verify, else trusted
click, verify again)
toggles.py toggle registry + sessions: resolve/get/set/list,
describe_tab, MenuError
tabs/
__init__.py TAB_MODULES (10 tabs, uniform describe(ws))
permissions.py defaults radios, website modes, protocols,
advanced switches, counts, tasks
general.py usage parse, theme, redeem entrypoint
data_controls.py model-improvement switch (rest read-only)
connectors|wallet|secure_store|messaging|devices|
help_support|legal.py read-only inventories
Dependency order (no cycles): mouse <- dialog <- controls
<- tabs/* <- toggles. Tab modules own their contracts
(headings, labels, slugs, modes); toggles.py only addresses them.
Toggle addresses
Static: permissions.connector_defaults,
permissions.web_access (auto_allow/always_ask);
permissions.advanced.transparent_proxy|tls_interception| sni_mismatch_rejection, data_controls.ai_improvement (on/off);
general.theme (match/default/blue/purple/pink/orange/green/
beige/monochrome).
Families: permissions.websites:<host> (Allow/Ask/Deny),
permissions.protocols:<slug> (on/off; slugs discovered live,
e.g. mcp-sse, mcp-streamable, agent-skills, mcp-apps,
mcp-oauth).
Every set verifies in place and reads back through a fresh
session; readback mismatch reports failure, never partial success.
Caller errors (unknown node/toggle/tab/value) raise MenuError
before any CDP traffic. Transport failures return {"ok": False}.
CLI
box chromebox permissions <node> list [--tab TAB] [--json]
box chromebox permissions <node> get <toggle> [--json]
box chromebox permissions <node> set <toggle> <value> [--json]
box chromebox permissions <node> describe <tab> # JSON inventory
Exit 2 on caller errors, 1 on transport/unreadable toggles.
Patch guide
| Site change | Patch |
|---|---|
| Dock button / dialog open flow | dialog.py (open_settings) |
| Radio/switch mechanics | controls.py |
| Permissions headings, modes, slugs, adv labels | tabs/permissions.py |
| Usage text, theme values | tabs/general.py |
| Data-controls switch label | tabs/data_controls.py |
| New settable toggle | tab module contract + toggles.py registry row |
| Trusted-click transport | mouse.py |
describe <tab> dumps a tab's live inventory for debugging.
Provenance
Contracts come from live read-only DOM recon (2026-10-06):
Permissions radios auto_allow/always_ask, Websites Allow/Ask/
Deny chooser (real click to open), 8 protocol switches, Advanced
section (Transparent proxy off, TLS interception off, SNI mismatch
rejection on), Data-controls single switch, General theme radios.
Radix menus need real Input.dispatchMouseEvent press+release with
monotonic CDP ids; synthetic clicks fail. Recon never touches Reset.
Tests
tests/test_hatch_menu.py (mocked CDP, per-module):
mouse/trusted-clicks, dialog open-retry/tab/row flows, control
verify-then-fallback, registry resolution + readback mismatch,
tab contracts on live-captured fixtures. tests/test_invite.py
covers the invite shims + flat usage parse.