Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9f5db21
Merge pull request #1 from Eleanor1018/bugfix/webui
Eleanor1018 Aug 24, 2026
f903e16
Merge pull request #2 from Eleanor1018/bugfix/webui
Eleanor1018 Aug 24, 2026
9c62d19
Merge pull request #3 from Eleanor1018/bugfix/webui
Eleanor1018 Aug 24, 2026
67e448e
Merge pull request #4 from Eleanor1018/bugfix/webui
Eleanor1018 Aug 25, 2026
353dcfc
Merge pull request #5 from Eleanor1018/bugfix/webui
Eleanor1018 Aug 25, 2026
d89dbeb
Merge pull request #6 from Eleanor1018/feature/task-settings
Eleanor1018 Aug 27, 2026
39da65f
Merge pull request #7 from Eleanor1018/style/square-controls
Eleanor1018 Aug 31, 2026
a0ac3fd
Merge pull request #8 from Eleanor1018/style/square-controls
Eleanor1018 Aug 31, 2026
8ccebc1
Merge pull request #9 from Eleanor1018/style/square-controls
Eleanor1018 Aug 31, 2026
cdf35b6
Merge pull request #10 from Eleanor1018/style/square-controls
Eleanor1018 Aug 31, 2026
b0e4eb2
test(desktop): refresh workspace smoke assertions
Eleanor1018 Aug 31, 2026
2e0cb9e
Merge pull request #11 from Eleanor1018/style/square-controls
Eleanor1018 Aug 31, 2026
1dd1e80
feat: add WebUI, desktop, and agent workflow support
Eleanor1018 Aug 31, 2026
433dc08
Merge pull request #12 from Eleanor1018/feature/consolidated-workbench
Eleanor1018 Aug 31, 2026
ea499b8
fix(viewer): stabilize legacy Viser markdown rendering
Eleanor1018 Aug 31, 2026
1fcb7a6
fix(i18n): localize retarget workflow state
Eleanor1018 Aug 31, 2026
a047c6b
Merge pull request #13 from Eleanor1018/feature/consolidated-workbench
Eleanor1018 Sep 1, 2026
adf9759
feat(desktop): add standalone Linux package support
Eleanor1018 Sep 1, 2026
e62ef0d
fix(calibration): persist packaged robot overrides in user storage
Eleanor1018 Sep 1, 2026
5f49309
Merge pull request #14 from Eleanor1018/feature/consolidated-workbench
Eleanor1018 Sep 1, 2026
c7b197a
feat(gvhmr): import external motion results
Eleanor1018 Sep 2, 2026
a951595
Merge pull request #15 from Eleanor1018/feature/gvhmr-extension
Eleanor1018 Sep 2, 2026
0fb1861
fix(startup): validate WebUI dependencies
Eleanor1018 Sep 2, 2026
63ad363
refactor(webui): migrate workbench from Vue to React
Eleanor1018 Sep 2, 2026
83461d3
docs(webui): clarify React architecture boundaries
Eleanor1018 Sep 2, 2026
f139ddb
Merge pull request #16 from Eleanor1018/feature/reformation
Eleanor1018 Sep 2, 2026
2cc97da
docs(runtime): clarify frontend orchestration boundaries
Eleanor1018 Sep 2, 2026
f1541b0
Merge pull request #17 from Eleanor1018/feature/reformation
Eleanor1018 Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
128 changes: 128 additions & 0 deletions .agents/skills/hhtools-agent/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
name: hhtools-agent
description: "Run local HHTools human-to-humanoid (H2R) retargeting through the versioned MCP Agent interface: discover capabilities, register or inspect allowlisted motion and robot assets, preflight immutable smoke/full plans, pause for calibration, manage jobs, and review verified artifacts. Use for HHTools H2R execution, status, cancellation, retry, or result requests. Do not use for UI or solver-code edits, R2R, Batch, Interaction-Mesh, arbitrary filesystem access, remote service setup, or real-robot deployment."
---

# HHTools Agent

Operate HHTools through its MCP tools and resources while preserving the service's asset,
plan, job, and artifact identities. Treat solver completion and motion quality as separate
claims.

## Choose the workflow

