[{"data":1,"prerenderedAt":24},["ShallowReactive",2],{"se-doc-create-project":3},{"html":4,"toc":5},"\u003Ch1>Create a SimEngine project\u003C/h1>\n\u003Cp>This skill ships with the SimEngine \u003Ccode>first_scene\u003C/code> example. It drives only\nSimEngine’s public tools: the \u003Ccode>simengine_host\u003C/code> scenario CLI, the \u003Ccode>simengine_capture\u003C/code>\noffscreen renderer and the example driver \u003Ccode>examples/first_scene/first_scene.py\u003C/code>, which\ncalls those two executables in separate processes and verifies what they write.\u003C/p>\n\u003Ch2 id=\"compatible-versions\">Compatible versions\u003C/h2>\n\u003Cp>Written for, and verified against, a SimEngine build that reports:\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Interface\u003C/th>\n\u003Cth>Version\u003C/th>\n\u003Cth>Where it is reported\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Scenario schema \u003Ccode>simengine.scenario\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>schema_version\u003C/code> 1\u003C/td>\n\u003Ctd>\u003Ccode>simengine_host --capabilities\u003C/code> → \u003Ccode>capabilities.scenario_schema.schema_version\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Capability document \u003Ccode>simengine.capabilities\u003C/code>\u003C/td>\n\u003Ctd>1\u003C/td>\n\u003Ctd>\u003Ccode>capabilities.schema_version\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Scene state \u003Ccode>simengine.scene_state\u003C/code>\u003C/td>\n\u003Ctd>1\u003C/td>\n\u003Ctd>\u003Ccode>capabilities.state_schema.schema_version\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Simulation (module extension) contract\u003C/td>\n\u003Ctd>1\u003C/td>\n\u003Ctd>\u003Ccode>capabilities.simulation_contract_version\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Module contract\u003C/td>\n\u003Ctd>1\u003C/td>\n\u003Ctd>\u003Ccode>simengine_host --report\u003C/code> → \u003Ccode>runtime.modules.registry.contract_version\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Scene / asset text formats\u003C/td>\n\u003Ctd>\u003Ccode>simengine_scene 1\u003C/code>, \u003Ccode>simengine_asset 1\u003C/code>\u003C/td>\n\u003Ctd>first line of \u003Ccode>.sescene\u003C/code> / \u003Ccode>.seasset\u003C/code> files\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Capture manifest \u003Ccode>simengine.capture.manifest\u003C/code>\u003C/td>\n\u003Ctd>1\u003C/td>\n\u003Ctd>\u003Ccode>simengine_capture --version\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Example driver / project file\u003C/td>\n\u003Ctd>driver 1, \u003Ccode>simengine.example_project\u003C/code> 1\u003C/td>\n\u003Ctd>\u003Ccode>first_scene.py\u003C/code>, \u003Ccode>project.json\u003C/code>\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Cp>The driver checks every one of these before it runs anything and stops with\n\u003Ccode>incompatible_engine\u003C/code> (exit 21) on a mismatch. Do not work around that: the skill is\nout of date for that engine.\u003C/p>\n\u003Ch2 id=\"what-simengine-can-do-today-and-what-it-cannot\">What SimEngine can do today (and what it cannot)\u003C/h2>\n\u003Cp>Can: run a deterministic, seeded, headless scenario of point entities in one Cartesian\nframe (positions in meters, yaw orientations, scheduled \u003Ccode>simengine.entity.set_position\u003C/code>\ncommands, seeded \u003Ccode>scatter_box\u003C/code> placement, end-of-run expectations), and render a static\nscene offscreen with a small PBR material subset to a PNG plus a JSON manifest.\u003C/p>\n\u003Cp>Cannot (do not promise or attempt it): a window or interactive camera, keyboard/mouse\ninput, physics, collisions or contacts, audio, a game loop, textures or normal maps,\nglTF import, local lights or shadows. Motion without the optional \u003Ccode>point_mass\u003C/code> module\nis a sequence of scheduled teleports.\u003C/p>\n\u003Ch2 id=\"before-you-start\">Before you start\u003C/h2>\n\u003Cp>You need a built SimEngine checkout. If \u003Ccode>build/linux-release/apps/host/simengine_host\u003C/code>\ndoes not exist yet, run the setup script first (\u003Ccode>./tools/setup.sh\u003C/code> on Linux,\n\u003Ccode>tools/setup.ps1\u003C/code> on Windows) and report its result.\u003C/p>\n\u003Cp>The commands below use three variables. Shell tools often do not keep variables between\ncalls: prefix each command with the assignments, or substitute absolute paths.\u003C/p>\n\u003Cpre class=\"code\" data-lang=\"text\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">text\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-var\">SIMENGINE_ROOT\u003C/span>=\u003Cspan class=\"tk-str\">/absolute/path/to/SimEngine\u003C/span>          \u003Cspan class=\"tk-cmd\">#\u003C/span> the checkout\n\u003Cspan class=\"tk-var\">SIMENGINE_BUILD\u003C/span>=\u003Cspan class=\"tk-str\">$SIMENGINE_ROOT/build/linux-release\u003C/span>  \u003Cspan class=\"tk-cmd\">#\u003C/span> what tools/setup.sh builds\n\u003Cspan class=\"tk-var\">PROJECT\u003C/span>=\u003Cspan class=\"tk-str\">/absolute/path/to/my_first_scene\u003C/span>             \u003Cspan class=\"tk-cmd\">#\u003C/span> a \u003Cspan class=\"tk-ph\">NEW\u003C/span> directory, outside the checkout\u003C/code>\u003C/pre>\n\u003Cp>Use \u003Ccode>python\u003C/code> instead of \u003Ccode>python3\u003C/code> where that is the Python 3 interpreter (Windows).\u003C/p>\n\u003Ch2 id=\"steps\">Steps\u003C/h2>\n\u003Col>\n\u003Cli>Discover what this build can do. Read \u003Ccode>capabilities.commands\u003C/code>, \u003Ccode>capabilities.components\u003C/code>\nand \u003Ccode>capabilities.modules\u003C/code>: a core-only build has one command\n(\u003Ccode>simengine.entity.set_position\u003C/code>) and no components or modules.\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">\"$SIMENGINE_BUILD/apps/host/simengine_host\"\u003C/span> \u003Cspan class=\"tk-flag\">--capabilities\u003C/span> \u003Cspan class=\"tk-punc\">&gt;\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD/capabilities.json\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-flag\">-c\u003C/span> \u003Cspan class=\"tk-str\">\"import json,sys; c=json.load(open(sys.argv[1]))['capabilities']; print('scenario schema', c['scenario_schema']['schema_version'], '| commands', [x['id'] for x in c['commands']], '| modules', [m['id'] for m in c['modules']])\"\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD/capabilities.json\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Create the project. \u003Ccode>new\u003C/code> copies the example scene, scenarios, assets and these\nskills (into \u003Ccode>$PROJECT/.claude/skills/\u003C/code>) and prints one JSON line (\u003Ccode>outcome\u003C/code>,\n\u003Ccode>files\u003C/code>, \u003Ccode>next\u003C/code>).\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> new \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Check it without a GPU: engine compatibility, scene import path, scenario validation.\nExpect \u003Ccode>&quot;outcome&quot;: &quot;PASS&quot;\u003C/code> and exit code 0.\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> check \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"4\">\n\u003Cli>Run the whole journey: two deterministic runs, the scene posed from the initial and\nfinal simulation states, three offscreen captures (two viewpoints), verification and\n\u003Ccode>manifest.json\u003C/code> under \u003Ccode>$PROJECT/runs/main-NNN/\u003C/code>.\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> run \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"5\">\n\u003Cli>Verify it independently from the files it wrote (hashes, PNG decode, sidecars).\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> verify \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"verify-what-you-produced\">Verify what you produced\u003C/h2>\n\u003Cp>Report these to the user, from the \u003Ccode>run\u003C/code> and \u003Ccode>verify\u003C/code> JSON lines, not from memory:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>outcome\u003C/code> is \u003Ccode>PASS\u003C/code> and the exit code is 0 for \u003Ccode>check\u003C/code>, \u003Ccode>run\u003C/code> and \u003Ccode>verify\u003C/code>;\u003C/li>\n\u003Cli>\u003Ccode>expectations\u003C/code>: 3 passed, 0 failed; \u003Ccode>final_state_sha256\u003C/code> (64 hex characters);\u003C/li>\n\u003Cli>\u003Ccode>checks.deterministic_repeat\u003C/code> and \u003Ccode>checks.motion_visible\u003C/code> are \u003Ccode>PASS\u003C/code>;\u003C/li>\n\u003Cli>three PNGs under \u003Ccode>runs/main-NNN/captures/\u003C/code> (\u003Ccode>initial-front\u003C/code>, \u003Ccode>final-front\u003C/code>,\n\u003Ccode>final-side\u003C/code>). Open \u003Ccode>final-front\u003C/code> and look at it: a table with a red ball on it, two\nstacked crates, three barrels on a checkered ground.\u003C/li>\n\u003C/ul>\n\u003Cp>If the exit code is 77 (\u003Ccode>BLOCKED_ENVIRONMENT\u003C/code>), the machine has no usable Vulkan device:\nthe simulation was verified but nothing was rendered. Say so; it is not a pass.\u003C/p>\n\u003Ch2 id=\"on-failure\">On failure\u003C/h2>\n\u003Cp>The driver prints \u003Ccode>failure.code\u003C/code>, \u003Ccode>failure.step\u003C/code>, \u003Ccode>failure.message\u003C/code> and a \u003Ccode>failure.hint\u003C/code>.\nQuote them verbatim. Then:\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Exit\u003C/th>\n\u003Cth>\u003Ccode>failure.code\u003C/code>\u003C/th>\n\u003Cth>Do this\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>20\u003C/td>\n\u003Ctd>\u003Ccode>build_not_found\u003C/code>\u003C/td>\n\u003Ctd>Run the setup script, or pass the build directory that contains \u003Ccode>apps/host\u003C/code> and \u003Ccode>apps/capture\u003C/code>.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>21\u003C/td>\n\u003Ctd>\u003Ccode>incompatible_engine\u003C/code>\u003C/td>\n\u003Ctd>Stop. Host and capture come from different builds, or the engine changed a version this skill was written for. Report it.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>22\u003C/td>\n\u003Ctd>\u003Ccode>module_missing\u003C/code>\u003C/td>\n\u003Ctd>The scenario needs an optional module. Use a build configured with \u003Ccode>-DSIMENGINE_MODULES=&lt;id&gt;\u003C/code> or pick a core-only scenario.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>23\u003C/td>\n\u003Ctd>\u003Ccode>scenario_invalid\u003C/code>\u003C/td>\n\u003Ctd>Use \u003Ccode>simengine-modify-scene\u003C/code>: fix each \u003Ccode>failure.detail.errors[]\u003C/code> entry at its JSON pointer \u003Ccode>path\u003C/code>.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>24\u003C/td>\n\u003Ctd>\u003Ccode>scene_invalid\u003C/code>\u003C/td>\n\u003Ctd>Fix the \u003Ccode>.sescene\u003C/code>/\u003Ccode>.seasset\u003C/code> line in \u003Ccode>failure.detail\u003C/code> (\u003Ccode>code\u003C/code>, \u003Ccode>file\u003C/code>, \u003Ccode>line\u003C/code>).\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>31\u003C/td>\n\u003Ctd>\u003Ccode>project_invalid\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>$PROJECT\u003C/code> already exists and is not empty, or \u003Ccode>project.json\u003C/code> is malformed. Choose a new directory.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>other\u003C/td>\n\u003Ctd>see \u003Ccode>simengine-run-capture-diagnose\u003C/code>\u003C/td>\n\u003Ctd>\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Cp>Never edit engine sources, tests or the example’s files under \u003Ccode>$SIMENGINE_ROOT\u003C/code> to make\na journey pass; change only the project.\u003C/p>\n",[6,9,12,15,18,21],{"id":7,"text":8},"compatible-versions","Compatible versions",{"id":10,"text":11},"what-simengine-can-do-today-and-what-it-cannot","What SimEngine can do today (and what it cannot)",{"id":13,"text":14},"before-you-start","Before you start",{"id":16,"text":17},"steps","Steps",{"id":19,"text":20},"verify-what-you-produced","Verify what you produced",{"id":22,"text":23},"on-failure","On failure",1793299074004]