leisaac · git:20260905.bc1c320 · 2026-09-05 · sha256 f4a86342cf41eefe
leisaac git:20260905.bc1c320A
Immutable. This exact content is served forever at /api/v1/blob/f4a86342cf41eefe.
--- name: leisaac description: Use when building, launching, operating, reviewing, or live-testing the NPA LeIsaac browser teleoperation tool, its secure agent-relay transport, immutable LeRobot datasets, custom bundles, or PAIDF export/materialization. --- # LeIsaac browser teleoperation Use this skill for the real LightwheelAI/LeIsaac workbench service and its authenticated NPA agent UI. Read `docs/workbench/leisaac-teleoperation.md` and `docs/workbench/guides/leisaac-transport-latency.md` before changing runtime, transport, recorder, or UI behavior. Also load these skills when their surfaces are involved: - `third-party-eula-preflight`, `gpu-selection`, and `nebius-infra` before a live launch; - `npa-agent` and `agent-fresh-operate` for agent deployment or live UI tests; - `workbench-tool`, `testing-conventions`, `real-components`, and `solution-licensing` for implementation, validation, or packaging changes; - `physical-ai-data-factory` for PAIDF export or materialization. ## Ground truth and capability boundary - Source is LeIsaac `0.4.0` at `1651c321e9b0c1bb54233211fc7b3cd70d8373d5` with exact, build-gated NPA packaging and observability patches. - The supported real tasks are `LeIsaac-SO101-PickOrange-v0` and `LeIsaac-SO101-LiftCube-v0`. Browser operation uses upstream `SO101Keyboard`; one session controls exactly one environment. - Rendering requires RT cores. The current launcher supports only the named RTX PRO 6000 Kubernetes pool. Do not route this workload to H100/H200, and do not advertise L40S until this exact image and launch path are validated. - Isaac Sim/Lab, NVIDIA's browser client, SO-101, and scene assets are runtime-fetched only after the shared Isaac preflight. The single public input defaults `ACCEPT_EULA=Y`; `Y`, `YES`, `1`, and `TRUE` normalize to `Y`, while empty, `N`, `NO`, `0`, and `FALSE` explicitly opt out before download and other values are invalid. The runtime derives `OMNI_KIT_ACCEPT_EULA=YES` internally. Do not add duplicate public consent variables or prompts. Keep `PRIVACY_CONSENT` and telemetry off by default. - This is a lifecycle-bearing interactive service, not a finite `npa.workflow` step. Launch and destroy it with the workbench CLI. ## Security and transport decision Use `agent-relay`, the CLI default, for production. It keeps Kubernetes on a private ClusterIP and carries status, controls, frames, and signaling through the agent's authenticated HTTPS origin and an authenticated WSS backhaul. TURN uses a digest-pinned coturn sidecar, session-scoped credentials, bounded relay ports, and operator CIDR restrictions. The browser never receives the raw session nonce or agent credentials. `public-load-balancer` is an unsupported historical transport. Its S3 manifest cannot securely deliver the browser credential, because publication strips the session nonce and there is no provenance-bound reinjection path. Launch rejects it before EULA or infrastructure mutation. Retain only status/destroy handling needed to diagnose and clean up already-existing historical resources; never describe that mode as usable, TLS, or secure. All control transports terminate in the same ordered runtime ledger and controller lease. WebSocket, data-channel, and HTTP polling fallbacks must enforce identical ownership: a second authenticated browser cannot drive keys, direct actions, modes, or orbit while another browser owns the lease. Preserve exact-key bounded messages, idempotent sequence acknowledgements, disconnect release, and bounded replay semantics. All same-run mutators (launch, destroy, and the lifecycle proof) use a renewed Kubernetes Secret as an exclusion lock. Preflight requires `get`, `create`, `update`, and `delete` on Secrets in the selected namespace before mutation. Custom cleanup-only roles must include those verbs; never bypass the lock to make teardown proceed concurrently with launch or credential rotation. ## Operate Inspect supported tasks before launch: ```bash npa/.venv/bin/npa workbench leisaac list-tasks --output json ``` Launch a digest-pinned image. Isaac acceptance defaults on for this route; `ACCEPT_EULA=N` is the explicit pre-download opt-out: ```bash npa/.venv/bin/npa workbench leisaac launch \ --run-id <run-id> \ --image <registry>/npa-leisaac@sha256:<digest> \ --context <rtxpro-kubernetes-context> \ --namespace <namespace> \ --source-range <operator-public-ip>/32 \ --agent-project <project-alias> \ --agent-name <agent-name> \ --task LeIsaac-SO101-LiftCube-v0 \ --environment-id <stable-environment-id> \ --environment-index 0 --seed 42 --num-envs 1 \ --output-path s3://<bucket>/datasets/<dataset> \ --manifest-prefix s3://<bucket>/checkpoints ``` The omitted `--transport` deliberately defaults to `agent-relay`. The image must be `repository@sha256:digest`; source ranges must be explicit restricted CIDRs. `--output-path` is the dataset prefix. `--manifest-prefix` is the capability prefix or exact `.../reports/leisaac-session.json` leaf. LeIsaac's required node affinity accepts either GPU Feature Discovery's exact RTX PRO 6000 product label or Nebius's managed-node `RTX6000` provider label; this preserves RT-core routing when managed drivers intentionally disable GPU Operator operands. Inspect and clean up only the selected run: ```bash npa/.venv/bin/npa workbench leisaac status \ --run-id <run-id> --context <context> --namespace <namespace> npa/.venv/bin/npa workbench leisaac destroy \ --run-id <run-id> --context <context> --namespace <namespace> ``` Destroy removes transient Kubernetes, relay, TURN, recorder-secret, and exact NPA-managed ingress resources. It preserves immutable S3 manifests, episodes, versions, and evidence. If launch fails, preserve the original error while reporting every cleanup failure and partial ingress progress. ## Artifacts and real-component guarantees - Capability: `<manifest-prefix>/<run-id>/reports/leisaac-session.json`, or the exact leaf supplied by the operator. It is write-once evidence, while agent resolution uses bounded freshness so a same-ID relaunch cannot retain a stale nonce or endpoint. - Dataset: immutable episode commits, version trees, Parquet records, raw JPEG evidence, and H.264 faststart MP4s under `--output-path`. `latest.json` is only a bounded-retry monotonic pointer; it is not the dataset record. - Custom robot/scene/device bundles are canonical, hash-addressed, bounded, and runtime revalidated. Uploaded Python is parsed but never executed. - PAIDF export must invoke the real Cosmos Transfer tool. Materialization must fail closed unless a real input-conditioned result preserves frame/timestamp alignment; never turn a manifest stub into a claimed augmentation. ## Packaging and licensing `npa-leisaac` is a public runtime-fetch image only when the built digest proves that Isaac/Omniverse payloads, the NVIDIA client, task assets, credentials, and caches are absent. Follow `npa/docker/workbench/leisaac/REDISTRIBUTION.md`, `THIRD_PARTY_NOTICES.md`, and `npa/docker/workbench/packaging-contract.yaml`. Validate the built image itself with `npa/scripts/scan_image_omniverse_payload.py`; Dockerfile inspection is not evidence. The host-side `imageio-ffmpeg==0.6.0` dependency belongs only to the `leisaac` extra, never `full` or core. Its wheel-bundled FFmpeg is excluded from the container; the image uses Debian FFmpeg. Keep coturn, pygame, aiortc, FFmpeg, and every other installed dependency represented accurately in notices. ## Agent UI availability LeIsaac UI is off by default. Its sole opt-in is YAML boolean `true` at `projects.<project-alias>.agents.<agent-name>.ui.leisaac_enabled` in the operator's `~/.npa/config.yaml` (`$NPA_CONFIG_DIR/config.yaml` when configured). Absent/false, non-booleans (including `"true"` and `1`), and malformed sections remain disabled. Keep navigation and capability polling absent in that state; browser storage, URL parameters, and client-only enable controls cannot opt in. After editing the operator config, bootstrap the same agent with `npa agent bootstrap --project <alias> --name <name>` and reload open browser pages. The flag is rendered into static HTML, so service restarts or VM reboot alone do not apply config edits. Bootstrap preserves the nested UI setting across record updates. Enabling exposes the normal readiness flow without launching a runtime or bypassing authorization. The minimal YAML and full lifecycle are in `docs/workbench/leisaac-teleoperation.md`, under **What makes the tab appear**. ## Live agent UI verification Deploy or bootstrap the agent from the branch under test using `npa-agent` and `agent-fresh-operate`. Use only the HTTPS customer URL and owner-only auth file; never print credentials. At minimum verify authenticated `/api/health` and both configuration states. Absent/false must produce no LeIsaac navigation or capability polling, including after restoring a historical localStorage opt-in. With boolean true, verify the normal tab/panel and unavailable state, actual readiness requests, status no-store behavior, secure transport labeling, and backend authorization. Exercise DOM interactions in Cypress, not only source string assertions. For temporary live configuration changes, preserve the operator's explicit opt-in or restore the false default after testing. With an existing authenticated deployment, run `npm run cy:live-access` from `npa/tests/browser` using protected `NPA_AGENT_BASE_URL`, `NPA_AGENT_USER`, and `NPA_AGENT_PASSWORD` environment values. It expects LeIsaac hidden; set `NPA_AGENT_EXPECT_LEISAAC=true` to assert a deployment already enabled through operator config. That test expectation does not enable the feature. Keep live output and screenshots only in access-controlled evidence outside Git. With an explicitly accepted live LeIsaac run, also exercise connect/reconnect, controller contention, motion and orbit, recorder transitions, finalized episode playback/ranges, and the live Cypress suite: ```bash cd npa/tests/browser npm run cy:live-leisaac ``` Set the required `NPA_AGENT_BASE_URL`, `NPA_AGENT_USER`, `NPA_AGENT_PASSWORD`, `NPA_LEISAAC_RUN_ID`, and `NPA_AGENT_TASK` environment values without committing or logging secrets. Keep the session available when the operator requested continuing access; otherwise use the scoped `destroy` command and record cleanup status. When replacing only the agent for an explicitly selected existing run, retain the exact `.../reports/leisaac-session.json` URI before agent teardown and use `npa workbench leisaac reconnect-agent` after the fresh agent is healthy. This command must preserve the existing Deployment, image, task, dataset, and run-scoped EULA values; it may rotate only the relay Secret/nonce, exact agent ingress, and that exact manifest. Never substitute `launch`, create another workload, or use broad bucket discovery for this recovery. When an operator explicitly requests relay restart and expiry proof against an existing run, use `npa/scripts/verify_leisaac_relay_lifecycle_live.py`. It is a mutating, same-Deployment check: it holds and safely releases a control across restart, verifies browser-facing control/video recovery, fires bounded credential expiry, resumes the same controller lease to prove its held keys were released before any pod restart, writes a new immutable capability generation for the rotated session credential, rejects the stale credential, and restores recorder-idle service. It temporarily scales that same Deployment to zero so current-nonce acceptance and stale-nonce denial are isolated from the single-active-backhaul rule. The original capability and immutable dataset objects remain unchanged. Never use it to infer EULA consent, launch a replacement workload, or test an unrelated run. Store its secret-free evidence outside Git with owner-only permissions. ## Validation Use the repository venv, never bare Python: ```bash npa/.venv/bin/python -m pytest \ npa/tests/workbench/test_leisaac.py \ npa/tests/workbench/test_leisaac_cli.py \ npa/tests/workbench/test_leisaac_dataset.py \ npa/tests/workbench/test_leisaac_agent_relay.py \ npa/tests/workbench/test_leisaac_paidf.py \ npa/tests/cli/test_agent_leisaac.py \ npa/tests/cli/test_agent_ui_config.py \ npa/tests/cli/test_agent_leisaac_bundles.py \ npa/tests/cli/test_agent_leisaac_episodes.py \ npa/tests/cli/test_leisaac_datachannel.py \ npa/tests/cli/test_leisaac_transport.py -q npa/.venv/bin/python -m pytest \ npa/tests/guardrails/test_hygiene_guards.py \ npa/tests/guardrails/test_skills_index.py \ npa/tests/guardrails/test_packaging_contract.py -q cd npa/tests/browser && npm run cy:mock ``` Also run Ruff, mypy, docs generation, the broad non-E2E suite, and image build plus full-filesystem payload scan when image contents change. Do not weaken content scans, upstream patch gates, exact input validation, escaped UI sinks, immutable publication, real-component checks, or the terminator guard.