- For a new H2R run, follow the smoke-first workflow below.
- For an asset-only request, discover or register the asset, inspect it, and report the
structured inspection without starting a job.
- For an existing job with a known `job_id`, start with `get_job`; do not recreate its inputs or
submit another job. If an earlier start response was lost, recover only that caller-owned
submission with `lookup_job` using its exact recorded `plan_id` and idempotency key.
- For a status or result request, poll only that job and read only its job-scoped artifacts.
- For cancellation or retry, require an explicit user request and follow the lifecycle rules in
[errors and stops](references/errors-and-stops.md).

If the HHTools MCP tools are unavailable, stop and explain that the local MCP integration must
be configured. Never substitute shell commands, the JSON CLI, REST calls, or direct filesystem
reads. The stdio server owns its service runtime and does not require `hhtools web` to be
running. Only one local runtime may own a given `save_dir`. The separate WebUI is used only
when a returned human `next_action` requests calibration; never request or read its session
token.

## Run a new H2R job

1. Call `get_capabilities`. Confirm the MCP feature, supported formats/backend, scheduler state,
allowlisted `asset_root_ids`, and robot readiness. Do not infer a GPU or backend that the
response does not report.
2. Resolve both content-addressed inputs.
- Prefer `search_assets` for an already registered motion or robot bundle.
- Register only with `register_asset_bundle` using a returned `root_id` and a portable
`relative_path`. Never pass or derive an absolute host path.
- Call `inspect_asset_bundle` with hash verification and parsing enabled for every selected
motion and robot bundle. Stop on `invalid`; surface warnings before continuing.
- Continue only when the motion inspection category is `plain_motion` and neither the
selected nor recommended backend is `interaction_mesh`. Stop on `object_interaction`,
`terrain_scene`, or Interaction-Mesh routing; this skill has no validated workflow for them.
- Select a supported `robot_id` from `list_robots` or the capability snapshot and pair it with
the inspected robot bundle's `asset_id`. Do not guess either identity.
3. Call `preflight_retarget` with a versioned `RetargetPreflightRequest`. Put
`run_mode: smoke` in `request.parameters`, use the currently supported
`output_policy: create_new`, and include the registered motion and robot asset IDs. Other
output policies are rejected in this phase.
4. Branch on the preflight `status`.
- `ready`: retain the returned immutable smoke `plan_id` and continue.
- `human_action_required`: pause and present every entry in `required_actions`. Stop or
disconnect the current stdio MCP runtime, ask the human to start the WebUI with the same
`save_dir`, and present the loopback calibration URL when supplied. After calibration, the
human must close the WebUI before MCP reconnects; then call capabilities again and perform
a new preflight.
- `rejected`: inspect the structured error and checks. Execute an `actor: agent` action only
when it matches the allowlisted action mapping below; otherwise stop and explain it.
5. Generate one caller-owned idempotency key for this logical submission. Call
`start_retarget(request={schema_version: "1.0", plan_id, idempotency_key})`; the nested request
contains only the ready plan identity and key. Persist the exact pair before submission. If the
transport result is ambiguous, call `lookup_job` with that pair before replaying the exact same
start request; never enumerate jobs or create a replacement key.
6. Poll with `get_job(job_id, after_revision=<last revision>)`. Respect `poll_after_ms`; do not
busy-poll. Treat `queued` and `running` as nonterminal, and report queue/progress changes
without requesting large trajectories.
7. At terminal state, use `list_job_artifacts(job_id, ...)` for canonical membership, then read
`hhtools://jobs/{job_id}/artifacts/{artifact_id}` when one descriptor needs verification. Read
`hhtools://jobs/{job_id}/evaluation`, `/manifest`, and `/failures` only when relevant.
Resources expose verified structured reports or descriptors, not binary motion bytes. When the
user asks for an artifact file, call `export_artifact(job_id, artifact_id)`: it verifies and
materializes the file below the fixed `agent-exports` root and returns a portable receipt. Give
the receipt to the user; do not inspect private storage or request bytes in model context.
8. Inspect both `state` and `outcome`. `completed` alone is not quality approval. For a completed
job, present the evaluation and manifest and pause on `review_required`, `partial`, or
`rejected`. For `failed` or `cancelled`, follow the error rules and read failure/manifest
resources only when present.
9. Start a full run only after explicit user approval of the smoke evidence. Perform a new
preflight with `request.parameters.run_mode: full`, receive a different immutable full plan,
and submit it with a new idempotency key. Never promote or mutate the smoke plan.

