nodehammer 0.2.0rc3__tar.gz → 0.2.0rc5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.gitignore +1 -1
  2. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/CMakeLists.txt +11 -10
  3. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/PKG-INFO +23 -15
  4. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/README.md +22 -14
  5. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/shared_consumer/main.cpp +3 -2
  6. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/Dependencies.cmake +2 -2
  7. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/conanfile.py +2 -2
  8. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/kitchen_sink.lua +1 -1
  9. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd.lua +2 -2
  10. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/cli.hpp +27 -2
  11. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/config.hpp +1 -1
  12. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/semantic_scene.hpp +5 -4
  13. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/packaging/web/README.md +1 -1
  14. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/packaging/web/src/nodehammer_web/__init__.py +1 -1
  15. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/pyproject.toml +1 -1
  16. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/python/nodehammer/__main__.py +7 -1
  17. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/python/nodehammer/cli.py +29 -5
  18. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/check_pages_site.py +1 -1
  19. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/check_web_serve.py +10 -4
  20. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/make_nhproj.py +6 -0
  21. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/api/render_scene.cpp +5 -37
  22. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/cli_common.hpp +53 -0
  23. nodehammer-0.2.0rc5/src/cli/cmd_config.cpp +204 -0
  24. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/cmd_convert.cpp +160 -55
  25. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/cmd_inspect.cpp +215 -41
  26. nodehammer-0.2.0rc5/src/cli/cmd_project.cpp +238 -0
  27. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/cmd_viewer_native.cpp +212 -135
  28. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/cmd_viewer_web.cpp +107 -72
  29. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/main.cpp +6 -0
  30. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/run.cpp +32 -9
  31. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/run_internal.hpp +15 -14
  32. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_loader.hpp +1 -1
  33. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/diagnostic_codes.hpp +7 -0
  34. nodehammer-0.2.0rc5/src/ir/fb/render/exporter.cpp +43 -0
  35. nodehammer-0.2.0rc5/src/ir/fb/render/exporter.hpp +25 -0
  36. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/importer.cpp +1 -1
  37. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/importer.hpp +1 -1
  38. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/render/exporter_registry.cpp +14 -0
  39. nodehammer-0.2.0rc5/src/ir/render/json_exporter.cpp +25 -0
  40. nodehammer-0.2.0rc5/src/ir/render/json_exporter.hpp +25 -0
  41. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/lua/lua_config.cpp +1 -1
  42. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/lua/lua_config.hpp +1 -1
  43. nodehammer-0.2.0rc5/src/project/pack.cpp +216 -0
  44. nodehammer-0.2.0rc5/src/project/pack.hpp +63 -0
  45. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/python/bindings.cpp +9 -2
  46. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/project_manifest.hpp +7 -0
  47. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/zip_working_set.cpp +67 -5
  48. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/runtime_locator.hpp +1 -1
  49. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/stage.cpp +7 -66
  50. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/CMakeLists.txt +37 -7
  51. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/api/test_api_surface.cpp +1 -1
  52. nodehammer-0.2.0rc5/tests/cli/cli_test_support.hpp +122 -0
  53. nodehammer-0.2.0rc5/tests/cli/test_cli_config.cpp +181 -0
  54. nodehammer-0.2.0rc5/tests/cli/test_cli_convert_stages.cpp +148 -0
  55. nodehammer-0.2.0rc5/tests/cli/test_cli_inspect_json.cpp +234 -0
  56. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/cli/test_cli_run.cpp +101 -91
  57. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/config/test_config_writer.cpp +1 -1
  58. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/ir/test_flatbuffer_roundtrip.cpp +1 -1
  59. nodehammer-0.2.0rc5/tests/ir/test_render_nhr_exporter.cpp +140 -0
  60. nodehammer-0.2.0rc5/tests/project/test_pack.cpp +249 -0
  61. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_semantic_scene.cpp +4 -3
  62. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/python/test_cli.py +92 -12
  63. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/python/test_semantic_scene.py +1 -1
  64. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_zip_working_set.cpp +41 -0
  65. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/web/test_static_server.cpp +1 -1
  66. nodehammer-0.2.0rc3/src/cli/cmd_config_flatten.cpp +0 -63
  67. nodehammer-0.2.0rc3/src/cli/cmd_config_lua.cpp +0 -80
  68. nodehammer-0.2.0rc3/src/cli/cmd_dump_render.cpp +0 -80
  69. nodehammer-0.2.0rc3/src/cli/cmd_dump_semantic.cpp +0 -327
  70. nodehammer-0.2.0rc3/src/cli/cmd_validate_config.cpp +0 -45
  71. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.clang-format +0 -0
  72. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.clang-tidy +0 -0
  73. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.gitattributes +0 -0
  74. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.pre-commit-config.yaml +0 -0
  75. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.vscode/launch.json +0 -0
  76. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.vscode/settings.json +0 -0
  77. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/.vscode/tasks.json +0 -0
  78. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/Justfile +0 -0
  79. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/LICENSE +0 -0
  80. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/LICENSES/MIT.txt +0 -0
  81. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/LICENSES/OFL-1.1.txt +0 -0
  82. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/LICENSES/Zlib.txt +0 -0
  83. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/REUSE.toml +0 -0
  84. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/STYLE.md +0 -0
  85. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/bench-summary.py +0 -0
  86. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/bench.sh +0 -0
  87. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/build.sh +0 -0
  88. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/check_shared_exports.py +0 -0
  89. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/shared-build.sh +0 -0
  90. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/shared_consumer/CMakeLists.txt +0 -0
  91. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/ci/verify-shared-install.sh +0 -0
  92. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/CompilerOptions.cmake +0 -0
  93. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/PicProbe.cmake +0 -0
  94. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/Sokol.cmake +0 -0
  95. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/ThirdPartyLicenses.cmake +0 -0
  96. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/Version.cmake +0 -0
  97. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/nodehammer-config.cmake.in +0 -0
  98. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/patch_sokol_wgpu.cmake +0 -0
  99. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/pic_probe.cpp +0 -0
  100. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/validate_shader_hlsl.cmake +0 -0
  101. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/cmake/validate_shader_wgsl.cmake +0 -0
  102. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/full_example.toml +0 -0
  103. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/include_bad_path.toml +0 -0
  104. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/include_basic.toml +0 -0
  105. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/include_cycle.toml +0 -0
  106. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/include_diamond.toml +0 -0
  107. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/include_nested.toml +0 -0
  108. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/cycle_a.toml +0 -0
  109. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/cycle_b.toml +0 -0
  110. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/diamond_base.toml +0 -0
  111. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/diamond_left.toml +0 -0
  112. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/diamond_right.toml +0 -0
  113. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/materials.toml +0 -0
  114. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/nested_inner.toml +0 -0
  115. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/nested_outer.toml +0 -0
  116. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/includes/rules.toml +0 -0
  117. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/invalid_bad_tolerance.toml +0 -0
  118. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/invalid_missing_material_ref.toml +0 -0
  119. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/calorimeters.lua +0 -0
  120. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/lib/constants.lua +0 -0
  121. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/materials.lua +0 -0
  122. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/muon.lua +0 -0
  123. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/base.lua +0 -0
  124. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/calorimeters.lua +0 -0
  125. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/materials.lua +0 -0
  126. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/muon.lua +0 -0
  127. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/tracker.lua +0 -0
  128. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/parity.lua +0 -0
  129. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/parity.toml +0 -0
  130. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/lua/tracker.lua +0 -0
  131. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/minimal.toml +0 -0
  132. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/base.toml +0 -0
  133. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/calorimeters.toml +0 -0
  134. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/calorimeters_simple.toml +0 -0
  135. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/materials.toml +0 -0
  136. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/muon.toml +0 -0
  137. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/muon_simple.toml +0 -0
  138. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/simple_materials.toml +0 -0
  139. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd/tracker.toml +0 -0
  140. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd.toml +0 -0
  141. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_drop_coincident_faces.toml +0 -0
  142. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_merged.toml +0 -0
  143. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_simple.toml +0 -0
  144. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_ecal_barrel_stave.toml +0 -0
  145. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_hcal_barrel_stave.toml +0 -0
  146. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_long_strip_barrel_module.toml +0 -0
  147. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_long_strip_barrel_stave.toml +0 -0
  148. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_muon_barrel_chamber.toml +0 -0
  149. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_pixel_barrel_module.toml +0 -0
  150. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_pixel_barrel_stave.toml +0 -0
  151. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_short_strip_barrel_module.toml +0 -0
  152. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_short_strip_barrel_stave.toml +0 -0
  153. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/configs/odd_tracker.toml +0 -0
  154. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/dd4hep/sensitive_detector.xml +0 -0
  155. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/fixtures/dd4hep/simple_box.xml +0 -0
  156. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/build.hpp +0 -0
  157. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/diagnostics.hpp +0 -0
  158. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/render_scene.hpp +0 -0
  159. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/version.hpp.in +0 -0
  160. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/include/nodehammer/visibility.hpp +0 -0
  161. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/packaging/plugins/nh_web_pin.py +0 -0
  162. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/packaging/web/.gitignore +0 -0
  163. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/packaging/web/LICENSE +0 -0
  164. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/packaging/web/pyproject.toml +0 -0
  165. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/profiles/emscripten +0 -0
  166. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/python/nodehammer/__init__.py +0 -0
  167. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/python/nodehammer/py.typed +0 -0
  168. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/cli11/conandata.yml +0 -0
  169. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/cli11/conanfile.py +0 -0
  170. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/imgui/CMakeLists.txt +0 -0
  171. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/imgui/conandata.yml +0 -0
  172. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/imgui/conanfile.py +0 -0
  173. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/implot/CMakeLists.txt +0 -0
  174. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/implot/conandata.yml +0 -0
  175. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/implot/conanfile.py +0 -0
  176. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/nfd/conandata.yml +0 -0
  177. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/nfd/conanfile.py +0 -0
  178. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/sokol/conandata.yml +0 -0
  179. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/sokol/conanfile.py +0 -0
  180. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/sokol-shdc/conandata.yml +0 -0
  181. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/recipes/sokol-shdc/conanfile.py +0 -0
  182. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/schemas/render.fbs +0 -0
  183. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/schemas/semantic.fbs +0 -0
  184. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/build_pages_site.sh +0 -0
  185. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/check_cli_no_exit.py +0 -0
  186. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/check_em_js_closure.py +0 -0
  187. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/check_wasm_module_linkage.py +0 -0
  188. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/check_wheel_pair.py +0 -0
  189. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/serve_nocache.py +0 -0
  190. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/stage_wasm_viewer.sh +0 -0
  191. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/wasm_compute_smoke.js +0 -0
  192. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/scripts/windows-msvc-cmake.ps1 +0 -0
  193. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/CMakeLists.txt +0 -0
  194. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/ao.glsl +0 -0
  195. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/ao_denoise.glsl +0 -0
  196. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/blit.glsl +0 -0
  197. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/composite.glsl +0 -0
  198. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/depth_helpers.glsl.h +0 -0
  199. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/ibl_bake.glsl +0 -0
  200. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/shaders/scene.glsl +0 -0
  201. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/api/build.cpp +0 -0
  202. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/api/config.cpp +0 -0
  203. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/api/diagnostics.cpp +0 -0
  204. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/api/handles.hpp +0 -0
  205. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/api/semantic_scene.cpp +0 -0
  206. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/pager.cpp +0 -0
  207. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/cli/pager.hpp +0 -0
  208. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/color_parse.cpp +0 -0
  209. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/color_parse.hpp +0 -0
  210. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_ast.hpp +0 -0
  211. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_enums.hpp +0 -0
  212. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_keys.hpp +0 -0
  213. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_loader.cpp +0 -0
  214. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_validator.cpp +0 -0
  215. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_validator.hpp +0 -0
  216. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_writer.cpp +0 -0
  217. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/config_writer.hpp +0 -0
  218. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/predicate_parser.cpp +0 -0
  219. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/config/predicate_parser.hpp +0 -0
  220. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/file_io.hpp +0 -0
  221. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/glm_json.hpp +0 -0
  222. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/markup.cpp +0 -0
  223. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/markup.hpp +0 -0
  224. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/overloaded.hpp +0 -0
  225. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/timing.hpp +0 -0
  226. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/detail/zstd_io.hpp +0 -0
  227. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/diagnostics.hpp +0 -0
  228. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/export_resolve.cpp +0 -0
  229. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/export_resolve.hpp +0 -0
  230. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/dd4hep/semantic/importer.cpp +0 -0
  231. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/dd4hep/semantic/importer.hpp +0 -0
  232. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/render/flatbuffer.cpp +0 -0
  233. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/render/flatbuffer.hpp +0 -0
  234. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/exporter.cpp +0 -0
  235. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/exporter.hpp +0 -0
  236. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/flatbuffer.cpp +0 -0
  237. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/flatbuffer.hpp +0 -0
  238. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/gltf/render/exporter.cpp +0 -0
  239. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/gltf/render/exporter.hpp +0 -0
  240. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/json/semantic/exporter.cpp +0 -0
  241. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/json/semantic/exporter.hpp +0 -0
  242. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/json/semantic/importer.cpp +0 -0
  243. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/json/semantic/importer.hpp +0 -0
  244. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/obj/render/exporter.cpp +0 -0
  245. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/obj/render/exporter.hpp +0 -0
  246. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/provenance.hpp +0 -0
  247. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/render/exporter.hpp +0 -0
  248. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/render.hpp +0 -0
  249. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/render_json.cpp +0 -0
  250. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/render_json.hpp +0 -0
  251. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic/exporter.hpp +0 -0
  252. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic/exporter_registry.cpp +0 -0
  253. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic/importer.hpp +0 -0
  254. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic/importer_registry.cpp +0 -0
  255. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic.cpp +0 -0
  256. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic.hpp +0 -0
  257. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic_json.cpp +0 -0
  258. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/semantic_json.hpp +0 -0
  259. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/synthetic/semantic/importer.cpp +0 -0
  260. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/synthetic/semantic/importer.hpp +0 -0
  261. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/importer.cpp +0 -0
  262. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/importer.hpp +0 -0
  263. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/shape_dispatch.cpp +0 -0
  264. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/shape_dispatch.hpp +0 -0
  265. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/python/CMakeLists.txt +0 -0
  266. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/scene_build.cpp +0 -0
  267. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/scene_build.hpp +0 -0
  268. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/selection/predicate.cpp +0 -0
  269. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/selection/predicate.hpp +0 -0
  270. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/selection/selector.cpp +0 -0
  271. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/selection/selector.hpp +0 -0
  272. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/sokol/sokol_imgui_impl.cc +0 -0
  273. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/sokol/sokol_imgui_impl.mm +0 -0
  274. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/sokol/sokol_impl.c +0 -0
  275. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/sokol/sokol_impl.mm +0 -0
  276. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/boolean_tessellator.cpp +0 -0
  277. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/boolean_tessellator.hpp +0 -0
  278. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/build_pipeline.cpp +0 -0
  279. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/build_pipeline.hpp +0 -0
  280. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/primitive_tessellator.cpp +0 -0
  281. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/primitive_tessellator.hpp +0 -0
  282. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/tessellation_job.hpp +0 -0
  283. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/tessellation_pass.cpp +0 -0
  284. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/tessellation_pass.hpp +0 -0
  285. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/tessellator.hpp +0 -0
  286. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/wedge_cut.cpp +0 -0
  287. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tessellation/wedge_cut.hpp +0 -0
  288. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/tools/imgui_kitchen_sink_main.cpp +0 -0
  289. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/version.cpp +0 -0
  290. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/CMakeLists.txt +0 -0
  291. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ao_denoise_pass.cpp +0 -0
  292. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ao_denoise_pass.hpp +0 -0
  293. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ao_pass.cpp +0 -0
  294. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ao_pass.hpp +0 -0
  295. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ao_render_target.cpp +0 -0
  296. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ao_render_target.hpp +0 -0
  297. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/app.cpp +0 -0
  298. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/app.hpp +0 -0
  299. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/app_state.cpp +0 -0
  300. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/app_state.hpp +0 -0
  301. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/archive_export.cpp +0 -0
  302. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/archive_export.hpp +0 -0
  303. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/archive_project_fs.cpp +0 -0
  304. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/archive_project_fs.hpp +0 -0
  305. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/backend_caps.hpp +0 -0
  306. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/bag_project_fs.cpp +0 -0
  307. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/bag_project_fs.hpp +0 -0
  308. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/bench_runner.cpp +0 -0
  309. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/bench_runner.hpp +0 -0
  310. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/blit_pass.cpp +0 -0
  311. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/blit_pass.hpp +0 -0
  312. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/build_controller.cpp +0 -0
  313. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/build_controller.hpp +0 -0
  314. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/build_session.cpp +0 -0
  315. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/build_session.hpp +0 -0
  316. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/byte_buffer.hpp +0 -0
  317. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/camera.cpp +0 -0
  318. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/camera.hpp +0 -0
  319. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/composite_pass.cpp +0 -0
  320. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/composite_pass.hpp +0 -0
  321. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/config.hpp +0 -0
  322. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/dynamic_render_scale.cpp +0 -0
  323. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/dynamic_render_scale.hpp +0 -0
  324. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/filesystem_project_fs.cpp +0 -0
  325. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/filesystem_project_fs.hpp +0 -0
  326. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/gpu_pass_timer.hpp +0 -0
  327. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/gpu_pass_timer_d3d11.cpp +0 -0
  328. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/gpu_pass_timer_noop.cpp +0 -0
  329. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ibl.cpp +0 -0
  330. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ibl.hpp +0 -0
  331. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ibl_baker.cpp +0 -0
  332. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ibl_baker.hpp +0 -0
  333. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/imgui_backend.cpp +0 -0
  334. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/imgui_backend.hpp +0 -0
  335. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/log_sink.hpp +0 -0
  336. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/native_bag_project_fs.cpp +0 -0
  337. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/native_bag_project_fs.hpp +0 -0
  338. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/platform.hpp +0 -0
  339. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/platform_macos.mm +0 -0
  340. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/platform_native_common.cpp +0 -0
  341. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/platform_native_common.hpp +0 -0
  342. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/platform_native_default.cpp +0 -0
  343. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/platform_web.cpp +0 -0
  344. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export.cpp +0 -0
  345. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export.hpp +0 -0
  346. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback.hpp +0 -0
  347. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_d3d11.cpp +0 -0
  348. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_gl.cpp +0 -0
  349. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_metal.mm +0 -0
  350. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_wgpu.cpp +0 -0
  351. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_exporter.cpp +0 -0
  352. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/png_exporter.hpp +0 -0
  353. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/project_fs.hpp +0 -0
  354. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/project_manifest.cpp +0 -0
  355. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/render_quality.hpp +0 -0
  356. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job.hpp +0 -0
  357. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_common.cpp +0 -0
  358. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_internal.hpp +0 -0
  359. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_native.cpp +0 -0
  360. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_web.cpp +0 -0
  361. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_web_backend.hpp +0 -0
  362. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_web_worker.cpp +0 -0
  363. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_render_target.cpp +0 -0
  364. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_render_target.hpp +0 -0
  365. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_renderer.cpp +0 -0
  366. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/scene_renderer.hpp +0 -0
  367. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/shared_image.hpp +0 -0
  368. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/stb_image_write_impl.cpp +0 -0
  369. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/debug_panel.cpp +0 -0
  370. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/debug_panel.hpp +0 -0
  371. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/icon_font.cpp +0 -0
  372. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/icon_font.hpp +0 -0
  373. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/menu_bar.cpp +0 -0
  374. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/menu_bar.hpp +0 -0
  375. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/notifications.cpp +0 -0
  376. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/notifications.hpp +0 -0
  377. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/perf_history.hpp +0 -0
  378. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/project_panel.cpp +0 -0
  379. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/project_panel.hpp +0 -0
  380. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/status_ui.cpp +0 -0
  381. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/status_ui.hpp +0 -0
  382. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/ui_context.hpp +0 -0
  383. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/view_panel.cpp +0 -0
  384. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/view_panel.hpp +0 -0
  385. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/viewer_ui.cpp +0 -0
  386. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/ui/viewer_ui.hpp +0 -0
  387. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/watched_filesystem_project_fs.cpp +0 -0
  388. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/watched_filesystem_project_fs.hpp +0 -0
  389. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/viewer/zip_working_set.hpp +0 -0
  390. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/compute_worker.js +0 -0
  391. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/compute_worker_main.cpp +0 -0
  392. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/executable_path.cpp +0 -0
  393. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/open_browser.cpp +0 -0
  394. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/open_browser.hpp +0 -0
  395. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/runtime_locator.cpp +0 -0
  396. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/stage.hpp +0 -0
  397. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/static_server.cpp +0 -0
  398. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/static_server.hpp +0 -0
  399. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/src/web/viewer_main.cpp +0 -0
  400. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/api/test_api_equivalence.cpp +0 -0
  401. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/api/test_config_wrapper.cpp +0 -0
  402. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/bench_main.cpp +0 -0
  403. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/config/test_config_fixtures.cpp +0 -0
  404. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/config/test_config_loader.cpp +0 -0
  405. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/config/test_config_validator.cpp +0 -0
  406. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/config/test_lua_config.cpp +0 -0
  407. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/config/test_predicate_parser.cpp +0 -0
  408. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/export/test_export_resolve.cpp +0 -0
  409. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/export/test_gltf_exporter.cpp +0 -0
  410. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/export/test_render_exporter_registry.cpp +0 -0
  411. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/export/test_semantic_exporter_registry.cpp +0 -0
  412. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/import/test_dd4hep_importer.cpp +0 -0
  413. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/import/test_synthetic_importer.cpp +0 -0
  414. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/import/test_tgeo_importer.cpp +0 -0
  415. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/ir/test_json_roundtrip.cpp +0 -0
  416. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/ir/test_render_flatbuffer_roundtrip.cpp +0 -0
  417. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/ir/test_semantic_ir.cpp +0 -0
  418. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/ir/test_shape_variant.cpp +0 -0
  419. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/public_fixture.hpp +0 -0
  420. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_build.cpp +0 -0
  421. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_cli.cpp +0 -0
  422. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_config.cpp +0 -0
  423. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_dd4hep.cpp +0 -0
  424. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_diagnostics.cpp +0 -0
  425. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_render_scene.cpp +0 -0
  426. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/public/test_public_tgeo.cpp +0 -0
  427. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/python/test_build.py +0 -0
  428. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/python/test_config_and_diagnostics.py +0 -0
  429. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/selection/test_predicate.cpp +0 -0
  430. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/selection/test_selector.cpp +0 -0
  431. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_boolean_tessellator.cpp +0 -0
  432. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_build_pipeline.cpp +0 -0
  433. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_obj_writer.hpp +0 -0
  434. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_primitive_tessellator.cpp +0 -0
  435. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_tessellation_pass.cpp +0 -0
  436. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_tgeo_tessellation.cpp +0 -0
  437. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/tessellation/test_wedge_cut.cpp +0 -0
  438. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/test_compute_pipeline.cpp +0 -0
  439. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/test_main.cpp +0 -0
  440. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/test_markup.cpp +0 -0
  441. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/test_scene_build.cpp +0 -0
  442. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/test_timing.cpp +0 -0
  443. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_app_state.cpp +0 -0
  444. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_archive_export.cpp +0 -0
  445. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_archive_project_fs.cpp +0 -0
  446. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_bag_project_fs.cpp +0 -0
  447. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_build_session.cpp +0 -0
  448. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_byte_buffer.cpp +0 -0
  449. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_dynamic_render_scale.cpp +0 -0
  450. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_filesystem_project_fs.cpp +0 -0
  451. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_native_bag_project_fs.cpp +0 -0
  452. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_project_manifest.cpp +0 -0
  453. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/viewer/test_watched_filesystem_project_fs.cpp +0 -0
  454. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/wasm_lua_smoke.cpp +0 -0
  455. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/web/test_runtime_locator.cpp +0 -0
  456. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/tests/web/test_stage.cpp +0 -0
  457. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/third_party/fontawesome7/IconsFontAwesome7.h +0 -0
  458. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/third_party/fontawesome7/README.md +0 -0
  459. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/third_party/fontawesome7/fa-solid-900.h +0 -0
  460. {nodehammer-0.2.0rc3 → nodehammer-0.2.0rc5}/third_party/stb/stb_image_write.h +0 -0
