Viewer Smoke
iopsystems/rezolus
Run the end-to-end viewer smoke test (tests/viewersmoke.sh).
How to verify luncosim changes end-to-end without asking the user to click.
$ npx skills add LunCoSim/lunco-sim --skill test-via-api -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LunCoSim/lunco-sim test-via-api --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/test-via-api .claude/skills/test-via-api && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "test-via-api" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-api into .claude/skills/test-via-api/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-via-api", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-apiType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LunCoSim/lunco-sim --skill test-via-api -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LunCoSim/lunco-sim test-via-api --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/test-via-api .agents/skills/test-via-api && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "test-via-api" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-api into .agents/skills/test-via-api/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-via-api", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LunCoSim/lunco-sim --skill test-via-api -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LunCoSim/lunco-sim test-via-api --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/test-via-api .cursor/skills/test-via-api && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "test-via-api" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-api into .cursor/skills/test-via-api/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-via-api", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LunCoSim/lunco-sim.git --path skills/test-via-api--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LunCoSim/lunco-sim --skill test-via-api -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LunCoSim/lunco-sim test-via-api --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/test-via-api .gemini/skills/test-via-api && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "test-via-api" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-api into .gemini/skills/test-via-api/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-via-api", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LunCoSim/lunco-sim test-via-apiInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LunCoSim/lunco-sim --skill test-via-api -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/test-via-api .github/skills/test-via-api && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "test-via-api" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-api into .github/skills/test-via-api/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-via-api", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LunCoSim/lunco-sim --skill test-via-api -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LunCoSim/lunco-sim test-via-api --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/test-via-api .opencode/skills/test-via-api && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "test-via-api" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/test-via-api into .opencode/skills/test-via-api/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-via-api", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
test-via-apiHow to verify luncosim changes end-to-end without asking the user to click.
Test Via API is an agent skill from LunCoSim/lunco-sim. How to verify luncosim changes end-to-end without asking the user to click. Trigger whenever a UI flow needs verification — a new diagram, a fix to drill-in, a screenshot to confirm a regression, a smoke test of any reflect-registered Event command. The workbench exposes a small HTTP API on --api PORT; this skill is the runbook for driving it from curl, capturing screenshots, diagnosing failures, and adding new commands when the existing surface isn't enough. Also trigger when you catch yourself about to pkill…
Its SKILL.md is about 7.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering REST APIs, QA and bug reports and Runbooks and postmortems. The repository describes itself as: Collaborative Multiphysics Cosimulator For Space Missions 🌎🚀🌚. The licence is Apache-2.0.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit d1c6f00. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
curljqpythoncargoFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use curl, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Test Via API loads about 7.8k tokens when it runs. Until then it costs about 189 tokens; SKILL.md has 3,331 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LunCoSim/lunco-sim at commit d1c6f00, republished under its Apache-2.0 licence (© LunCoSim). 3,331 words, ~7,756 tokens.
.claude/skills/test-via-api/SKILL.md (or your agent's skills folder).The production luncosim exposes a reflect-registered Event API on
--api PORT (default 4101). Always pass this flag when launching the luncosim, including
visual checks; use another explicit free port if 4101 is occupied. UI verification — diagrams rendering,
drill-ins, simulations, file ops — should be driven from this API
rather than asking the user to click.
Use a headful windowed luncosim session by default whenever the work
concerns a scene, Editor, viewport, UI, motion, layout, or any result the user
needs to watch. Start the production binary with --api PORT and a graphical
display; do not add --no-ui, --offscreen, or another windowless flag. Keep
that window alive while iterating so the user can see each coherent change.
Use --no-ui/luncosim-server only for explicitly numeric or API-only checks
where there is no visual acceptance claim. Use --offscreen only when the user
specifically requests an offscreen recording or a graphics test that is meant
to run without a visible window. If a requested visual check cannot run
headfully, stop and report the display/session blocker instead of silently
falling back to headless mode.
Shader source edits are a live-test path. Keep the production luncosim running, edit the
WGSL under assets/shaders/, then dispatch ReloadShader through the same API. A bare
engine path such as shaders/starfield.wgsl resolves the active default-source or
lunco:// asset identity; an explicit lunco://… or twin://… path is exact. An empty
path reloads every currently loaded WGSL asset, not an arbitrary hard-coded file list.
The response reports the queued paths and fails if no active asset matches. Confirm the
command result, then inspect the unchanged window; shader compiler errors remain in the
render log. Do not relaunch the app just to pick up a shader edit.
For Twin lifecycle regressions, open an editor document in Twin A, replace it
with Twin B, and inspect ListOpenDocuments plus USD preview state. No old
document ID or preview may survive; repeat OpenTwin on B to verify fresh
admission. A rejected Twin path must preserve the current documents. Twin
replacement closes loose/library editor documents as well as Twin-owned files;
RestartScene preserves editable documents and tests a different lifecycle.
Pending editor and workspace-restore work must not recreate old tabs after
replacement. Modelica CloseDocument is owned by the headless core, so exercise
scratch-document closure in both headless and windowed hosts.
The maintained document-close scene gate is
scenes/tests/twin_session_retirement/twin_session_retirement.usda with verdict
channel TWIN_DOCUMENT_CLOSE. Run it through $LUNCOSIM_BIN test. The
gate covers dirty SysML drafts as well as Modelica scratch documents; assert
actual domain retirement rather than only removal from workspace metadata.
The windowed switch/reopen/rejected-candidate gate is
python scripts/api/test_twin_session_retirement.py; set LUNCOSIM_BIN and
an explicit free LUNCOSIM_API_PORT. Its assertions are authored in
assets/scenarios/tests/twin_session_retirement.rhai, and its process wrapper
verifies API Exit and port release.
Tutorial behavior is authored in assets/tutorials/**/*.rhai and should be
tested through its production scene gate in assets/scenes/tests/ with the
observer in assets/scenarios/tests/. After editing either Rhai file, rerun
./scripts/run_scene_tests.sh --no-build --exact <scene-name> for a single
scene, or ./scripts/run_scene_tests.sh --no-build <scene-substring> for a
group; the runner uses four independent headless processes by default, and
-j/--jobs N changes that bound (-j 1 is the serial diagnostic mode). This
does not change each gate process's deterministic --threads 1 --jitter 0, and
graphics assertions remain a separate serial offscreen pass. Do not rebuild the
Rust core for a script-only change. The observer must verify public cmd:*
events plus the resulting live state and emit a real verdict. Parsing or
--validate is only preflight evidence.
The generic model-authoring facades have the same production gate. The focused
fixture is model_authoring:
./scripts/run_scene_tests.sh --no-build --exact model_authoring -j 4Its Rhai observer exercises model_context, readiness_report,
scene_recipe, port_graph, wiring_plan, and publish_component, including
fail-loud missing endpoint, control, asset, identity, and provenance cases.
Use this narrow gate after changing the tool or its authored fixture; a parse
pass alone does not prove the namespaced calls work in production.
The live port-owner collision contract is covered the same way:
./scripts/run_scene_tests.sh --no-build --exact port_owner_collision -j 4Its USD fixture owns the duplicate and clean control cases; the Rhai observer
calls RunLint and verifies the structured LintReport winner, shadowed owner,
property paths, and precedence. Prefer this authored pair for observable lint
behavior instead of embedding USDA or fake backend components in Rust tests.
Public USD query-provider behavior belongs in authored .usda fixtures and
Rhai scene gates, exercised through the production query bridge. Keep Rust
tests for provider internals only when the behavior cannot be observed through
that public surface; do not construct DocumentRegistry worlds with inline
USDA to duplicate inspection, target-resolution, or synchronization behavior.
The usd_query_api gate covers those public contracts, while the assembly
proposal lifecycle gate covers edit-session inspection.
Editor material edits belong in an authored USD fixture plus an editor Rhai
scenario, not a Rust test with a multiline USDA string. The
usd_material_edit_projection fixture exercises typed material edits,
whole-source replacement, and the preview's projected-generation lifecycle
through the production editor runner. Keep Rust coverage for the focused
USD-to-render-intent mapping mechanism, where the mapping itself is the subject.
For source-preview isolation, run scripts/api/test_usd_source_isolation.py
with an exact --scene, --source, composed --selection-path, free --port
and --log. Its RunScenarioAsset invocation supplies all required parameters
to assets/scenarios/tests/usd_source_isolation.rhai and requires eight authored
checks, including invalid-source rejection, unchanged Twin/topology and
advancing physics. --screenshot records the exact viewport/selection context;
the shared ProductionSession.capture_screenshot requires fresh publication
before API Exit. Pair the resulting image with those handles when checking
Prim-tree reveal and highlight.
For spatial safety coverage, keep malformed authored transforms in the USD
projection layer: that layer must reject them before ECS materialization. Test
runtime-state admission at the lunco-usd-avian bridge owner, where a finite
but f32-unrepresentable pose must raise a named RuntimeFaults record and
PhysicsHolds::SAFETY_FAILURE before Avian runs. Test public Raycast and
GroundHeight with a finite but unrepresentable query origin through an
authored production scene; the expected result is {hit:false}, not a
terminal simulation fault. This distinction keeps query-input validation from
masking an engine-state failure and avoids duplicating guards in sensors,
terrain, and vehicle callers.
For terminal runtime-fault recovery, verify the two owners separately and then
the lifecycle seam. RuntimeFaults must pause Time<Physics> with a zero delta
while leaving Time<Virtual> available for diagnostics and teardown. The bad
scene is not repaired or resumed. SceneTeardown clears only the outgoing
scene's terminal fault and PhysicsHolds::SAFETY_FAILURE; the physics owner
also resets scene-owned holds, deliberate-step debt, and the physics clock
before replacement admission. The focused regression names are
terminal_runtime_fault_pauses_physics_until_cleared in lunco-physics and
fault_then_scene_reload_can_admit_a_replacement_runtime in lunco-usd-sim.
The multi-process scene-test runner cannot prove same-process replacement: its expected terminal-fault process exits when the authored verdict is observed. Use a lifecycle test or a live API session that explicitly submits teardown, loads the replacement, and checks the new scene's admission/status. Do not add an automatic repair, retry, process restart, or fault-clearing fallback to make the invalid scene continue.
Scene, render, and editor acceptance runs are isolated by default and use a fresh production process. Their launchers keep settings in memory and disable runtime-overlay reads and writes regardless of Twin policy. The production scene runner fails before scenario start if a file-backed authored USD document is already dirty; runtime setup must not turn a clean fixture into unsaved authored work.
For a one-shot assertion that needs the currently loaded USD stage, use
./scripts/api/run_rhai_test.sh <port> <test.rhai> [probe-prim]. It prepends
the test libraries and delegates to the native luncosim rhai --stdout client,
which calls RunRhai on the existing production session. Editing and rerunning
the test does not restart the app. Use ./scripts/api/run_scenario.sh
when the assertion should remain attached as a persistent observer.
When a test depends on a Twin-scoped Rhai tool, register or reload that library
in the same session first, confirm it with ListToolLibraries/GetToolLibrary,
and make a minimal namespaced call before running the real observer. Discovery
does not prove that the current Rhai engine has rebuilt its static module set.
For a user-requested same-session workflow, use RunRhai or an attached
RunScenario; do not substitute the multi-process scene-test runner.
For an interactive lesson, keep one production session and use
RunScenarioAsset through /api/commands, then inspect the HUD and event
stream. RunScenario is the live hot-reload path for a script attached to an
existing host. Restart only when changing Rust or when a clean scene lifecycle
is itself under test.
To exercise a discrete semantic action, address the target's api_id and send
one SimulateIntentEdge command; do not model a pulse as two API requests:
{
"type": "ExecuteCommand",
"command": "SimulateIntentEdge",
"params": {
"target": 1234,
"intent": "release",
"edge": "pulse",
"producer_id": 4123
}
}The response includes the canonical intent, edge, producer_id,
correlation_id, and command id. Reuse the same nonzero producer_id for
commands from one API producer. API submissions also include admission with
the committed scene generation, effective simulation tick, and per-tick
sequence. Confirm
delivery through the intent.edge telemetry event (source,
value.target_gid, and value.correlation_id identify the same target/action);
its admission fields carry the same stamp. Use the returned correlation_id
for the exact edge's trace, even when the scene emits later edges:
{
"type": "ExecuteCommand",
"command": "CausalTrace",
"params": {"target": 1234, "correlation_id": 5678}
}The response composes the authored binding, selected PortRegistry owner,
USD connection/native-joint admission, current retained measurements, and the
producer's admission stamp. An empty/pending stage is a real incomplete path.
A target-scoped command still passes the normal ownership/authority gate; an
acknowledgement alone does not prove that a consuming Twin policy acted on the
edge.
For a held control, send one SimulateIntent command with held: true or
false and a stable nonzero producer_id, reusing that ID for later commands
from the same API producer. An external command targeting fixed-simulation
state returns a correlation id and next-tick admission stamp; verify the
matching intent.hold event has the same producer, target, held value, and
stamp. The held state changes at that fixed tick. Local-embodiment commands
remain on the interaction cadence.
The native luncosim UI watches the retained runtime surfaces under
assets/ui/. Edit a surface's .html or .css in place and inspect the same
window; HUI rebuilds the affected template and Flair reapplies the stylesheet
without a binary rebuild or relaunch. Editing runtime_surfaces.json rebuilds
the registered surface roots and action bindings. Rust exposure producers and
action observers still require a rebuilt production binary.
Use ReadExposures to verify the data side independently of the pixels:
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H 'content-type: application/json' \
-d '{"type":"ExecuteCommand","command":"ReadExposures","params":{"surface":"driven-vessel"}}' | jq .The response's revision changes only when an exposed value or visibility flag
changes. If it is stable, an unchanged runtime surface should not rebuild its
view-model. Use CaptureScreenshot for the visual check. ReloadShader and
RunScenario reload WGSL and Rhai respectively; neither reloads HTML/CSS.
Runtime UI is a small native HUI/Flair language, not a browser DOM. Do not expect JavaScript, forms, text inputs, full CSS, or host-font fallback. Read the runtime UI skill for the supported surface contract, placement/dock ownership, font rules, and performance gates.
Each agent doing runtime work owns a luncosim session on a distinct explicit free
API port. Concurrent agent sessions are allowed on different ports. Launch from
the same repository checkout and working directory as that agent's terminal,
using that checkout's production binary. Before replacing your own session, send
Exit and verify its process and port are gone; never control another agent's
session or reuse an occupied port. Keep your current process for live shader/Rhai
edits; restart only when a rebuilt binary or an explicit clean session is required.
# 1. Resolve the production binary in this checkout, choose a free API port
# owned by this agent, and start it from this checkout's working directory.
# Keep it alive in the runner's background session.
"$LUNCOSIM_BIN" --api 4101
# 2. Wait for the readiness contract, not just an open socket:
until curl -s http://127.0.0.1:4101/api/ready 2>/dev/null \
| jq -e '.data.ready == true and .data.world_hold == false and .data.pending_count == 0' >/dev/null; do
sleep 1
done
# 3. Send commands (see catalog below).
# 4. Stop with Exit, NEVER pkill / kill (user has to confirm those):
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"Exit","params":{}}'After Exit, verify that the process and :4101 listener are gone before
starting another session. A queued command or a reachable socket is not proof
that a scene is ready; /api/ready is the gate for scene load, Modelica compile
and participant initialization.
For scene replacements that change ActivePhysicsFrame, also query each new
dynamic body with QueryPhysicsState and require physics_pose_seeded == true
before declaring admission complete; this catches a physics clock blocked
before the replacement scene's first pose is written.
Every typed command uses the tagged envelope
{"type":"ExecuteCommand","command":"<Name>","params":{...}}.
Include params even for parameterless commands. Built-in discovery and entity
listing use their own explicit type values.
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"OpenClass","params":{"qualified":"Modelica.Blocks.Continuous.PID"}}'Successful fire-and-forget response: {"data":{"accepted":true}}. A result-returning typed command puts its command-specific payload in the same data envelope. Malformed envelopes are rejected at the transport boundary, and invalid typed parameters return HTTP 422. A deferred command may resolve its acknowledgement on the same request, but that is not necessarily completion of the domain work. RunExperiment returns its exact experiment_id once registered; the numerical solve remains asynchronous and is read through RunStatus and GetExperimentResult using that id. Rhai's in-process cmd may expose a pending command id; command_result(id) resolves that deferred command acknowledgement only. There is no generic HTTP command-id polling endpoint, and callers must not guess the run from its label or newest position.
Choose the command that owns the address type and check its result:
| command | takes | notes |
|---|---|---|
OpenTwin | a folder containing twin.toml | auto-loads [usd] default_scene |
LoadScene | a root-qualified twin:// or lunco:// address | mounts a scene address; it is not a filesystem opener |
OpenFile | a filesystem path or supported URI | extension-routes the document to its owning domain; USD paths resolve their Twin root |
Passing the .usda file to OpenTwin fails the twin.toml check and is
refused with a warn!.
LoadScene is not a general file opener. Bare and absolute filesystem paths
are refused with
[scene] `…` is not a root-qualified scene address — LoadScene takes `lunco://…` or `twin://…`The command returns a terminal rejection before admission; the currently mounted
scene remains active. Read the command result and query the active scene before
trusting a screenshot. Use OpenFile
for a filesystem path; it resolves the workspace layer and preserves the
document-first mounting contract.
CaptureScreenshot returns the PNG as the response body; write those bytes
yourself rather than relying on save_to_file.
ValidateAsset prepares fresh file facts without mounting a scene. Its initial
query returns pending with an operation_id; poll the same query with only
that ID. The consumed ready result contains report and actual
source_revisions; failed contains a terminal diagnostic. Retired or consumed
IDs reject. Do not resubmit the initial path while waiting.
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"ValidateAsset","params":{"path":"lunco://models/LunCo/Electrical/Battery.mo"}}'The native CLI uses the same validators without constructing an app:
"$LUNCOSIM_BIN" --validate assets/models/LunCo/Electrical/Battery.moFull runbook — per-extension checks, exit codes, and the CWD path-resolution
trap: validate-assets.
ValidateTwin is the read-only Twin-wide counterpart. Pass an explicit local
folder and use policy: "error" in CI when a resolver collision must fail:
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"ValidateTwin","params":{"path":"/work/rover-twin","policy":"error"}}'Poll the returned operation_id; ready.report contains indexed entries,
resolver scopes, collisions, source-read errors, and namespace findings. For a
mounted browser Twin pass its current twin://<assigned-authority> instead of
a native folder. For the active Twin after OpenFolder/OpenTwin, use
cmd("RunLint", #{scope: "twin", policy: "warn"}) and read
query("GetDiagnostics", #{scope: "twin"}) for the returned lint revision.
The queued Ack is admission information; the scope's pending/ready/failed state
is the terminal report. Native and mounted browser Twin lint share the same
async preparation. Unreadable or invalid sources fail the scope even with
policy: "warn"; retirement or supersession discards the exact operation.
Loaded-stage lint remains available on both platforms.
This skill owns the generic API envelope, runtime lifecycle, screenshots, and
end-to-end evidence. For Modelica-specific loading, compile/run, experiment,
and plot commands, use run-modelica; keep that
catalog in one place.
1. Start workbench (run_in_background:true).
2. Monitor until READY.
3. OpenFile or OpenClass to load model.
4. Wait ~3-5s for rumoca parse + projection (background tasks).
5. OpenClass or drill action if scoping to a sub-class.
6. Wait ~3-5s for the post-drill projection to land.
7. FitCanvas + sleep 1.
8. CaptureScreenshot → /tmp/foo.png.
9. Read the PNG to inspect.
10. Check the process log for lines like `[Projection] import done in Xms: N nodes M edges`.
11. Exit when done.
## Rover modeling loop: reload the live scene, then measure it
For a world-direction tracker, use the API to verify one complete coordinate
chain after reload: target vector in the mount frame, controller setpoint,
measured joint angle, and rendered boresight. Do not accept a controller's
internal `locked` state alone; it can be self-consistent with an incorrect axis
or boresight convention.
Keep one luncosim process running while iterating on a rover. Edit the USD, then
use `OpenFile` for a file-backed asset, `RestartScene` for the mounted scene, or
`ApplyUsdOp` for an in-place authored opinion. Reattach a diagnostic script with
`RunScenario`; this hot-reloads only that script. Read `ScriptInspect`,
`QueryEntity`, `rover_status`, and relevant ports while the simulation is live.
A rover test must report measured telemetry and movement, not merely compile or
compare two values at rest. Use `luncosim test` for deterministic CI verdicts,
but keep the live API check because it exercises the production reload and
command paths. Do not add a second reload command or a standalone rover test
binary.
For presentation work, establish the acceptance chain in order: builtin
raycast drive first (`DRIVETRAIN PARITY: PASS`), then the Modelica drive-law
overlay (`MODELICA DRIVE LAW: PASS`), then optional power/thermal/autonomy.
Never use a visual screenshot as a substitute for either verdict: a rover that
does not move, or one still driven by the builtin kernel after a failed Modelica
overlay, can look plausible in a parked frame.
Partial USD object/reference reload is intentionally not exposed yet. Until its
composition, connection, and Modelica-worker lifecycle are implemented as one
operation, use the full `RestartScene` reload for rover tests. A successful full
reload must re-run USD prim projection, cosim model creation/compilation, and
connection rewiring before the test verdict is trusted.
For a placed rover, also query the composed USD transform after reload. Check
that every authored rotation op appears in xformOpOrder and that the effective
heading comes from one placement layer. For a fixed solar panel, list the
composed SolarPanel, Battery and rover-root network entities, then read the
rover-root boundary ports. Presence of a panel mesh is not a power verdict: require
positive solar_power/panel power_out, a valid incidence, and battery current
or changing soc.
Tutorial acceptance belongs to the production $LUNCOSIM_BIN binary.
Build that binary in the worktree, run the scene-test command directly, and
capture its exit code and authored verdict. --validate proves only USD
parsing; a successful acknowledgement proves validation and dispatch, not that
the simulation has finished its work. A live API check must also wait for /api/ready to report ready:true,
world_hold:false, and pending_count:0.
Autopilot checks should observe the same AcquireControl and port-write events
as a human control sequence, plus a real movement/port predicate and the final
goal. Keep declared cosim topology separate from current samples: a connection
may resolve before the first sample, but an absent value is not a valid zero.
The complete boundary is in
tutorial-autopilot-and-port-contracts.
For source-backed program authoring, query ListOpenDocuments for the USD
document, dispatch AttachProgram, then verify ListPorts, CosimStatus, and
GetBrokenConnections. The production Rhai gate is:
"$LUNCOSIM_BIN" test \
--scene scenes/tests/program_attach_command.usda --max-ticks 3000It proves both a declared Modelica participant and the visible error status for an attached source with no port contract. Do not treat a prim appearing in the scene tree or a fire-and-forget command acknowledgement as a running model.
InspectActiveDoc → are the components really there in the AST?
If not, parse failed.local_classes_by_short or the source-library palette. The diagram-builder
registers the target's nested + sibling classes (sibling-pass in
panels/canvas_projection.rs, the local_classes_by_short
registration); connector types need to be in
library_index.json (regenerate via
cargo run -p lunco-modelica-assets --bin modelica_library_indexer).lunco-modelica-ui-core; keep its observer in the owning UI package, give
its observer the #[on_command(X)] attribute, and list that observer in the
register_commands!(...) block in
crates/lunco-modelica-ui/src/ui/commands/mod.rs (see § Add a command).params includes the
empty object {} even for parameterless commands.std::thread::spawn and use the cache-only source-aware resolver
in the projection (peek_class_cached).Exit, verify
port 4101 is free, then start the rebuilt production binary.When testing reveals a missing API surface, add the command immediately rather than asking the user:
lunco-modelica-ui-core, or shared scene-edit payloads in
lunco-scene-command-contracts). Define it with #[Command]. Keep the
observer in the behavior-owning package and mark it with #[on_command(...)]
(both attributes come from lunco_core). For the Modelica UI, the observer
file is under crates/lunco-modelica-ui/src/ui/commands/:use lunco_core::{Command, on_command};
#[Command(default)] // or `#[Command]` if you impl Default
pub struct MyCommand { pub foo: String }
#[on_command(MyCommand)]
pub fn on_my_command(trigger: On<MyCommand>, mut commands: Commands) {
let foo = trigger.event().foo.clone();
commands.queue(move |world: &mut World| { /* ... */ });
}#[Command] emits the Event/Reflect/reflect(Event) derives and
#[on_command] generates the register_type + add_observer wiring —
you don't write them by hand.register_commands!(...) list in
crates/lunco-modelica-ui/src/ui/commands/mod.rs (use the
module::fn path form, e.g. inspect::on_my_command).pkill -f lunica. The user has to confirm; use
Exit command..rs files to verify
rumoca behaviour. Add an Inspect* command if the workbench can't
already surface what you need.sleep 30 && tail .... Use Monitor with an until loop.InjectWindowInput distinguishes absolute PointerMove { x, y } from raw
relative MouseMotion { delta_x, delta_y }. Cursor coordinates drive picking
and egui; raw motion drives the native camera input map. For mouse look, hold
the configured input_binding("look_button"), emit raw motion, and release the
button. Cursor positioning alone does not rotate a camera. The bridge emits
both the native WindowEvent::MouseMotion and typed Bevy MouseMotion message.
For path interoperability, run the production twin_search_paths scene gate:
it exercises layer/Twin search precedence and imports, tool discovery, and
timeline discovery with literal #, %, and spaces in filenames. Distinguish
Linux runtime evidence from Windows-native CI tests. Root resolution and
application builders are fallible; an invalid LUNCO_ASSET_ROOT must exit with
a diagnostic rather than panic or silently discover another library.
python scripts/api/test_path_interoperability.py uses an owned windowed
production session on LUNCOSIM_API_PORT (default 4193) and a fresh temporary
Twin below target/. Its Rhai observer verifies Modelica documents through
literal filenames, canonical-root and case-only renames, rejected existing or
nonportable targets, and save/readback at the renamed path. It authors a USD
document through typed document operations, saves it with a literal filename,
and admits it through the Twin's default scene to verify its Modelica source
equation and loaded canonical stage. API Exit must release both the process
and port.
© LunCoSim, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/test-via-api of LunCoSim/lunco-sim.
Open the folder on GitHubat commit d1c6f00
Test Via API next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Test Via API this skillLunCoSim/lunco-sim | 105 | — | ~7.8k | Automated safety check: Pass | Apache-2.0 | |
| Viewer Smokeiopsystems/rezolus | 275 | — | ~849 | Automated safety check: Pass | Custom licence | |
| Fleet SupervisorApra-Labs/apra-fleet | 101 | — | ~3.6k | Automated safety check: Pass | Custom licence | |
| QA Metricspetrkindlmann/qa-skills | 165 | — | ~5.3k | Automated safety check: Pass | MIT | |
| Use Yaakmountain-loop/yaak | 19k | — | ~1.9k | Automated safety check: Pass | MIT | |
| Testing Mwaa Workflowaws/agent-toolkit-for-aws | 2.8k | — | ~3.8k | Automated safety check: Pass | Apache-2.0 |
iopsystems/rezolus
Run the end-to-end viewer smoke test (tests/viewersmoke.sh).
Apra-Labs/apra-fleet
How to start/smoke-test the supervisor process itself, and start, check, and kill fleet-sprints via its HTTP API only (POST /api/sprints on localhost:8787).
petrkindlmann/qa-skills
Define, track, and act on QA metrics: test coverage percentage, flakiness rate, defect escape rate, MTTR, test execution time trends, automation ROI, quality gates, and SLAs for test suites.
mountain-loop/yaak
A skill your agent uses when the user mentions Yaak, a Yaak workspace, or the yaak command, or asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API requests for reuse or manual…
aws/agent-toolkit-for-aws
Tests Amazon MWAA workflow execution end-to-end: trigger a run and monitor it to completion for Provisioned (Python DAG, via Airflow REST API) and Serverless (YAML workflow, via StartWorkflowRun).
CALLE-AI/awesome-phone-call-agents
Monitor business phone lines and deployed voice agents with LineCanary — scheduled CALL-E test calls that walk the caller journey, assert structured results, diff against baselines and alert on…
LunCoSim/lunco-sim
Generate concise LunCoSim nightly GitHub release notes with platform downloads, installation guidance, an AI-agent mission prompt, and a changelog link.
LunCoSim/lunco-sim
Build or repair a reusable scene component through a live LunCoSim Editor session.
LunCoSim/lunco-sim
Build or review a componentized LunCoSim USD assembly with a realistic, dimensionally checkable presentation.
LunCoSim/lunco-sim
Author and review LunCoSim behavioral, asset-backed, component, mission, visual, and requirements-verification tests.
LunCoSim/lunco-sim
Create, extend, register, or debug a reusable LunCoSim Rhai tool library for live USD authoring, component linting, inspection, or test support.
LunCoSim/lunco-sim
Author an interactive tutorial, guided lesson, onboarding flow, coach-mark tour, or objectives checklist in LunCoSim.
Categories
How to verify luncosim changes end-to-end without asking the user to click. Test Via API is an agent skill from LunCoSim/lunco-sim. How to verify luncosim changes end-to-end without asking the user to click.
Test Via API fits situations like: ever a UI flow needs verification — a new diagram; A fix to drill-in; A screenshot to confirm a regression; A smoke test of any reflect-registered Event command.
Run `npx skills add LunCoSim/lunco-sim --skill test-via-api -a claude-code`. Or copy the skill folder (skills/test-via-api in LunCoSim/lunco-sim) into .claude/skills/test-via-api in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LunCoSim/lunco-sim --skill test-via-api -a codex`. Or copy the skill folder (skills/test-via-api in LunCoSim/lunco-sim) into .agents/skills/test-via-api in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LunCoSim/lunco-sim --skill test-via-api -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/test-via-api, .gemini/skills/test-via-api, .github/skills/test-via-api and .opencode/skills/test-via-api in your project.
Going by SKILL.md and its folder, Test Via API needs the command-line tools its instructions call (curl, jq, python and cargo). Our summary lists: Python 3.
SKILL.md contains no URLs. Its commands use curl, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Test Via API is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.8k tokens (SKILL.md is roughly 31k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Test Via API: Viewer Smoke (iopsystems/rezolus, 275 stars), Fleet Supervisor (Apra-Labs/apra-fleet, 101 stars), QA Metrics (petrkindlmann/qa-skills, 165 stars) and Use Yaak (mountain-loop/yaak, 19k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LunCoSim (a GitHub organization) maintains it in LunCoSim/lunco-sim, which has 105 GitHub stars. The repository holds 38 skills in this directory. The repository was last updated on October 7, 2026.
Source: LunCoSim/lunco-sim on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.