feat(ui): mark every arm-driving control; explicit view buttons on library cards - #108
Open
Mokuroh54 wants to merge 2 commits into
Open
feat(ui): mark every arm-driving control; explicit view buttons on library cards#108Mokuroh54 wants to merge 2 commits into
Mokuroh54 wants to merge 2 commits into
Conversation
Mokuroh54
force-pushed
the
feat/studio-panels-rework
branch
from
September 2, 2026 17:44
86d51df to
20ae38d
Compare
Mokuroh54
force-pushed
the
feat/robot-action-affordance
branch
from
September 2, 2026 17:46
0b72dcc to
facc738
Compare
This was referenced Sep 2, 2026
…icit view buttons Robot-action affordance - Button gains a `robot` variant (amber, new --robot/* tokens in both themes) and a `destructive` reuse for anything that ends with the arm de-energized. `RobotActionButton` / `ReleaseActionButton` wrappers pin the icon (Zap / PowerOff) and a mandatory tooltip resolved from `lib/robotActions.ts`, keyed by session kind; a vitest parity test ties the energizing kinds to `SessionStartBody.kind` in the OpenAPI snapshot. - 21 buttons across 9 components switched: every session starter (teleop, record, both inference starts, replay, manual/auto/zero-pose calibration, wiggle) is amber; every Stop / Quit / Abort / Cancel- calibration is red. Read-only controls stay neutral so the signal keeps its meaning. No release-torque UI is added (none exists). - Tooltip strings in en + zh-CN. Library cards - Dataset card: clicking the card toggles selection (role=button, keyboard, focus ring); the footer Select is replaced by an outline "View dataset" button that opens the episode viewer and renders only where a viewer is wired. Click-to-view is removed. - Run card: card-level click and hover affordance removed; a "View run" button leads the action row, hidden for imported jobs as the click was. - `library.datasets.select/selected` are now dead keys, kept for a separate catalog cleanup. Cosmetic only: no request, storage or form-value change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The coaching work replaced the panel's Start/Stop pair with RunVerbs, whose three verbs all start an inference session. Their `variant` is the armed-state channel and their `title` carries the blocked reason, so they cannot take RobotActionButton; the shared affordance rides on the icon alone: the Play glyph inside each label becomes the bolt from lib/robotActions.ts. Variants, title, aria-disabled and the ring are untouched, and RunVerbs.test.tsx asserts nothing about the icon. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Mokuroh54
force-pushed
the
feat/robot-action-affordance
branch
from
September 3, 2026 15:10
facc738 to
a2d3657
Compare
Mokuroh54
added a commit
that referenced
this pull request
Sep 3, 2026
Slice 3.4 of the DRTC integration (design: docs/drtc/SLICE3.md, "S3.4 as built"). Remote inference is now startable, watched and stopped from the Deploy panel; the SFU and the Modal policy server are still started by hand, which is what the generated command line is for. - Deploy panel: a fourth run mode, "Run it remotely" (verb grid 3 → 2x2), reusing the panel's existing checkpoint derivation of camera_bindings / camera_dims / checkpoint_state_dim / task and forking only at startSession(kind="remote_inference"). Remote-only fields: Hub policy id, horizon, fps, video codec, max duration. The ACT temporal-ensemble control, the engine picker and the shared duration field are hidden for this mode. Guards: armSupportsRemote (single SO-101 only — CAN arms and bimanual refused, checked first) and transportReady (the transport endpoint must report configured, reachable and an operator in the room; "not ready" while the probe is in flight). The heartbeat is held by DeployPanel itself, which StudioOverlay keeps mounted, so closing the overlay does not let the lease expire. - The generated `modal run` line (components/remote-inference/ modalCommand.ts, asserted verbatim in tests): built from the same options object the session is started with, plus the transport's url/room, so the two halves cannot disagree on horizon/fps/codec/room — Portal drops mismatched packets silently, and this is the mitigation. Carries --task (shell-quoted) when set; on a local-SFU override adds --tailscale --livekit-url and key/secret as literal <from livekit.local.yaml> placeholders — the API never exposes secrets. - Status panel: the eleven-phase ladder from remote_inference.py, returning_to_rest during stopping, elapsed/duration, operator, chunks/requests, a lead-vs-(horizon - s_min) margin bar, a DEGRADE badge, chunk age, e2e p50/p95, rtt, and holds as a per-second RATE (a healthy run's cumulative holds freezes after warm-up, so the counter would mislead forever after); outcome/error/hint and the log path when a run ends. - Transport section: source (which credential layer supplied the URL), url/room, missing variables, the local-override file with a delete button (idempotent; never touches livekit.local.yaml), reachable / operator-present as a three-state (null = not probed), error code and message verbatim. - Hooks: useRemoteInferenceStatus polls at 1 Hz while a remote session is live regardless of the studio being open, refetching eagerly on a session_changed hint — the first real consumer of useSessionEvent; useRemoteInferenceTransport fetches on demand and exposes clearLocalOverride(). Every request targets /api/v1. - i18n: a new `remoteInference` namespace (en + zh-CN) rather than growing `studio`, keeping the shared catalog diff small for the studio-rework rebase; codec ids, room, URL, error codes and every character of the generated command are data and are not translated. The whole surface lives under frontend/src/components/remote-inference/; the footprint in shared files is one run-mode entry, two guard flags, two hooks and one mounted element in DeployPanel.tsx / deployGuards.ts, so the rebase across PRs #107/#108 stays small. Known limitation: the block renders inside the Deploy panel's "skill selected" section, so a run started elsewhere is not visible until a skill is picked. Checks: lint delta 0 against the 38-problem baseline; both tsc projects clean; vitest 27 files / 292 tests; build ok with frontend/dist restored (CI rebuilds it). No package-lock change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Mokuroh54
added a commit
that referenced
this pull request
Sep 3, 2026
Brings the run-form opener, single-popover policy/checkpoint pickers, stretched libraries and picker badges (origin/feat/studio-panels-rework @ 20ae38d) onto the DRTC branch, so the checkpoint is picked from one popover instead of the old flow. PR #108 (button affordance) deliberately not included. Three conflicts resolved: DeployPanel.tsx was rebuilt on the rework's render body with slice 3.4's remote-inference mode re-expressed on it (fourth verb, guard flags, the two hooks, the panel-held heartbeat, runActive feeding the guards and camera-preview pause, remote-hidden controls, the startSession(kind="remote_inference") fork reusing the reworked camera derivation, and <RemoteInferenceBlock> now inside the run form with an unchanged visibility rule). The run form is held open while a remote run is live (open={formOpen || remoteActive}) because remote's live surface — telemetry and Stop — is inline in the panel rather than in the session dialog the local modes open. The two studio catalogs are the union of both sides; PR #107's new keys arrived in the retired "skill" vocabulary and were merged under the policy spellings (deploy.entry "Run a policy", deploy.policy.label, deploy.checkpoint.pickPolicyFirst). Nothing under components/remote-inference/ changed. Checks on the merged tree: lint 38 problems (4 errors) — identical to both parents' baselines, zero in touched files; both tsc projects clean; vitest 27 files / 292 tests; build ok with frontend/dist restored. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Robot-action affordance
Makes it unmistakable which buttons drive the arm, with one shared affordance and one source of truth.
robotButton variant (amber; new--robot/*tokens in both themes, 8.8:1 light / 10.8:1 dark) and the existingdestructivefor anything that ends with the arm de-energized.RobotActionButton/ReleaseActionButtonwrappers pin the icon (Zap / PowerOff) and a mandatory tooltip fromlib/robotActions.ts, keyed by session kind. A vitest parity test asserts the energizing kinds equalSessionStartBody.kindindocs/api/openapi.json, and fails loudly if that enum disappears.enandzh-CN.Deliberate side effects of the rule: recording's Done (was green) and Quit are both red now; the inference Abort buttons are solid red rather than outline.
Not included: a header "arm held" chip. There is no shared page chrome, and
session_changedcarries no session id, so the chip needs a per-hint fetch of the current session. Deferred.Library cards
CollectPanelis the only consumer and needed no change;selectedDatasetdrives only the header chip and the Train panel.HubJobCard's click opens an external Hub page and is left as is.library.datasets.select/selectedare dead keys, kept for a separate catalog cleanup.Re-applied onto
staging(2026-09-03)stagingrestructured the calibration panel since this was written (1a917364: one control per arm row, mode picked first), so theRobotConfigDialoghunks were re-applied by hand against that layout:DeviceSlotCell. It becomes an amber iconRobotActionButton(bolt replaces the hand glyph, spinner while wiggling); the nativetitlecomes off so the shared tooltip does not fire beside it, and thearia-labelkeeps the icon named.HandandSquareimports drop as a result.CollectPanel's Start keepsstaging'smt-autopin wrapper; only the button inside changes.RunVerbs. Its verbs cannot takeRobotActionButton(theirvariantis the armed-state channel, theirtitlecarries the blocked reason, and they usearia-disabledon purpose), so the affordance rides on the icon alone: each verb's Play glyph is the bolt (second commit).variant,title,aria-disabled, the ring andRunVerbs.test.tsxare untouched.InferenceSessionDialog's surviving Stop and both Abort buttons keep the red release treatment. The coaching flow's quiet "End session" ghost button also ends the session de-energized but was deliberately left quiet by its author; listed here, not converted.Checks
Against
stagingat526e0412:tscboth projects clean; vitest 294/294 (29 files) including the parity and i18n tests; lint 38 problems before and after (all pre-existing);npm run buildok;frontend/distandpackage-lock.jsonuntouched.Manual checklist: amber legible in both themes; hover tooltips repaint on language switch; disabled Teleop chip shows the setup-gap reason, not the robot tooltip; card click selects, View dataset opens the viewer without changing selection; View run opens the monitor; the slot-cell wiggle bolt spins while wiggling.
🤖 Generated with Claude Code