## Execute allowlisted agent actions

The only automatic preflight recovery mapping is:

| Returned action | MCP operation | Required behavior |
|---|---|---|
| `actor: agent`, `action: register_asset_bundle` | `register_asset_bundle` | Pass `next_action.parameters` unchanged as the tool arguments. It must contain exactly one `request` matching `AssetRegistrationRequest`. Inspect the returned robot bundle, replace `robot_asset_id` with its `asset_id`, and perform a new preflight. |

Do not translate semantic action names, derive a host path, enumerate directories, or repair a
malformed action. If the action name, wrapper shape, `root_id`, or portable `relative_path` does
not validate against the live tool schema, stop and present the contract error.

## Non-negotiable invariants

| ID | Rule |
|---|---|
| `MCP_ONLY` | Use HHTools MCP tools/resources only; never fall back to shell, JSON CLI, REST, or direct service imports. |
| `ALLOWLISTED_ASSETS` | Asset registration accepts only a capability-advertised `root_id` plus normalized `relative_path`, never an arbitrary or absolute path. |
| `PLAIN_H2R_ONLY` | Start new jobs only for inspected `plain_motion` assets on a non-`interaction_mesh` route; stop on object interaction, terrain scenes, or Interaction-Mesh. |
| `PREFLIGHT_OWNS_MODE` | `run_mode` belongs in preflight `request.parameters`; `start_retarget` accepts only `plan_id` and `idempotency_key`. |
| `OUTPUT_CREATE_NEW` | Use `output_policy: create_new`; other output policies are unsupported in the current H2R Agent service. |
| `IDEMPOTENT_START` | Persist the exact plan and idempotency key, recover with `lookup_job`, and replay an ambiguous start only with that same plan and idempotency key; never create a second key for the same logical submission. |
| `IDEMPOTENT_RETRY` | Replay an ambiguous retry with the exact same parent job and retry idempotency key; never create a second child attempt. |
| `NEW_FULL_PLAN` | A full run requires explicit approval, a new full preflight, a new plan, and a new idempotency key. |
| `JOB_SCOPED_ARTIFACTS` | List, resolve, or export an artifact with both `job_id` and `artifact_id`; never trust or expose an unbound artifact identity. |
| `NO_BINARY_CONTEXT` | Keep binary motion, meshes, video, trajectories, and Base64 payloads out of tool arguments and model context; use `export_artifact` and its portable receipt for file delivery. |
| `HUMAN_GATES` | Pause for calibration and quality review; never guess calibration or equate `completed` with accepted motion quality. |
| `COOPERATIVE_CANCEL` | Running cancellation is a request checked at safe points; do not claim cancellation until the returned job state is terminal. |
| `HONEST_PROVENANCE` | Report only device and execution provenance present in capabilities or the manifest; never infer actual GPU use. |
| `SINGLE_RUNTIME_OWNER` | One local runtime may own a `save_dir`: disconnect stdio MCP before same-directory WebUI calibration, close WebUI before reconnecting MCP, then preflight again. |
| `LOCAL_BOUNDARY` | This skill covers local stdio only, with a loopback calibration UI. It provides no remote auth, multi-user isolation, worker resume, or real-robot deployment. |

## Load references progressively

- Read [contracts](references/contracts.md) before constructing an unfamiliar tool request,
selecting a schema resource, or interpreting an artifact.
- Read [errors and stops](references/errors-and-stops.md) for every non-ready preflight,
failed/partial/review-required job, cancellation, retry, hash failure, or ambiguous tool call.

## Report the result

