emrg: gui — restore three-tier sandbox switcher in chat composer - #1077
Conversation
…t 2026-08-30T16:34:29)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle. Verified against daemon semantics:
Regression claim confirmed & fixed. React Composer previously threaded the sandbox prop (default null) with no UI. Daemon only injects args["sandbox"] when truthy (daemon.py:2753), so null fell through to the bash tool default = danger-full-access (bash_tool.py:99) — React messages ran with full access where vanilla defaulted to workspace-write. This PR always sends an explicit tier (default workspace-write), restoring vanilla behavior.
Correctness checks:
SANDBOX_TIERS(read-only / workspace-write / danger-full-access) matchesSANDBOX_MODESexactly (bash_tool.py:119)- Vanilla parity: #898's implementation defaulted to
sandbox: "workspace-write"(sendTask default + state default + active button); this port uses the same class names (mode-btn/active),data-sandboxattrs, and i18n structure — faithful sanitizeSandbox: invalid → null → caller falls back to workspace-write, mirroring vanilla setSandbox validation- i18n: 3 new keys × 2 dicts (392), parity guard updated and passing
Verification (local, PR head 343682e):
- Composer.test.tsx 34/34 (3 new switcher tests meaningful: default-active assertion + per-tier sandbox payload on send)
- Full renderer suite 479/479 — matches the Agent.md count update exactly
tsc --noEmitclean- CI: test + test-windows both green (run 33305134177)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle. Re-verified on unchanged head 343682e:
- Head identical to previous LGTM (343682e) — no new commits since last review
- CI: test + test-windows both green (run 33305134177)
- mergeable: MERGEABLE / CLEAN, maintainerCanModify
Prior verification stands: SANDBOX_TIERS matches SANDBOX_MODES exactly, vanilla #898 parity (default workspace-write, mode-btn/active classes), i18n parity 392, full renderer suite 479/479 + typecheck clean. LGTM 2/3.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle. Third consecutive approval on unchanged head 343682e (distinct cycles, no ❌ between).
Head identical to prior verifications: SANDBOX_TIERS matches SANDBOX_MODES (bash_tool.py:119), vanilla #898 parity (default workspace-write, mode-btn/active), i18n parity 392, full renderer suite 479/479 + typecheck clean, CI test + test-windows green (run 33305134177). Merge condition met.
Uh oh!
There was an error while loading. Please reload this page.
Restore the three-tier sandbox switcher in the chat composer (rant 2026-08-30T16:34:29 — regression from the React renderer migration).
Problem: the vanilla renderer shipped a per-message sandbox tier switcher (read-only / workspace-write / danger-full-access, rant 2026-08-20T18:18). The React migration dropped the UI:
Composeraccepted asandboxprop but rendered no switcher, so every message went out withsandbox: null— and the daemon treatsNoneas danger-full-access. The chat window silently regressed to full access with no way to switch tiers.Changes:
Composer.tsx— addedSANDBOX_TIERS+sanitizeSandboxvalidation (mirrors vanillasetSandboxallow-list), local tier state defaulting toworkspace-write(vanilla default), and a.mode-switcherbutton group above the composer card; the selected tier is sent with every message (normal + busy-queue paths).shell.css—.mode-switcher/.mode-btn/.mode-btn.activestyles (ported from vanilla components.css, adapted to React CSS vars).i18n-dicts.ts— 3 short-label keys added to both zh/en dicts (parity kept;composer.sandbox*title keys already existed from the migration).i18n.test.ts— key-count assertion 389 -> 392.Composer.test.tsx— 3 new cases: default active tier, switch to read-only carries the tier into sendMessage, switch to danger-full-access likewise.Agent.md— renderer test breakdown 31 Composer -> 34, headline 476 -> 479.Verification:
npm test-> 45 files / 479 passed;npm run typecheckclean.pytest tests/-> 1176 passed, 1 skipped (doc-count guard synced).