一键导入
new-operation
Scaffold a new Usd Optimize operation plugin (C++ source, premake, test, guide, optional validator). Use to add a new op or plugin.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Scaffold a new Usd Optimize operation plugin (C++ source, premake, test, guide, optional validator). Use to add a new op or plugin.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Reference for Usd Optimize's validator infrastructure (registration, CLI, logging, REQUIRES_MESH cache). Do not use for ad-hoc validation runs — use run-validators instead.
Build Usd Optimize from source via repo.sh (Linux) or repo.bat (Windows). Use when compiling the repo, switching configs, or selecting a USD flavor.
Diff two USD stages by prim/mesh/vertex/material count, file size, and validator summary. Use for before/after optimization comparisons.
Create a USD proxy mesh sibling. Use to generate decimated, bbox, or LOD stand-ins, with optional render/proxy purpose variant set.
Triage a failing Usd Optimize operation. Use when an op errors, silently no-ops, or returns unexpected output.
Collapse duplicate prim hierarchies into instanceable internal references. Use when deduplicating subtrees or folding repeated prims into prototypes.
| name | new-operation |
| description | Scaffold a new Usd Optimize operation plugin (C++ source, premake, test, guide, optional validator). Use to add a new op or plugin. |
| version | 1.0.0 |
| allowed-tools | Shell, Read, Write, Glob, Grep |
| metadata | {"author":"NVIDIA Corporation","tags":["scaffolding","plugin","development"]} |
Scaffold a complete Usd Optimize operation plugin from scratch. The output is a buildable, testable plugin with all the wiring in place.
Companion docs: PLUGINS.md (full plugin authoring reference),
.agents/operations/_template.md (guide template),
.agents/skills/validators/SKILL.md (validator authoring recipe).
Gather these from the user before scaffolding:
| Input | Required | Example | Notes |
|---|---|---|---|
| Operation key | yes | removeOverlaps | camelCase, used in JSON configs and the Python API. |
| Display name | yes | Remove Overlaps | Title case, shown in UI. |
| Description | yes | Removes overlapping mesh regions | One sentence, shown in UI tooltips. |
| Display group | yes | Geometry | One of: Geometry, Materials, Stage, Utilities. |
| Author | no | Your Name | Defaults to NVIDIA Corporation. |
| Arguments | no | (list of name/type/default/description) | Can be added later. |
| Supports analysis | no | true / false | Whether to scaffold executeAnalysisImpl. Default false. |
| Needs validator | no | true / false | Whether to also scaffold a validator wrapper. Default false. |
If the user only provides a goal (e.g. "I want to detect X"), help them derive the key, display name, and description before proceeding.
| Thing | Convention | Example |
|---|---|---|
| Operation key | camelCase | removeOverlaps |
C++ class (<ClassName>) | PascalCase + Operation suffix | RemoveOverlapsOperation |
C++ file basename (<FileBase>) | PascalCase, typically the class name without the Operation suffix | RemoveOverlaps |
| Source directory | source/operations/<key>/ | source/operations/removeOverlaps/ |
| C++ file | <FileBase>.cpp | RemoveOverlaps.cpp |
| Test file | test_operation_<snake_case>.py | test_operation_remove_overlaps.py |
| Operation guide | .agents/operations/<key>.md | .agents/operations/removeOverlaps.md |
Report category (<CATEGORY>) | UPPER_SNAKE_CASE short identifier | REMOVE_OVERLAPS |
| Validator class | UsdOptimize + PascalCase + Checker | UsdOptimizeRemoveOverlapsChecker |
File-basename convention is a soft rule. Premake auto-discovers any
*.cppundersource/operations/<key>/, so the filename isn't enforced. A handful of existing operations diverge (e.g.fitPrimitives/Primitive.cppforPrimitiveFitOperation,subdivideMeshes/Subdivide.cppforSubdivideOperation). Prefer the convention for new operations; don't rename existing ones just to match.
Create source/operations/<key>/<FileBase>.cpp. Use source/operations/<key>/
as the directory — premake auto-discovers it.
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
#include <usd_optimize/core/Core.h>
#include <usd_optimize/core/Operation.h>
namespace usd_optimize
{
constexpr const char* s_category = "<CATEGORY>";
class <ClassName> : public Operation
{
public:
<ClassName>()
: Operation("<key>", "<Display Name>", "<Description>")
{
// Declare arguments here via addArgument().
// Example:
// addArgument("threshold", "Threshold", kDisplayTypeFloat,
// "Distance threshold in stage units", m_threshold);
}
std::string getAuthor() const override
{
return "<Author>";
}
UsdOptimizePluginVersion getVersion() const override
{
return { 1, 0, 0 };
}
std::string getCategory() const override
{
return s_category;
}
std::string getDisplayGroup() const override
{
return <display_group_constant>;
}
// Uncomment if the operation supports analysis mode:
// bool getSupportsAnalysis() const override { return true; }
protected:
OperationResult executeImpl() override
{
// TODO: implement
return OperationResult::eSuccess;
}
// Uncomment if the operation supports analysis mode:
// OperationResult executeAnalysisImpl() override
// {
// // TODO: implement analysis (read-only inspection)
// return OperationResult::eSuccess;
// }
private:
// Member variables bound to arguments:
// float m_threshold = 0.001f;
};
} // namespace usd_optimize
// Register plugin after the class declaration so this single-file template compiles.
USD_OPTIMIZE_PLUGIN_INIT(usd_optimize::<ClassName>);
Map <display_group_constant> from the user's display group choice:
| Display group | Constant |
|---|---|
| Geometry | s_displayGroupGeometry |
| Materials | s_displayGroupMaterials |
| Stage | s_displayGroupStage |
| Utilities | s_displayGroupUtilities |
getCategory()is not the display group.getCategory()returns an UPPER_SNAKE_CASE report-bucket identifier used for grouping log/report output (e.g. existing operations return"COINCIDING","FIT_PRIMITIVES","SHRINKWRAP","OUTPUT").getDisplayGroup()is a separate concern — it returns one of the fours_displayGroup*constants above and controls UI grouping. Pick a value for each independently; don't substitute one for the other.
If the user provided arguments, add addArgument() calls in the
constructor and corresponding member variables. See PLUGINS.md for
display types, enum arguments, grouping, and further configuration.
If supportsAnalysis is true, uncomment the analysis stubs.
Create source/operations/<key>/premake5.lua:
project_with_location("<key>")
usd_optimize_build.operation_plugin({ "*.cpp" })
This is the standard one-liner. The parent source/operations/premake5.lua
auto-discovers it via os.matchfiles("**premake5.lua").
If the operation needs additional libraries beyond the core SDK, add
links or includedirs calls after operation_plugin. Look at existing
operations (e.g. decimateMeshes, shrinkwrap) for examples of linking
third-party deps.
Create source/tests/test.python/test_operation_<snake_case>.py:
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
from pxr import Usd, UsdGeom
from .test_utils import Test_Operation
class Test_Operation_<PascalCase>(Test_Operation):
OPERATION = "<key>"
async def test_basic(self):
"""Verify the operation runs without error on a trivial stage."""
stage = Usd.Stage.CreateInMemory()
UsdGeom.Xform.Define(stage, "/World")
UsdGeom.Mesh.Define(stage, "/World/Mesh")
# Set up minimal mesh data so the operation has something to work with
mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/World/Mesh"))
mesh.CreatePointsAttr([(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)])
mesh.CreateFaceVertexCountsAttr([4])
mesh.CreateFaceVertexIndicesAttr([0, 1, 2, 3])
_, (success, error, _) = self._execute_command({})
self.assertTrue(success, f"Operation failed: {error}")
The test uses Test_Operation as the base class, which handles stage
caching and teardown. Tests are async by convention (the metaclass wraps
them for sync execution). Use self._execute_command(args_dict) to run
the operation.
For operations that need fixture files, place them in
source/tests/data and load with self._open_stage("fixture.usda").
Copy .agents/operations/_template.md to .agents/operations/<key>.md
and fill in the header:
# <Display Name>
**Key:** `<key>`
**Source:** `source/operations/<key>/<FileBase>.cpp`
Fill in the Parameters table from the addArgument() calls. Leave the
Overview, Tuning Order, Visual Diagnosis, Starting Configs, and Known
Limitations sections with <!-- TODO(developer) --> markers (HTML
comment, literal text TODO(developer) between the comment delimiters)
if the operation logic isn't implemented yet.
Alternatively, use the tune-parameters skill's Guide Authoring Mode
(/tune-parameters create a guide for <key>) to auto-generate the guide
from the C++ source.
Add a row to .agents/operations/INDEX.md in the appropriate position
(sorted by argument count descending):
| <Display Name> | `<key>` | <arg_count> |
If the operation supports analysis mode and a validator is requested,
follow the recipe in .agents/skills/validators/SKILL.md §
"Adding a new performance validator":
source/core/python/usd_optimize/validators/<snake_case>.py
subclassing UsdOptimizeRuleBase.OPERATION_NAME = "<key>" and DEFAULT_ARGS = {<default_args>}._translate(stage, analysis) to convert the analysis JSON
into _AddWarning / _AddFailedCheck calls.REQUIRES_MESH = False if the operation targets hierarchy /
materials / animation rather than meshes.validators/__init__.py._RULE_CATEGORIES tuple in
validators/__init__.py.source/tests/test.python/test_validators_<snake_case>.py.test_validators_smoke.py EXPECTED_RULES tuple../repo.sh build
./repo.sh test -s cpp
./repo.sh test -s python
The python suite covers any test_operation_<snake_case>.py and
test_validators_<snake_case>.py files you added. The repo's Python test
wrapper currently runs the full suite; it does not forward per-file filters to
source/tests/test.python/run_discover.py.
Verify the operation is registered:
# Should print True
python3 -c "from usd_optimize.core import UsdOptimizeCore; print('<key>' in UsdOptimizeCore.getInstance().getOperations())"
PLUGINS.md — full plugin authoring guide (arguments, display types,
enums, groups, analysis mode, registration)..agents/operations/_template.md — operation guide template..agents/operations/INVOCATION.md — how to call operations from Python..agents/skills/validators/SKILL.md — validator infrastructure reference..agents/skills/tune-parameters/SKILL.md — guide authoring mode for
auto-generating the .agents/operations/<key>.md from C++ source.Stand up a complete, buildable, testable operation plugin from
scratch — the C++ source, premake build entry, Python binding test,
operation guide, optional validator wrapper, and the index update.
The output compiles, registers, and runs after ./repo.sh build even
before any operation logic is implemented (the stub executeImpl
returns success).
./repo.sh build or repo.bat build) so the
scaffolded plugin links and its tests can run.source/operations/,
source/tests/test.python/, .agents/operations/.executeImpl() returns eSuccess as a stub. The author wires up
the actual algorithm in a follow-up pass.TODO(developer) wrapped in an HTML comment) until the author fills
them in or runs the tune-parameters Guide Authoring Mode.| Symptom | Likely cause | Fix |
|---|---|---|
error: unknown operation '<key>' after build | Premake didn't pick up the new source/operations/<key>/. | Confirm premake5.lua exists in the new dir; re-run ./repo.sh build --rebuild. |
Plugin builds but getOperations() doesn't list <key> | Missing USD_OPTIMIZE_PLUGIN_INIT(...) macro or wrong namespace. | Ensure the macro at the bottom of the .cpp (after the closing } // namespace usd_optimize line) matches the class's fully-qualified name (see the template in Step 1). |
Test file errors ImportError: test_utils | Test placed in wrong directory. | Tests must live under source/tests/test.python/ (alongside test_utils.py). |
nvidia_usd_validate --help doesn't show the new validator | Validator class not re-exported from validators/__init__.py or not added to _RULE_CATEGORIES. | Complete Step 6 sub-steps 5 & 6 of this skill. |
getCategory() and getDisplayGroup() confused | Category is a report-bucket string; display group is a UI grouping constant. | See the callout in Step 1 — they're independent and use different value spaces. |