Return a compact audit trail: selected asset IDs and robot ID, run mode and plan ID, job ID and
lineage, final state/outcome, evaluation verdict, canonical artifact IDs with hashes when
available, any artifact export receipt requested by the user, and any remaining human action.
Explicitly label unverified quality, unavailable actual-device provenance, and unsupported remote
or real-robot steps.
4 changes: 4 additions & 0 deletions .agents/skills/hhtools-agent/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "HHTools Agent"
short_description: "Run safe, preflighted HHTools H2R jobs"
default_prompt: "Use $hhtools-agent to preflight an H2R smoke run and stop for review before any full job."
120 changes: 120 additions & 0 deletions .agents/skills/hhtools-agent/references/contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# HHTools Agent contract map

Use the live MCP tool input/output schema as the runtime authority. These repository snapshots
explain the stable Agent v1 documents and are useful when a field, state, or resource is
unfamiliar. Load only the contracts needed for the current step.

The architectural workflow and supported boundaries are documented in the
[Agent integration plan](../../../../docs/agent-integration-plan.md).

## Tool and schema routing

| MCP operation | Request contract | Success contract |
|---|---|---|
| `get_capabilities` | No request document | [capabilities](../../../../docs/schemas/agent/v1/capabilities.schema.json) |
| `list_robots` | No request document | [robot list](../../../../docs/schemas/agent/v1/robot-list-response.schema.json) |
| `register_asset_bundle` | [asset registration request](../../../../docs/schemas/agent/v1/asset-registration-request.schema.json) | [asset bundle](../../../../docs/schemas/agent/v1/asset-bundle.schema.json) |
| `search_assets` | Bounded scalar filters from the live tool schema | [asset search response](../../../../docs/schemas/agent/v1/asset-search-response.schema.json) |
| `inspect_asset_bundle` | `asset_id`, `verify_hashes`, and `parse_content` from the live tool schema | [asset inspection](../../../../docs/schemas/agent/v1/asset-inspection.schema.json) |
| `preflight_retarget` | [retarget preflight request](../../../../docs/schemas/agent/v1/retarget-preflight-request.schema.json) | [preflight response](../../../../docs/schemas/agent/v1/preflight-response.schema.json) |
| `start_retarget` | [job start request](../../../../docs/schemas/agent/v1/job-start-request.schema.json) | [agent job view](../../../../docs/schemas/agent/v1/agent-job-view.schema.json) |
| `lookup_job` | [job lookup request](../../../../docs/schemas/agent/v1/job-lookup-request.schema.json) | [agent job view](../../../../docs/schemas/agent/v1/agent-job-view.schema.json) |
| `get_job` / `cancel_job` | Scalar job identity and live tool fields | [agent job view](../../../../docs/schemas/agent/v1/agent-job-view.schema.json) |
| `retry_job` | [job retry request](../../../../docs/schemas/agent/v1/job-retry-request.schema.json) | [agent job view](../../../../docs/schemas/agent/v1/agent-job-view.schema.json) |
| `list_job_artifacts` | `job_id`, `limit`, and `offset` | [artifact list response](../../../../docs/schemas/agent/v1/artifact-list-response.schema.json) |
| `export_artifact` | Scalar `job_id` and `artifact_id` | [artifact export receipt](../../../../docs/schemas/agent/v1/artifact-export-receipt.schema.json) |

Expected tool failures use the [API error](../../../../docs/schemas/agent/v1/api-error.schema.json)
contract rather than a prose-only exception. Inspect `code`, `retryable`, `stage`, `details`, and
`next_action`; do not recover from the human-readable message alone.

## Executable next-action mapping

`NextAction.action` is executable only when it has an exact mapping in this table:

| `actor` | `action` | Tool | Parameter contract |
|---|---|---|---|
| `agent` | `register_asset_bundle` | `register_asset_bundle` | `parameters` is the complete tool argument object: `{"request": <AssetRegistrationRequest>}`. Pass it unchanged. |

The returned request contains only a capability-advertised `root_id` and normalized
`relative_path`; it never contains the installed preset's host path. After registration, inspect
the returned bundle and rerun preflight with its `asset_id`. An unknown action or malformed
parameter object is a stop condition, not permission to infer another tool or browse a root.

## Read-only resources

Use these exact URI shapes:

