leisaac ยท diff

git:20260818.c836fa3 to git:20260905.bc1c320

34 added, 4 removed. Audit A to A.

---
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`, the
- LeIsaac tab/panel and unavailable state, status no-store behavior, secure
- transport labeling, and backend authorization. With an explicitly accepted,
- live LeIsaac run, also exercise connect/reconnect, controller contention,
+ 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.