[{"data":1,"prerenderedAt":24},["ShallowReactive",2],{"se-doc-run-capture-diagnose":3},{"html":4,"toc":5},"\u003Ch1>Run, capture and diagnose\u003C/h1>\n\u003Cp>This skill ships with the SimEngine \u003Ccode>first_scene\u003C/code> example. It uses only public\ntools: \u003Ccode>simengine_host\u003C/code> (headless scenario CLI), \u003Ccode>simengine_capture\u003C/code> (offscreen render\nand PNG), \u003Ccode>tools/run_scenario.py\u003C/code> (out-of-process run supervisor) and\n\u003Ccode>examples/first_scene/first_scene.py\u003C/code> (the example driver that chains them and\nverifies what they write).\u003C/p>\n\u003Ch2 id=\"compatible-versions\">Compatible versions\u003C/h2>\n\u003Cp>Scenario schema \u003Ccode>simengine.scenario\u003C/code> \u003Cstrong>schema_version 1\u003C/strong>, capabilities 1, scene state 1,\nhost result \u003Ccode>simengine.host.result\u003C/code> 1, simulation contract 1, module contract 1, capture\nmanifest \u003Ccode>simengine.capture.manifest\u003C/code> 1, scene/asset formats 1, example driver 1 and\n\u003Ccode>simengine.example_manifest\u003C/code> 1. Exit codes below are the ones those versions document\n(\u003Ccode>simengine_host --help\u003C/code>, \u003Ccode>simengine_capture --help\u003C/code>, \u003Ccode>first_scene.py --help\u003C/code>).\u003C/p>\n\u003Ch2 id=\"variables\">Variables\u003C/h2>\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-cmd\">SIMENGINE_ROOT=/absolute/path/to/SimEngine\u003C/span>\n\u003Cspan class=\"tk-cmd\">SIMENGINE_BUILD=$SIMENGINE_ROOT/build/linux-release\u003C/span>\n\u003Cspan class=\"tk-cmd\">PROJECT=/absolute/path/to/my_first_scene\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Prefix each command with them if your shell tool does not keep variables between calls.\u003C/p>\n\u003Ch2 id=\"run\">Run\u003C/h2>\n\u003Cp>The full journey (two runs, posing, three captures, verification), then an independent\nre-verification from the files:\u003C/p>\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>\n\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\u003Cp>Simulation only (no GPU needed; the render check is reported \u003Ccode>NOT_RUN\u003C/code>, never passed, and a\nlater \u003Ccode>verify\u003C/code> of that run reports \u003Ccode>&quot;render&quot;: &quot;NOT_RUN&quot;\u003C/code>):\u003C/p>\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> \u003Cspan class=\"tk-flag\">--skip-capture\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Each \u003Ccode>run\u003C/code> prints one JSON line (\u003Ccode>simengine.example_result\u003C/code>: \u003Ccode>outcome\u003C/code>, \u003Ccode>exit_code\u003C/code>,\n\u003Ccode>failure\u003C/code>, \u003Ccode>final_state_sha256\u003C/code>, \u003Ccode>expectations\u003C/code>, \u003Ccode>captures\u003C/code>, \u003Ccode>checks\u003C/code>) and writes\n\u003Ccode>$PROJECT/runs/&lt;scenario&gt;-NNN/\u003C/code>:\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Path\u003C/th>\n\u003Cth>Content\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>manifest.json\u003C/code>\u003C/td>\n\u003Ctd>The build/run/capture manifest: build identity and CMake settings, dependency graph, enabled and disabled modules with absence checks, every step (argv, exit code, wall time, peak RSS where the OS reports it), simulation digests and expectations, posing, captures, checks, warnings, \u003Ccode>not_covered\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>logs/NN-&lt;step&gt;.stdout\u003C/code> / \u003Ccode>.stderr\u003C/code>\u003C/td>\n\u003Ctd>each engine process’s JSON result and its JSON Lines diagnostics\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>run-1/\u003C/code>, \u003Ccode>run-2/\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>simengine_host --run\u003C/code> artifacts: \u003Ccode>scenario.json\u003C/code>, \u003Ccode>initial_state.json\u003C/code>, \u003Ccode>final_state.json\u003C/code>, \u003Ccode>trace.jsonl\u003C/code>, \u003Ccode>result.json\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>scenes/&lt;pose&gt;-&lt;view&gt;.sescene\u003C/code>\u003C/td>\n\u003Ctd>the scene posed from a simulation state\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>captures/&lt;pose&gt;-&lt;view&gt;/\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>&lt;scene_id&gt;.png\u003C/code> and \u003Ccode>&lt;scene_id&gt;.capture.json\u003C/code> (device, timings, validation, content check)\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Cp>Look at the PNGs yourself; a passing content check only means the image is not black or\nempty.\u003C/p>\n\u003Ch2 id=\"use-the-engine-tools-directly\">Use the engine tools directly\u003C/h2>\n\u003Cp>When you need more detail than the driver gives, call the same tools it calls. Each\nprints one JSON document on stdout (also on failure) and JSON Lines diagnostics on stderr.\u003C/p>\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\">--load\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/scenario.json\"\u003C/span> \u003Cspan class=\"tk-punc\">&gt;\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs/load.json\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">\"$SIMENGINE_BUILD/apps/capture/simengine_capture\"\u003C/span> \u003Cspan class=\"tk-flag\">--check-scene\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/scene.sescene\"\u003C/span> \u003Cspan class=\"tk-punc\">&gt;\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs/check-scene.json\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/tools/run_scenario.py\"\u003C/span> \u003Cspan class=\"tk-flag\">--host\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD/apps/host/simengine_host\"\u003C/span> \u003Cspan class=\"tk-flag\">--scenario\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/scenario.json\"\u003C/span> \u003Cspan class=\"tk-flag\">--out\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs/supervised-$(date +%Y%m%d%H%M%S)\"\u003C/span> \u003Cspan class=\"tk-flag\">--timeout\u003C/span> 60\u003C/code>\u003C/pre>\n\u003Cp>\u003Ccode>run_scenario.py\u003C/code> classifies the outcome (\u003Ccode>completed\u003C/code>, \u003Ccode>invalid\u003C/code>, \u003Ccode>timeout\u003C/code>,\n\u003Ccode>expectation_failed\u003C/code>, \u003Ccode>fault\u003C/code>, \u003Ccode>crash\u003C/code>, \u003Ccode>supervisor_timeout\u003C/code>, …) even when the host\ncrashes. \u003Ccode>simengine_host --run FILE --out NEW_DIR --trace-every 1\u003C/code> records a state digest\nper tick to find the first tick where two runs diverge. \u003Ccode>simengine_host --report\u003C/code> shows\nthe Vulkan device and the module registry.\u003C/p>\n\u003Ch2 id=\"diagnose-exit-codes-and-what-to-do\">Diagnose: exit codes and what to do\u003C/h2>\n\u003Cp>\u003Ccode>first_scene.py\u003C/code> (\u003Ccode>failure.code\u003C/code>; \u003Ccode>failure.hint\u003C/code> repeats the action):\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Exit\u003C/th>\n\u003Cth>Code\u003C/th>\n\u003Cth>Meaning → action\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>0\u003C/td>\n\u003Ctd>—\u003C/td>\n\u003Ctd>Everything passed. Report digests, expectations and PNG paths.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>1\u003C/td>\n\u003Ctd>\u003Ccode>internal_error\u003C/code>\u003C/td>\n\u003Ctd>Driver defect → keep the run directory, report it with the message.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>2\u003C/td>\n\u003Ctd>\u003Ccode>usage_error\u003C/code>\u003C/td>\n\u003Ctd>Fix the command line (\u003Ccode>first_scene.py --help\u003C/code>).\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>20\u003C/td>\n\u003Ctd>\u003Ccode>build_not_found\u003C/code>\u003C/td>\n\u003Ctd>Build first (\u003Ccode>tools/setup.sh\u003C/code> / \u003Ccode>tools/setup.ps1\u003C/code>), or fix \u003Ccode>--build\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>Different builds for host and capture, or a version this skill does not know → stop and report.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>22\u003C/td>\n\u003Ctd>\u003Ccode>module_missing\u003C/code>\u003C/td>\n\u003Ctd>Scenario needs an optional module → build with \u003Ccode>-DSIMENGINE_MODULES=&lt;id&gt;\u003C/code> or use 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>\u003Ccode>failure.detail.errors[]\u003C/code>: fix each at its JSON pointer \u003Ccode>path\u003C/code> (\u003Ccode>line\u003C/code>, \u003Ccode>column\u003C/code>, \u003Ccode>expected\u003C/code>, \u003Ccode>found\u003C/code>). Nothing ran.\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 scene/asset 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>25\u003C/td>\n\u003Ctd>\u003Ccode>pose_mapping_failed\u003C/code>\u003C/td>\n\u003Ctd>Entities without a same-named scene instance, a non-\u003Ccode>+y\u003C/code> frame or a non-yaw orientation → fix the project.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>26\u003C/td>\n\u003Ctd>\u003Ccode>run_failed\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>failure.detail.host_exit_code\u003C/code>: 11 timeout (fewer ticks or a larger \u003Ccode>--timeout\u003C/code>), 13 I/O, 14 \u003Ccode>simulation_fault\u003C/code> (non-finite state; rolled back), 15 module startup, negative = crash → report crashes.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>27\u003C/td>\n\u003Ctd>\u003Ccode>expectation_failed\u003C/code>\u003C/td>\n\u003Ctd>Compare \u003Ccode>failure.detail.failed[].expected\u003C/code> with \u003Ccode>.actual\u003C/code>; fix the command or the expectation, never the tolerance alone.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>28\u003C/td>\n\u003Ctd>\u003Ccode>nondeterministic\u003C/code>\u003C/td>\n\u003Ctd>Same build, same input, different digests: an engine defect → keep both run directories and report.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>29\u003C/td>\n\u003Ctd>\u003Ccode>capture_failed\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>failure.detail.error.code\u003C/code>: \u003Ccode>validation_errors\u003C/code> (8) or \u003Ccode>render_failed\u003C/code> (11) → engine defect, report; \u003Ccode>capture_content_invalid\u003C/code> (12) → the camera sees nothing, fix camera/target.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>30\u003C/td>\n\u003Ctd>\u003Ccode>capture_check_failed\u003C/code>\u003C/td>\n\u003Ctd>PNG or manifest does not verify independently → report; do not regenerate silently.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>31\u003C/td>\n\u003Ctd>\u003Ccode>project_invalid\u003C/code>\u003C/td>\n\u003Ctd>Malformed \u003Ccode>project.json\u003C/code> or a non-empty \u003Ccode>--out\u003C/code> directory.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>77\u003C/td>\n\u003Ctd>\u003Ccode>blocked_environment\u003C/code>\u003C/td>\n\u003Ctd>No usable Vulkan 1.3 device (capture exit 3–6). Simulation verified; rendering \u003Ccode>BLOCKED_ENVIRONMENT\u003C/code>, not passed. Install a GPU driver or Mesa lavapipe.\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Cp>\u003Ccode>simengine_host\u003C/code> exit codes (in \u003Ccode>logs/*.stdout\u003C/code>, \u003Ccode>error.code\u003C/code>): 2 \u003Ccode>usage_error\u003C/code>,\n10 \u003Ccode>scenario_invalid\u003C/code>, 11 \u003Ccode>scenario_timeout\u003C/code>, 12 \u003Ccode>scenario_expectation_failed\u003C/code>,\n13 \u003Ccode>scenario_io_error\u003C/code> (input unreadable, or \u003Ccode>--out\u003C/code> not new/empty), 14\n\u003Ccode>simulation_fault\u003C/code>, 15 \u003Ccode>module_startup_failed\u003C/code>; 3–9 concern \u003Ccode>--report\u003C/code> only.\n\u003Ccode>simengine_capture\u003C/code> exit codes: 3–6 no usable Vulkan device, 7\n\u003Ccode>backend_initialization_failed\u003C/code>, 8 \u003Ccode>validation_errors\u003C/code>, 10 \u003Ccode>scene_invalid\u003C/code>, 11\n\u003Ccode>render_failed\u003C/code>, 12 \u003Ccode>capture_content_invalid\u003C/code>, 13 \u003Ccode>output_write_failed\u003C/code>.\u003C/p>\n\u003Ch2 id=\"diagnosis-drill\">Diagnosis drill\u003C/h2>\n\u003Cp>Practise the loop on a new, uniquely named copy: break one unit and see the located\nerror. Keep that copy and its diagnostics for inspection; existing projects are preserved.\u003C/p>\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-var\">DRILL\u003C/span>=\u003Cspan class=\"tk-str\">$(python3\u003C/span> \u003Cspan class=\"tk-cmd\">-\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-str\">'EOF'\u003C/span>\n\u003Cspan class=\"tk-cmd\">import\u003C/span> pathlib, shutil, sys, tempfile\n\u003Cspan class=\"tk-cmd\">project\u003C/span> = pathlib.Path(sys.argv[1]).resolve()\n\u003Cspan class=\"tk-cmd\">drill\u003C/span> = pathlib.Path(tempfile.mkdtemp(prefix=project.name + \u003Cspan class=\"tk-str\">\".drill-\"\u003C/span>, dir=project.parent))\n\u003Cspan class=\"tk-cmd\">shutil.copytree(project,\u003C/span> drill, dirs_exist_ok=True, ignore=shutil.ignore_patterns(\u003Cspan class=\"tk-str\">\"runs\"\u003C/span>, \u003Cspan class=\"tk-str\">\".git\"\u003C/span>))\n\u003Cspan class=\"tk-cmd\">print(drill)\u003C/span>\n\u003Cspan class=\"tk-cmd\">EOF\u003C/span>\n\u003Cspan class=\"tk-cmd\">)\u003C/span>\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> - \u003Cspan class=\"tk-str\">\"$DRILL/scenario.json\"\u003C/span> \u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-str\">'EOF'\u003C/span>\n\u003Cspan class=\"tk-cmd\">import\u003C/span> json, sys\n\u003Cspan class=\"tk-cmd\">path\u003C/span> = sys.argv[1]\n\u003Cspan class=\"tk-cmd\">scenario\u003C/span> = json.load(open(path, encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>))\n\u003Cspan class=\"tk-cmd\">scenario[\"entities\"][0][\"position\"][\"unit\"]\u003C/span> = \u003Cspan class=\"tk-str\">\"cm\"\u003C/span>  \u003Cspan class=\"tk-com\"> # the schema accepts meters only\u003C/span>\n\u003Cspan class=\"tk-cmd\">json.dump(scenario,\u003C/span> open(path, \u003Cspan class=\"tk-str\">\"w\"\u003C/span>, encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>), indent=2)\n\u003Cspan class=\"tk-cmd\">EOF\u003C/span>\n\u003Cspan class=\"tk-cmd\">set\u003C/span> +e\n\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\">\"$DRILL\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD\"\u003C/span> \u003Cspan class=\"tk-punc\">&gt;\u003C/span> \u003Cspan class=\"tk-str\">\"$DRILL/check.json\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">status=$?\u003C/span>\n\u003Cspan class=\"tk-cmd\">set\u003C/span> \u003Cspan class=\"tk-flag\">-e\u003C/span>\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> - \u003Cspan class=\"tk-str\">\"$DRILL/check.json\"\u003C/span> \u003Cspan class=\"tk-str\">\"$status\"\u003C/span> \u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-str\">'EOF'\u003C/span>\n\u003Cspan class=\"tk-cmd\">import\u003C/span> json, sys\n\u003Cspan class=\"tk-cmd\">result\u003C/span> = json.load(open(sys.argv[1], encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>))\n\u003Cspan class=\"tk-cmd\">error\u003C/span> = result[\u003Cspan class=\"tk-str\">\"failure\"\u003C/span>][\u003Cspan class=\"tk-str\">\"detail\"\u003C/span>][\u003Cspan class=\"tk-str\">\"errors\"\u003C/span>][0]\n\u003Cspan class=\"tk-cmd\">assert\u003C/span> int(sys.argv[2]) == 23 and result[\u003Cspan class=\"tk-str\">\"failure\"\u003C/span>][\u003Cspan class=\"tk-str\">\"code\"\u003C/span>] == \u003Cspan class=\"tk-str\">\"scenario_invalid\"\u003C/span>, result[\u003Cspan class=\"tk-str\">\"failure\"\u003C/span>]\n\u003Cspan class=\"tk-cmd\">assert\u003C/span> error[\u003Cspan class=\"tk-str\">\"code\"\u003C/span>] == \u003Cspan class=\"tk-str\">\"unit_mismatch\"\u003C/span> and error[\u003Cspan class=\"tk-str\">\"path\"\u003C/span>] == \u003Cspan class=\"tk-str\">\"/entities/0/position/unit\"\u003C/span>, error\n\u003Cspan class=\"tk-cmd\">print(\"diagnosed:\",\u003C/span> error[\u003Cspan class=\"tk-str\">\"code\"\u003C/span>], \u003Cspan class=\"tk-str\">\"at\"\u003C/span>, error[\u003Cspan class=\"tk-str\">\"path\"\u003C/span>], \u003Cspan class=\"tk-str\">\"line\"\u003C/span>, error[\u003Cspan class=\"tk-str\">\"line\"\u003C/span>], \u003Cspan class=\"tk-str\">\"expected\"\u003C/span>, error[\u003Cspan class=\"tk-str\">\"expected\"\u003C/span>], \u003Cspan class=\"tk-str\">\"found\"\u003C/span>, error[\u003Cspan class=\"tk-str\">\"found\"\u003C/span>])\n\u003Cspan class=\"tk-cmd\">EOF\u003C/span>\n\u003Cspan class=\"tk-cmd\">printf\u003C/span> \u003Cspan class=\"tk-str\">'Diagnosis files retained in %s\\n'\u003C/span> \u003Cspan class=\"tk-str\">\"$DRILL\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Report failures verbatim (code, step, message, the engine’s own error object). Change\nonly the project; never edit SimEngine sources, tests or tolerances to get a pass, and\nnever describe a \u003Ccode>BLOCKED_ENVIRONMENT\u003C/code> or \u003Ccode>NOT_RUN\u003C/code> render as passed.\u003C/p>\n",[6,9,12,15,18,21],{"id":7,"text":8},"compatible-versions","Compatible versions",{"id":10,"text":11},"variables","Variables",{"id":13,"text":14},"run","Run",{"id":16,"text":17},"use-the-engine-tools-directly","Use the engine tools directly",{"id":19,"text":20},"diagnose-exit-codes-and-what-to-do","Diagnose: exit codes and what to do",{"id":22,"text":23},"diagnosis-drill","Diagnosis drill",1793299074004]