@@ -14,7 +14,7 @@
14
14
  # Project archives packed by the viewer / make_nhproj.py — always generated.
15
15
  *.nhproj
16
16
 
17
- # config-flatten output written to the repo root (generated from fixtures/).
17
+ # `config flatten` output written to the repo root (generated from fixtures/).
18
18
  /*_flat.toml
19
19
  CMakeUserPresets.json
20
20
 
@@ -136,7 +136,7 @@ include(GNUInstallDirs)
136
136
 
137
137
  # ── The web runtime's contract ───────────────────────────────────────────────
138
138
  # The wasm viewer is delivered as a directory, not a program: a shell, a worker
139
- # script, three bundles and the stamp below. `nodehammer viewer --web` locates
139
+ # script, three bundles and the stamp below. `nodehammer viewer serve` locates
140
140
  # one through a ladder of candidate directories (a flag, an environment
141
141
  # variable, this install path, later a download cache), which means it can be
142
142
  # handed a directory that nobody validated — an old checkout's build tree is
@@ -253,6 +253,8 @@ set(NH_CORE_SOURCES
253
253
  src/ir/gltf/render/exporter.cpp
254
254
  src/ir/obj/render/exporter.cpp
255
255
  src/ir/render/exporter_registry.cpp
256
+ src/ir/fb/render/exporter.cpp
257
+ src/ir/render/json_exporter.cpp
256
258
  src/ir/json/semantic/exporter.cpp
257
259
  src/ir/fb/semantic/exporter.cpp
258
260
  src/ir/semantic/exporter_registry.cpp
@@ -298,11 +300,7 @@ set(NH_CORE_SOURCES
298
300
  src/cli/pager.cpp
299
301
  src/cli/cmd_convert.cpp
300
302
  src/cli/cmd_inspect.cpp
301
- src/cli/cmd_validate_config.cpp
302
- src/cli/cmd_config_flatten.cpp
303
- src/cli/cmd_dump_semantic.cpp
304
- src/cli/cmd_dump_render.cpp
305
- src/cli/cmd_config_lua.cpp
303
+ src/cli/cmd_config.cpp
306
304
  )
307
305
 
308
306
  # ── Application sources ───────────────────────────────────────────────────────
@@ -478,7 +476,11 @@ if(NOT EMSCRIPTEN)
478
476
  src/web/static_server.cpp
479
477
  src/web/stage.cpp
480
478
  src/web/open_browser.cpp
481
- # `viewer --web` itself. Excluded here rather than #ifdef'd inside:
479
+ # Packing mounts a FilesystemProjectFs, so it is gated here rather than
480
+ # beside the ZipWorkingSet it builds -- that half *is* cross-platform.
481
+ src/project/pack.cpp
482
+ src/cli/cmd_project.cpp
483
+ # `viewer serve` itself. Excluded here rather than #ifdef'd inside:
482
484
  # every line of it calls something in the three files above, so a wasm
483
485
  # build of this TU would be a shell around a refusal. `run.cpp` skips
484
486
  # the registration to match, and a wasm module simply has no `viewer`
@@ -868,7 +870,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
868
870
  src/scene_build.cpp
869
871
  src/selection/selector.cpp
870
872
  src/cli/cmd_convert.cpp
871
- src/cli/cmd_dump_semantic.cpp
872
873
  PROPERTIES COMPILE_OPTIONS "-Wno-maybe-uninitialized"
873
874
  )
874
875
  endif()
@@ -912,7 +913,7 @@ if(EMSCRIPTEN AND NODEHAMMER_WITH_VIEWER)
912
913
  # share/nodehammer/web is also the rung the asset ladder looks for relative
913
914
  # to the executable (docs/cli-and-web-viewer-plan.md Part 1), which is why
914
915
  # it is a datadir path and not an opaque one: a native install tree and a
915
- # wasm install tree merge into one directory that `nodehammer viewer --web`
916
+ # wasm install tree merge into one directory that `nodehammer viewer serve`
916
917
  # can resolve without being told where anything is.
917
918
  install(TARGETS nodehammer-gles3 nodehammer-wgpu nodehammer-compute
918
919
  RUNTIME DESTINATION "${NH_WEB_RUNTIME_DIR}"
@@ -942,7 +943,7 @@ if(EMSCRIPTEN AND NODEHAMMER_WITH_VIEWER)
942
943
 
943
944
  # The stamp, written beside the bundles in the build tree so that a build
944
945
  # directory and an install tree are the same shape — `just wasm-serve` and
945
- # `just pages-site` stage straight out of the former, and `viewer --web
946
+ # `just pages-site` stage straight out of the former, and `viewer serve
946
947
  # --web-assets build/emscripten/Release` is the first thing any developer
947
948
  # reaches for.
948
949
  file(GENERATE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nodehammer
3
- Version: 0.2.0rc3
3
+ Version: 0.2.0rc5
4
4
  Summary: Detector geometry tessellation and export
5
5
  Author: Paul Gessinger
6
6
  License-Expression: MIT
@@ -77,8 +77,7 @@ versus what's on the roadmap.
77
77
  - **Analytical geometry surgery**: semantic-level azimuthal wedge cuts and
78
78
  boolean operations via [manifold](https://github.com/elalish/manifold),
79
79
  correct on non-manifold swept primitives, cooperative with UI progress.
80
- - **CLI**: `convert`, `inspect`, `validate-config`, `config-flatten`,
81
- `dump-semantic`, `dump-render`, `viewer`.
80
+ - **CLI**: `convert`, `inspect`, `config`, `project`, `viewer`.
82
81
  - **Viewer rendering pipeline**, live today:
83
82
  - Full offscreen HDR pipeline with ACES / Reinhard / AgX tonemapping and
84
83
  exposure control
@@ -90,7 +89,7 @@ versus what's on the roadmap.
90
89
  profile — renders on demand and caps the idle frame rate
91
90
  - Live ImPlot performance graphs in the debug panel
92
91
  - High-resolution, supersampled PNG screenshot export
93
- (`nodehammer viewer --screenshot out.png ...`) — **verified on Metal**;
92
+ (`nodehammer viewer shot -o out.png ...`) — **verified on Metal**;
94
93
  the WebGL2/GLES3 and WebGPU readback paths compile and link but are not
95
94
  yet verified in-browser
96
95
  - **Builds on macOS, Linux, and Windows** natively (Metal, GLCORE, and D3D11
@@ -162,18 +161,27 @@ Full design of record, including backend mapping and mode transitions:
162
161
  ## CLI
163
162
 
164
163
  ```
165
- nodehammer convert # geometry → glTF / OBJ / render IR
166
- nodehammer inspect # explore a semantic scene
167
- nodehammer validate-config # lint a TOML config before running it
168
- nodehammer config-flatten # resolve config includes/overrides
169
- nodehammer dump-semantic # dump the semantic scene as JSON
170
- nodehammer dump-render # dump the render IR as JSON
171
- nodehammer viewer # launch the interactive viewer
164
+ nodehammer convert # geometry in, anything out — the pipeline
165
+ nodehammer inspect # summary | tree | tags — ask about a scene
166
+ nodehammer config # validate | flatten — TOML and Lua configs
167
+ nodehammer project # pack | publish | info — .nhproj archives
168
+ nodehammer viewer # open | serve | shot | bench — the app
172
169
  ```
173
170
 
174
- Running the executable with no arguments at all (e.g. double-clicking
175
- `nodehammer.exe` in a file manager) also launches the viewer, in builds with
176
- `NODEHAMMER_WITH_VIEWER` enabled.
171
+ Four nouns and one verb. The design of record, including the vocabulary and why
172
+ each old name went, is [docs/cli-design.md](docs/cli-design.md).
173
+
174
+ `convert` spans the whole pipeline, and **the output format decides how far it
175
+ runs**: `-o scene.nhb` stops at the semantic scene, `-o scene.glb` tessellates
176
+ first, and asking for both in one command is one pass rather than two.
177
+ Tessellation is lossy by construction — solids become triangles — so `.nhb` is
178
+ the faithful stop and `.glb` is a one-way door.
179
+
180
+ ```bash
181
+ nodehammer project pack -c scene.toml -i odd.xml -o odd.nhproj
182
+ nodehammer viewer odd.nhproj serve # open it in a browser
183
+ nodehammer project publish odd.nhproj -o site/
184
+ ```
177
185
 
178
186
  ## Building
179
187
 
@@ -235,7 +243,7 @@ The repo ships a real detector fixture — the Open Data Detector — ready to c
235
243
 
236
244
  ```bash
237
245
  just odd # full ODD → glb (see the Justfile for single-stave recipes too)
238
- build/RelWithDebInfo/nodehammer viewer
246
+ build/RelWithDebInfo/nodehammer viewer open
239
247
  ```
240
248
 
241
249
  ### …in a browser
@@ -58,8 +58,7 @@ versus what's on the roadmap.
58
58
  - **Analytical geometry surgery**: semantic-level azimuthal wedge cuts and
59
59
  boolean operations via [manifold](https://github.com/elalish/manifold),
60
60
  correct on non-manifold swept primitives, cooperative with UI progress.
61
- - **CLI**: `convert`, `inspect`, `validate-config`, `config-flatten`,
62
- `dump-semantic`, `dump-render`, `viewer`.
61
+ - **CLI**: `convert`, `inspect`, `config`, `project`, `viewer`.
63
62
  - **Viewer rendering pipeline**, live today:
64
63
  - Full offscreen HDR pipeline with ACES / Reinhard / AgX tonemapping and
65
64
  exposure control
@@ -71,7 +70,7 @@ versus what's on the roadmap.
71
70
  profile — renders on demand and caps the idle frame rate
72
71
  - Live ImPlot performance graphs in the debug panel
73
72
  - High-resolution, supersampled PNG screenshot export
74
- (`nodehammer viewer --screenshot out.png ...`) — **verified on Metal**;
73
+ (`nodehammer viewer shot -o out.png ...`) — **verified on Metal**;
75
74
  the WebGL2/GLES3 and WebGPU readback paths compile and link but are not
76
75
  yet verified in-browser
77
76
  - **Builds on macOS, Linux, and Windows** natively (Metal, GLCORE, and D3D11
@@ -143,18 +142,27 @@ Full design of record, including backend mapping and mode transitions:
143
142
  ## CLI
144
143
 
145
144
  ```
146
- nodehammer convert # geometry → glTF / OBJ / render IR
147
- nodehammer inspect # explore a semantic scene
148
- nodehammer validate-config # lint a TOML config before running it
149
- nodehammer config-flatten # resolve config includes/overrides
150
- nodehammer dump-semantic # dump the semantic scene as JSON
151
- nodehammer dump-render # dump the render IR as JSON
152
- nodehammer viewer # launch the interactive viewer
145
+ nodehammer convert # geometry in, anything out — the pipeline
146
+ nodehammer inspect # summary | tree | tags — ask about a scene
147
+ nodehammer config # validate | flatten — TOML and Lua configs
148
+ nodehammer project # pack | publish | info — .nhproj archives
149
+ nodehammer viewer # open | serve | shot | bench — the app
153
150
  ```
154
151
 
155
- Running the executable with no arguments at all (e.g. double-clicking
156
- `nodehammer.exe` in a file manager) also launches the viewer, in builds with
157
- `NODEHAMMER_WITH_VIEWER` enabled.
152
+ Four nouns and one verb. The design of record, including the vocabulary and why
153
+ each old name went, is [docs/cli-design.md](docs/cli-design.md).
154
+
155
+ `convert` spans the whole pipeline, and **the output format decides how far it
156
+ runs**: `-o scene.nhb` stops at the semantic scene, `-o scene.glb` tessellates
157
+ first, and asking for both in one command is one pass rather than two.
158
+ Tessellation is lossy by construction — solids become triangles — so `.nhb` is
159
+ the faithful stop and `.glb` is a one-way door.
160
+
161
+ ```bash
162
+ nodehammer project pack -c scene.toml -i odd.xml -o odd.nhproj
163
+ nodehammer viewer odd.nhproj serve # open it in a browser
164
+ nodehammer project publish odd.nhproj -o site/
165
+ ```
158
166
 
159
167
  ## Building
160
168
 
@@ -216,7 +224,7 @@ The repo ships a real detector fixture — the Open Data Detector — ready to c
216
224
 
217
225
  ```bash
218
226
  just odd # full ODD → glb (see the Justfile for single-stave recipes too)
219
- build/RelWithDebInfo/nodehammer viewer
227
+ build/RelWithDebInfo/nodehammer viewer open
220
228
  ```
221
229
 
222
230
  ### …in a browser
@@ -108,12 +108,13 @@ int main() {
108
108
  }
109
109
  std::cout << std::flush;
110
110
 
111
- if (!listed(semanticFormats, "synthetic") || !listed(semanticFormats, "flatbuffer")) {
111
+ if (!listed(semanticFormats, "synthetic") || !listed(semanticFormats, "nhb")) {
112
112
  std::cerr << "SemanticScene::formats() is missing a built-in format\n";
113
113
  return 1;
114
114
  }
115
115
  if (!listed(nodehammer::Config::formats(), "toml") ||
116
- !listed(nodehammer::RenderScene::formats(), "gltf")) {
116
+ !listed(nodehammer::RenderScene::formats(), "gltf") ||
117
+ !listed(nodehammer::RenderScene::formats(), "nhr")) {
117
118
  std::cerr << "a built-in format is missing from formats()\n";
118
119
  return 1;
119
120
  }
@@ -60,7 +60,7 @@ FetchContent_Declare(nlohmann_json
60
60
  FetchContent_MakeAvailable(nlohmann_json)
61
61
 
62
62
  # ── cpp-httplib ───────────────────────────────────────────────────────────────
63
- # The static server behind `viewer --web`. Native only: the wasm build has no
63
+ # The static server behind `viewer serve`. Native only: the wasm build has no
64
64
  # sockets, and the module it would serve is the thing being served.
65
65
  #
66
66
  # Chosen over the ~370 hand-rolled lines it replaces because it is *less* code
@@ -215,7 +215,7 @@ if(TARGET flatbuffers)
215
215
  endif()
216
216
 
217
217
  # ── Lua config front-end (lua + sol2) ────────────────────────────────────────
218
- # Powers the `config-lua` CLI command and `Config::read`'s `.lua` branch — an
218
+ # Powers the `config flatten` CLI command and `Config::read`'s `.lua` branch — an
219
219
  # unconditional source in nodehammer_lib on every platform, Emscripten included.
220
220
  # Both come from Conan (lua has no clean upstream CMake — it ships a Makefile —
221
221
  # so, like imgui/implot below, we resolve via find_package rather than a git
@@ -57,7 +57,7 @@ class Nodehammer(ConanFile):
57
57
  # — and static-lib dead-strip keeps it out of any binary that does not
58
58
  # reference it.
59
59
  self.requires("miniz/3.0.2")
60
- # Lua scripting config front-end: the `config-lua` CLI command and
60
+ # Lua scripting config front-end: the `config flatten` CLI command and
61
61
  # `Config::read`'s `.lua` branch. Lua is a small C interpreter; sol2 is
62
62
  # its header-only C++ binding (and pulls lua transitively, but we pin lua
63
63
  # explicitly for parity with the CMake find_package).
@@ -71,7 +71,7 @@ class Nodehammer(ConanFile):
71
71
  # never calls the `.lua` path, which today is both wasm bundles.
72
72
  self.requires("lua/5.4.6")
73
73
  self.requires("sol2/3.5.0")
74
- # The static server behind `viewer --web`. Gated on the platform rather
74
+ # The static server behind `viewer serve`. Gated on the platform rather
75
75
  # than unconditional, unlike miniz and lua above, because this one is not
76
76
  # a capability of the library: it exists to *serve* the wasm runtime to a
77
77
  # browser, and under Emscripten the wasm module is the thing being
@@ -1,7 +1,7 @@
1
1
  -- Kitchen-sink scripted config. Demonstrates the whole surface: top-level
2
2
  -- flags, per-format export overrides, include() of side-effect fragments (which
3
3
  -- in turn use() a shared constants module), literal keep/rule tails, and global
4
- -- defaults. `config-lua -c fixtures/configs/lua/kitchen_sink.lua` emits
4
+ -- defaults. `config flatten -c fixtures/configs/lua/kitchen_sink.lua` emits
5
5
  -- flattened TOML that round-trips through ConfigLoader.
6
6
  --
7
7
  -- The predicates name ODD geometry because that is the detector on hand, but
@@ -2,8 +2,8 @@
2
2
  --
3
3
  -- This is a faithful translation, not a demonstration: it builds the same
4
4
  -- scene as `fixtures/configs/odd.toml`, so the two can be compared directly.
5
- -- `config-lua -c fixtures/configs/lua/odd.lua` and
6
- -- `config-flatten -c fixtures/configs/odd.toml` emit equivalent TOML.
5
+ -- `config flatten -c fixtures/configs/lua/odd.lua` and
6
+ -- `config flatten -c fixtures/configs/odd.toml` emit equivalent TOML.
7
7
  --
8
8
  -- For a tour of the scripting surface itself, see kitchen_sink.lua.
9
9
  --
@@ -41,9 +41,29 @@ struct RunOptions {
41
41
  /// cannot tell those apart: an interactive interpreter has one.
42
42
  bool pager = false;
43
43
 
44
+ /// Suppress the running commentary commands write to stderr.
45
+ ///
46
+ /// On by default, and the mirror image of `pager` above: what a person
47
+ /// watching a conversion wants — what was written, what was merged, where a
48
+ /// root landed — is noise to a program that called a function and will read
49
+ /// the exit code. `src/cli/main.cpp` clears it, so somebody who typed the
50
+ /// command still gets the commentary; an embedder gets silence without
51
+ /// having to discover the member.
52
+ ///
53
+ /// It silences *narration only*. Diagnostics and the line a failing command
54
+ /// prints before it answers non-zero are not narration and are never
55
+ /// affected — a switch that hides errors is a trap rather than a setting.
56
+ /// Neither are reports the caller asked for by name (`--timing`,
57
+ /// `--size-report`): naming a report is asking for it.
58
+ ///
59
+ /// Nothing that a caller might *parse* is on that channel to begin with.
60
+ /// stdout carries the answer — the flattened document, the JSON, the path
61
+ /// to the archive — and this flag cannot turn any of it off.
62
+ bool quiet = true;
63
+
44
64
  /// Where the wasm viewer runtime is, for callers that know.
45
65
  ///
46
- /// `viewer --web` needs a directory of Emscripten output that this library
66
+ /// `viewer serve` needs a directory of Emscripten output that this library
47
67
  /// cannot build and, in an embedded process, cannot find: under the Python
48
68
  /// wheel the running executable is the interpreter, so the install-tree
49
69
  /// guess resolves to the wrong prefix entirely. The `nodehammer-web` package
@@ -60,7 +80,12 @@ struct RunOptions {
60
80
  /// code page, so a runtime under a directory with a non-ASCII name would
61
81
  /// arrive mangled. Callers that have the real encoding — nanobind's
62
82
  /// `stl/filesystem.h` caster above all — can hand it over intact.
63
- std::filesystem::path webAssets;
83
+ ///
84
+ /// Braced rather than bare: every other member here carries a default, and
85
+ /// under `-Wmissing-field-initializers` a member without one makes
86
+ /// `{.quiet = false}` -- the natural way to set one field -- a warning at
87
+ /// each call site, which `-Werror` turns into a build failure.
88
+ std::filesystem::path webAssets{};
64
89
  };
65
90
 
66
91
  /// Run one command line. Returns the exit code the executable would have.
@@ -121,7 +121,7 @@ class Config {
121
121
  /// open says nothing about a document's contents, which is what this
122
122
  /// promised to describe.
123
123
  ///
124
- /// This is what `nodehammer validate-config` does, available to a caller
124
+ /// This is what `nodehammer config validate` does, available to a caller
125
125
  /// that wants to check a config without committing to using it — an editor,
126
126
  /// a CI step, a settings dialog.
127
127
  [[nodiscard]] NH_API static DiagnosticList check(const std::filesystem::path &path);
@@ -44,7 +44,7 @@ class SemanticScene {
44
44
  /// without the enclosing type (#41 §4).
45
45
  struct ReadOptions {
46
46
  /// Explicit input format — one of the names `formats()` reports, e.g.
47
- /// "synthetic", "json", "flatbuffer", or "tgeo"/"dd4hep" where the
47
+ /// "synthetic", "json", "nhb", or "tgeo"/"dd4hep" where the
48
48
  /// backend is present. Empty means "infer from the path extension". A
49
49
  /// name this build does not have throws rather than failing to link: the
50
50
  /// format is a value, so nothing earlier could have known.
@@ -55,9 +55,10 @@ class SemanticScene {
55
55
  /// Explicit output format: "json" or "nhb". Empty means "infer from the
56
56
  /// path extension".
57
57
  ///
58
- /// The write side spells the FlatBuffer format "nhb" where the read side
59
- /// spells it "flatbuffer" — the two registries were named independently
60
- /// and `formats()` reports both rather than picking a winner.
58
+ /// The same names the read side takes. The two registries were named
59
+ /// independently and disagreed for a while — the FlatBuffer format was
60
+ /// "nhb" to write and "flatbuffer" to read, so `formats()` listed both
61
+ /// and a caller had to know which direction it was facing.
61
62
  std::string format;
62
63
  };
63
64
 
@@ -16,7 +16,7 @@ You do not normally call that. Installing this package alongside `nodehammer` is
16
16
  what makes
17
17
 
18
18
  ```console
19
- $ nodehammer viewer --web
19
+ $ nodehammer viewer serve
20
20
  ```
21
21
 
22
22
  open the viewer in a browser: the command stages a servable directory from this
@@ -6,7 +6,7 @@ serving it is the library's job, and this only answers the question the library
6
6
  cannot answer for itself.
7
7
 
8
8
  That question is worth spelling out, because it is the whole reason this package
9
- exists as a separate distribution. ``nodehammer viewer --web`` needs a directory
9
+ exists as a separate distribution. ``nodehammer viewer serve`` needs a directory
10
10
  of Emscripten output, and it finds one by walking a ladder --- ``--web-assets``,
11
11
  then ``NODEHAMMER_WEB_ASSETS``, then whatever the calling program supplies, then
12
12
  ``<executable>/../share/nodehammer/web``. Under a wheel the last rung is wrong:
@@ -113,7 +113,7 @@ NODEHAMMER_WERROR = "OFF"
113
113
  provider = "scikit_build_core.metadata.setuptools_scm"
114
114
 
115
115
  # ── the dependency on nodehammer-web ─────────────────────────────────────────
116
- # `viewer --web` needs a runtime no native build can produce, so it comes from a
116
+ # `viewer serve` needs a runtime no native build can produce, so it comes from a
117
117
  # sibling distribution. That is a plain dependency rather than an extra: the wasm
118
118
  # never runs unless asked, so a headless install pays 2.9 MB and nothing else,
119
119
  # and "the GUI works after pip install nodehammer" is worth more than that.
@@ -25,8 +25,14 @@ def main() -> int:
25
25
  is the whole reason the option exists: reaching this function means a person
26
26
  typed a command at a shell, which is the one situation where taking over
27
27
  their terminal until they press q is the helpful thing to do.
28
+
29
+ ``quiet`` is inverted for the same reason and points the same way. The
30
+ progress a command reports on stderr is written for somebody watching it
31
+ happen, and here somebody is. ``-q`` still turns it off, exactly as it does
32
+ for the compiled executable -- which sets both of these identically
33
+ (``src/cli/main.cpp``), so the two front doors behave the same.
28
34
  """
29
- return run(sys.argv[1:], pager=True)
35
+ return run(sys.argv[1:], pager=True, quiet=False)
30
36
 
31
37
 
32
38
  if __name__ == "__main__":
@@ -14,6 +14,13 @@ here::
14
14
  if code != 0:
15
15
  ...
16
16
 
17
+ Two streams, and the split is what makes this callable rather than only
18
+ typeable. **stdout is the answer** -- the flattened config, the JSON, the path
19
+ to the archive that was written. **stderr is everything about producing it** --
20
+ diagnostics, and the running commentary a person watching would want. ``quiet``
21
+ silences the commentary and defaults to on here, because reaching this function
22
+ means a program called it. Diagnostics are never silenced.
23
+
17
24
  Output goes to the process's stdout and stderr at the file-descriptor level,
18
25
  not through ``sys.stdout`` -- the commands print from C++. In a notebook that
19
26
  means it lands in the terminal the kernel was started from rather than in the
@@ -36,7 +43,7 @@ __all__ = ["run"]
36
43
  def _web_runtime_dir() -> str:
37
44
  """Where the ``nodehammer-web`` package put the wasm viewer runtime.
38
45
 
39
- ``viewer --web`` needs a directory of Emscripten output that this wheel does
46
+ ``viewer serve`` needs a directory of Emscripten output that this wheel does
40
47
  not carry -- it is a separate ``py3-none-any`` distribution, so a headless
41
48
  install can drop it and a GUI one can have it without either being a
42
49
  different build. C++ cannot find it: under a wheel the running executable is
@@ -72,7 +79,7 @@ def _web_runtime_dir() -> str:
72
79
  return ""
73
80
 
74
81
 
75
- def run(args: Sequence[str] | None = None, *, pager: bool = False) -> int:
82
+ def run(args: Sequence[str] | None = None, *, pager: bool = False, quiet: bool = True) -> int:
76
83
  """Run one command line and return the exit code the executable would give.
77
84
 
78
85
  :param args: the arguments *after* the program name, as
@@ -87,15 +94,32 @@ def run(args: Sequence[str] | None = None, *, pager: bool = False) -> int:
87
94
  replaces this process's file descriptor 1 and then blocks until someone
88
95
  quits ``less``. The console script turns it on, because there a person
89
96
  really did type the command.
97
+ :param quiet: suppress the progress and summary lines commands write to
98
+ stderr -- ``Writing odd.glb ...``, ``root <dir>``, ``wrote flat.toml``.
99
+ On by default, and off in the console script, for exactly the reason
100
+ ``pager`` is the other way round: that commentary is for a person
101
+ watching the work, and a caller of this function is not one.
102
+
103
+ It hides narration only. Diagnostics and the line a failing command
104
+ prints before it answers non-zero always come through, because a switch
105
+ that hides errors is a trap; so do reports asked for by name
106
+ (``--timing``, ``--size-report``). Nothing a caller might *parse* is on
107
+ that stream in the first place.
108
+
109
+ ``["-v", "convert", ...]`` turns the commentary back on from the
110
+ arguments, which is the form to reach for when the caller does not own
111
+ this call -- a test harness, a notebook cell being debugged.
90
112
 
91
113
  :returns: 0 on success, non-zero otherwise. A command that could not do its
92
114
  job reports the reason on stderr and answers with a code, exactly as the
93
- executable does -- it does not raise.
115
+ executable does -- it does not raise. ``config validate`` answers this
116
+ way too: an invalid document is a report on stdout *and* a non-zero
117
+ code, so a caller never has to scrape a stream to learn the verdict.
94
118
 
95
119
  :raises nodehammer.Error: only for a failure that escaped a command body,
96
120
  which is a defect rather than a diagnosis.
97
121
 
98
- ``viewer --web`` is told where the wasm runtime is, if the ``nodehammer-web``
122
+ ``viewer serve`` is told where the wasm runtime is, if the ``nodehammer-web``
99
123
  package is installed alongside this one -- see :func:`_web_runtime_dir`. That
100
124
  is a default and not an override: ``--web-assets`` and
101
125
  ``NODEHAMMER_WEB_ASSETS`` still win, so a locally built runtime can be tried
@@ -107,4 +131,4 @@ def run(args: Sequence[str] | None = None, *, pager: bool = False) -> int:
107
131
  """
108
132
  if args is None:
109
133
  args = sys.argv[1:]
110
- return _nodehammer.cli_run([str(a) for a in args], pager, _web_runtime_dir())
134
+ return _nodehammer.cli_run([str(a) for a in args], pager, quiet, _web_runtime_dir())
@@ -7,7 +7,7 @@ parts a static check *can* see:
7
7
  - every posture directory carries the shell, the worker script and both
8
8
  backend runtimes (a missing bundle is a blank canvas at runtime);
9
9
  - each one is self-describing: an `nh_runtime.json` naming the schema id the
10
- bundles were built against, which is what `nodehammer viewer --web` checks
10
+ bundles were built against, which is what `nodehammer viewer serve` checks
11
11
  before serving a directory it was merely pointed at;
12
12
  - the application posture has no sidecar — that absence *is* what selects
13
13
  application mode in `index.html`;
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- """Run `viewer --web`, fetch everything it serves, and stop it.
2
+ """Run `viewer serve`, fetch everything it serves, and stop it.
3
3
 
4
4
  The staged root and the server agree or they do not, and the only cheap proof is
5
5
  to ask the server for every file the runtime is supposed to contain. A browser
@@ -62,8 +62,14 @@ def _await_url(lines: queue.Queue, seen: list[str]) -> str:
62
62
  if line is None:
63
63
  fail("the command exited before serving anything; output:\n" + "".join(seen))
64
64
  seen.append(line)
65
- if line.startswith("serving "):
66
- return line.split(None, 1)[1].strip()
65
+ # The URL arrives alone on stdout, with the banner around it on stderr:
66
+ # `viewer serve` puts it there precisely so a caller does not have to
67
+ # find it inside a sentence. This stream has both merged, so the URL is
68
+ # the line that *is* one -- matching a prefix would be matching the
69
+ # narration, which is the half free to be reworded.
70
+ candidate = line.strip()
71
+ if candidate.startswith(("http://", "https://")):
72
+ return candidate
67
73
 
68
74
 
69
75
  def _get(url: str) -> tuple[int, int]:
@@ -82,7 +88,7 @@ def main() -> None:
82
88
  if len(sys.argv) < 2:
83
89
  sys.exit(__doc__)
84
90
 
85
- command = [*sys.argv[1:], "viewer", "--web", "--no-browser", "--port", "0"]
91
+ command = [*sys.argv[1:], "viewer", "serve", "--no-browser", "--port", "0"]
86
92
  print("$ " + " ".join(command), flush=True)
87
93
 
88
94
  # stderr is merged in rather than discarded: the ladder's explanation goes
@@ -19,6 +19,12 @@ same inputs always hash to the same name — the archive is named
19
19
  `project.<content-hash>.nhproj` so republishing cache-busts for free while an
20
20
  unchanged publication keeps its URL.
21
21
 
22
+ `nodehammer project pack` is the shipped way to build one of these, and produces
23
+ the same shape from the same `buildArchiveWorkingSet` walk. This script stays for
24
+ the wasm dev loop and the Pages build, which run against an Emscripten tree
25
+ without necessarily having a native `nodehammer` binary to call — and which want
26
+ the content-hashed name that `pack` does not generate.
27
+
22
28
  Usage:
23
29
  scripts/make_nhproj.py <scene> <out-dir>
24
30
 
@@ -16,26 +16,6 @@
16
16
  namespace nodehammer {
17
17
  namespace {
18
18
 
19
- constexpr std::string_view kNhr = "nhr";
20
-
21
- // @TODO: Potentially unify this with other occurrences
22
- [[nodiscard]] std::string lowerExtension(const std::filesystem::path &path) {
23
- std::string ext = path.extension().string();
24
- std::transform(ext.begin(), ext.end(), ext.begin(),
25
- [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
26
- return ext;
27
- }
28
-
29
- /// `.nhr` and `.nhr.zst`. The compound form needs the second extension checked
30
- /// explicitly, since `path.extension()` only ever reports the last one.
31
- [[nodiscard]] bool isNhrPath(const std::filesystem::path &path) {
32
- const auto ext = lowerExtension(path);
33
- if (ext == ".nhr") {
34
- return true;
35
- }
36
- return ext == ".zst" && lowerExtension(path.stem()) == ".nhr";
37
- }
38
-
39
19
  void appendUnique(std::vector<std::string> &out, std::string_view name) {
40
20
  if (std::find(out.begin(), out.end(), name) == out.end()) {
41
21
  out.emplace_back(name);
@@ -66,9 +46,11 @@ RenderScene RenderScene::read(std::span<const std::byte> nhr) {
66
46
 
67
47
  std::span<const std::string_view> RenderScene::formats() {
68
48
  static const std::vector<std::string> owned = [] {
69
- // `nhr` first because it is the only format this type can also *read*;
70
- // the exporters follow in registration order.
71
- std::vector<std::string> out{std::string{kNhr}};
49
+ // Straight off the registry, in registration order. `nhr` used to be
50
+ // prepended here by hand, because it was dispatched by `write` rather
51
+ // than registered -- which is exactly what made this list and the CLI's
52
+ // disagree. It is an exporter now, so there is one source.
53
+ std::vector<std::string> out;
72
54
  const auto registry = ir::RenderExporterRegistry::makeDefault();
73
55
  for (const auto &exp : registry.exporters()) {
74
56
  appendUnique(out, exp->formatName());
@@ -83,20 +65,6 @@ void RenderScene::write(const std::filesystem::path &path, const OutputConfig &o
83
65
  const WriteOptions &options) const {
84
66
  const auto &scene = api::sceneOrThrow(*this, "RenderScene::write");
85
67
 
86
- // The render IR's own format is not in the exporter registry — nothing in
87
- // the CLI writes one — so it is dispatched here, ahead of the registry that
88
- // would otherwise report it as unknown.
89
- // @TODO: Change the above and include it in the registry, so the CLI can write it too.
90
- if (options.format == kNhr || (options.format.empty() && isNhrPath(path))) {
91
- try {
92
- const auto bytes = ir::renderSceneToBytes(scene);
93
- detail::zstd_io::writeBytesToFile(path, bytes);
94
- return;
95
- } catch (const std::exception &e) {
96
- api::rethrowAsError(e, codes::kFatalExportWriteFailed, path.string());
97
- }
98
- }
99
-
100
68
  const auto registry = ir::RenderExporterRegistry::makeDefault();
101
69
  const auto *exporter = registry.resolve(path, options.format);
102
70
  if (exporter == nullptr) {