```text
hhtools://capabilities
hhtools://schemas/agent/v1/{schema_name}
hhtools://robots/{robot_id}
hhtools://assets/{asset_id}/manifest
hhtools://plans/{plan_id}
hhtools://jobs/{job_id}/status
hhtools://jobs/{job_id}/manifest
hhtools://jobs/{job_id}/evaluation
hhtools://jobs/{job_id}/failures
hhtools://jobs/{job_id}/artifacts/{artifact_id}
```

For the schema resource, `{schema_name}` is the exact registry slug with no filename suffix—for
example, `capabilities` or `job-spec-v2`, never `capabilities.schema.json`.

The report resources validate managed bytes before returning the versioned
[evaluation report](../../../../docs/schemas/agent/v1/evaluation-report.schema.json),
[failure report](../../../../docs/schemas/agent/v1/failure-report.schema.json), or
[job manifest](../../../../docs/schemas/agent/v1/job-manifest.schema.json). The job-scoped
artifact resource returns only a verified
[artifact descriptor](../../../../docs/schemas/agent/v1/artifact.schema.json). It does not stream
binary content.

## Field placement and identity rules

- Operational Agent v1 request and response envelopes use `schema_version: "1.0"` and reject
unknown fields. The audit-only JobSpec v2 embedded in a manifest is the explicit exception and
uses integer `schema_version: 2`.
- `register_asset_bundle` identifies a deployment-owned source with `root_id + relative_path`.
Backslashes, absolute paths, drive paths, `.` segments, and `..` traversal are not portable
registration inputs.
- `asset_id`, `plan_id`, `job_id`, and `artifact_id` are distinct identities. Never derive one
from a display name or host path.
- `run_mode` is `RetargetPreflightRequest.parameters.run_mode`. It is frozen in the returned
plan. [Job start](../../../../docs/schemas/agent/v1/job-start-request.schema.json) has no mode
override.
- Use `output_policy: create_new`. The current PreflightService rejects `overwrite` and
`fail_if_exists` as unsupported rather than treating them as user-selectable alternatives.
- An idempotency key binds one logical start request. Reuse it only with the exact same plan
when delivery of the response is uncertain. Persist that pair before calling `start_retarget`;
`lookup_job` accepts only the exact pair and recovers one submission without listing other jobs.
- `AgentJobView.artifacts` is compact and may contain only the first page. Use
`artifact_count` and `list_job_artifacts` for canonical pagination.
- Every artifact lookup requires the owning `job_id` and `artifact_id`; verify one descriptor by
reading its exact job-scoped resource URI. Binary data is never embedded as Base64.
- `export_artifact` is the MCP file-delivery boundary. It verifies canonical managed bytes, writes
them only below the service-configured `agent-exports` root, and returns a portable
`root_id + relative_path` receipt with size and SHA-256. It accepts no caller-selected host path
and exposes neither the private content-addressed store nor file bytes.

## Audit-only public schemas

The immutable [JobSpec v2](../../../../docs/schemas/agent/v1/job-spec-v2.schema.json), with integer
`schema_version: 2`, appears in the terminal manifest but is not a replacement for preflight. The
public REST/CLI legacy upgrade
contracts—[request](../../../../docs/schemas/agent/v1/legacy-job-upgrade-request.schema.json),
[response](../../../../docs/schemas/agent/v1/legacy-job-upgrade-response.schema.json), and
[receipt](../../../../docs/schemas/agent/v1/legacy-migration-receipt.schema.json)—remain useful for
audit interpretation, but the initial MCP surface has no legacy-upgrade tool. Do not fall back to
the CLI or manufacture a v2 document inside this skill.

## Current boundary

The MCP stdio process assembles the same transport-neutral application services directly; it is
not a REST client and does not need `hhtools web` running. A given `save_dir` has exactly one
local runtime owner. A returned loopback WebUI URL is solely for human calibration: disconnect
the stdio MCP owner, let the human run the WebUI against that same `save_dir`, close the WebUI
after calibration, reconnect MCP, and preflight again. Never request a WebUI session token or run
MCP and Web concurrently against the same directory. There is no authenticated remote MCP
transport, multi-user authorization, cross-process native-worker resume, or guaranteed actual-GPU
provenance in this phase. `lookup_job` can recover the persisted identity and truthful status of a
known submission; it cannot resume interrupted native execution.
Loading
Loading