fix(ui): loud clipboard denial, mid-width kill verb, phone legibility (dogfood 2026-08-24) - #9
Merged
Conversation
From the 2026-08-24 dogfood walk (founder-agent-os/prototypes/ dogfood-reports-2026-08-24/agent-usage-manager.md): - bug #1: copyHint had no .catch on navigator.clipboard.writeText — a denied write (permission, unfocused document) failed silently and the operator walked away believing they held a bootout command they didn't. Now flashes "copy failed — press ⌘C" on the chip, then selects the command for a manual copy (an active selection also pauses auto-refresh, so it can't be yanked). Guards the mid-flash re-render race (el.isConnected) so the console stays clean. - bug #2: the 701–~1494px dead zone — the ~1.5kpx nowrap table scrolled the last column (the only kill verb) off-screen while the phone stack only engages ≤700px. The actions column (.c-act) is now position:sticky on the right above the phone breakpoint, right-aligned so the verbs hug the pinned edge (the nowrap launchctl hint inflates the column). Measured at 800px, unscrolled: 0/40 kill buttons visible before, 40/40 + 5/5 launchctl chips after. - F1: phone rows rendered unitless cpu/mem ("1.0 155") — .unit spans, hidden on desk (headers carry the units), shown in the phone stack. - F2: phone child rows lost the cmdline, their only identity — child .c-cmd stays visible in the phone stack, wrapped. - F3: the phone launchd hint ellipsed the job label (the one part that differs) — now truncates from the left (direction: rtl) at 240px, so "…501/ai.hermes.gateway-frontdoor" instead of "launchctl boot…". Out of scope (follow-up): F4, the chronic idle daemon pinned top-row — needs cmdline-granular idle_ok matching in app.py, a config-semantics change. Verified: 75 pytest pass (incl. new test_index_frontend_regressions); browse-verified against an isolated :8766 instance (live :8765 never touched, zero kill clicks): clipboard denial simulated by overriding writeText to reject (flash at t=1ms, restore+select at t=1503ms; success path still flashes "copied ✓"); sticky verbs reachable at 800px and 1440px; phone rows carry units + child cmdlines; hint chips show the job-label tail; console clean. LLD §6 line cites refreshed per the design-doc contract.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Frontend fixes from the 2026-08-24 dogfood walk of the live fleet dashboard (
founder-agent-os/prototypes/dogfood-reports-2026-08-24/agent-usage-manager.md). All changes are inagent_usage_manager/static/index.html(+ regression test + LLD §6 line-cite refresh per the design-doc contract).Bug #1 — click-to-copy failed silently when the clipboard write was denied
copyHintwasnavigator.clipboard?.writeText(...).then(...)with no.catch. A denied write (permission, unfocused document — reproduced live in the walk) produced no "copied ✓", no error, nothing on the clipboard: the operator walks away believing they hold abootoutcommand they don't have.Now a rejection (or missing clipboard API) flashes "copy failed — press ⌘C" on the chip, then restores the command and selects it so a manual copy is one keystroke away (an active selection also pauses auto-refresh via the existing
refresh()guard, so the re-render can't yank it). Anel.isConnectedguard covers the race where a poll re-renders the row mid-flash, keeping the console clean.Bug #2 — 701px–~1494px dead zone hid the only kill verb
The all-
nowraptable measures ~1.5kpx;.wrapscrolls horizontally and the actions column — the last one — sat off-screen until scrolled to, while the stacked phone layout only engages ≤700px. A half-screen desk window landed in a dead zone: full chrome, no reachable verb.The actions column (
.c-act) is nowposition: sticky; right: 0above the phone breakpoint, withtext-align: rightso the verbs hug the pinned edge (the nowraplaunchctlhint chips inflate the column to ~454px). Phone rows are stacked blocks with no horizontal overflow, so the rule is scopedmin-width: 701px.F1/F2/F3 — phone legibility
1.0 155with no units (headers hidden,titletooltips unreachable on touch)..unitspans — hidden on desk where the headers carry the units, shown in the phone stack →1.0% 155 MB(main + child rows)..c-cmdat ≤700px — their only identity ("↳ 2.1.241 0.0 34"). Child cmdline now stays in the phone layout, wrapped (overflow-wrap: anywhere).direction: rtl, 240px) → "…501/ai.hermes.gateway-frontdoor". Click-to-copy still copies the full text.Validation
pytest tests/— 75 passed (includes newtest_index_frontend_regressionspinning the served page's behavior-bearing markup; no JS runner in this repo)./tmp/aum-before-midwidth-800.png//tmp/aum-fix-midwidth-800.png; desk:/tmp/aum-fix-desk-1440.png.writeTextto reject withNotAllowedError— MutationObserver recorded "copy failed — press ⌘C" at t=1ms, command restored + fully selected at t=1503ms; success path still flashes "copied ✓" (stubbed resolve). Screenshot:/tmp/aum-fix-copy-failed.png. Console clean.4.8% 259 MB; expanded children show full wrapped cmdlines; supervised chips read "…/ai.hermes.gateway-engineer_5" etc. — each distinguishable. Screenshots:/tmp/aum-fix-phone-tree.png,/tmp/aum-fix-phone-hint.png.Deferred (follow-up PR, per assignment scope)
idle 10m+daemon row pinned top forever —idle_ok:matches on row label (app.py:1201-1209) and the daemon sharesclaude-codewith every interactive session; needs cmdline-granular suppression (e.g.idle_ok_match:). A config-semantics change, deliberately not in this frontend PR.test_design_docs.pyflagsagents.default.yamlas added-but-unnamed in the LLD.F5 (native confirm/prompt chrome) and F6 (keyboard a11y on the
+N/hint spans) also remain open from the report.