SideFX Houdini customization package
git clone https://git.lucas.co/hou-control.git
otls: add the HDA audit report
Headless audit of every library in otls/ from 2026-09-14: hollow files,
dummy children of missing types, cook failures, unread parameters,
bypassed children, versions and naming, plus a per-definition appendix.
A status note at the top records which findings have since been fixed.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
otls-audit.md | 469 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 469 insertions(+)
diff --git a/otls-audit.md b/otls-audit.md
new file mode 100644
index 0000000..6ad8915
--- /dev/null
+++ b/otls-audit.md
@@ -0,0 +1,469 @@
+# otls audit
+
+Audit of every HDA in `otls/`, run 2026-09-14 against Houdini 22.0.429 (Indie) with `hython`. Every library was loaded, every definition was instantiated with its contents unlocked, and every SOP was cooked once with a 10x10 polygon grid on each required input. The audit script and raw JSON are not in the repo; the method and its limits are at the end.
+
+> **Status after the audit.** The 20 hollow files were deleted (`d3d8cb3`). The dummy children in section 2 were replaced with their current types in 29 assets (`aef363e`, `28dfa29`); what remains are the SideFX Labs nodes, the five `l_s_galante::im_cull` uses, and the `lucas::dev::` children in `im_bevel` and `im_relax`. Sections 3 to 7 are untouched.
+
+| | count |
+|---|---|
+| `.hdalc` files | 218 |
+| definitions that load | 198 (190 SOP, 6 COP, 2 Object) |
+| hollow files (index only, no definition) | 20 |
+| nodes containing dummy children of a missing type | 33 |
+| SOPs that fail to cook on a plain grid | 6 |
+| SOPs with parameters nothing reads | 81 |
+| nodes with bypassed children | 18 |
+| nodes with embedded help | 1 |
+
+## 1. Hollow files are rename leftovers, not lost work
+
+All 20 hollow files are 83 bytes: an `INDX` header and nothing else. That is what Houdini leaves behind when a definition is moved to a new library file with **Save As / Copy to new file**, and every one of them has a successor on disk. The `developer_*` files were already hollow in the first commit (2025-12-09); the backups in `otls/backup/` show the originals were renamed on 2025-04-24 between 16:25 and 16:43. The three `im_*` files were hollowed by commits `1e159f7` (2025-12-12) and `75e0c07` (2025-12-31), which also touched the consolidated `im_cull` and `im_count`.
+
+Successor found by matching the backup's parameter set against live definitions (exact match unless noted):
+
+| hollow file | latest backup | successor |
+|---|---|---|
+| `developer_clip` | bak2 | `developer_attribute_clip` |
+| `developer_combine` | bak3 | `developer_attribute_combine` |
+| `developer_composite` | bak2 | `developer_attribute_composite` |
+| `developer_constant` | bak2 | `developer_attribute_constant` |
+| `developer_promote` | bak1 | `developer_attribute_promote` |
+| `developer_concentrate` | bak3 | `developer_vector_concentrate` |
+| `developer_diffuse (1.0 and 1.1)` | 1.1_bak4 | `developer_float_diffuse 1.1` |
+| `developer_direct` | bak10 | `developer_vector_direct` |
+| `developer_detangle` | bak3 | `developer_surface_detangle` |
+| `developer_remesh` | bak3 | `developer_surface_remesh 1.0` |
+| `developer_subdivide` | bak1 | `developer_surface_subdivide` |
+| `developer_initialize` | bak3 | `developer_attribute_initialize (identical), itself later split` |
+| `developer_attribute_initialize` | bak12 | `developer_float_initialize + developer_vector_initialize (split, half the parms each)` |
+| `developer_migrate 1.1` | bak2 | `developer_float_migrate 1.1 + developer_vector_migrate 1.1 (split)` |
+| `developer_map` | bak3 | `developer_attribute_remap (by function: attribute + domain in/out ranges)` |
+| `developer_miasma` | bak1 | `developer_volume_miasma (backup had no parms)` |
+| `im_count_primitives` | git f3872bf | `im_count (consolidated)` |
+| `im_cull_points` | git 23c1076 | `im_cull (consolidated)` |
+| `im_cull_primitives` | git 23c1076 | `im_cull (consolidated)` |
+
+No live node embeds any of the hollow type names, so deleting the 20 files loses nothing. Two side notes: `.gitignore` lists `*otls/backup`, but 277 backup files were committed before that rule and are still tracked. And `otls/` holds two `im_soft_transform.1.1.hdalc.bak.*` files plus a stray `sop_l_s_galante.matcap_shader.1.0.hdalc.hda *.otl` (a mangled filename that still contains a valid `im_soft_transform 1.1` definition, duplicating the real file).
+
+## 2. 33 nodes contain dummy children whose type no longer exists
+
+This is the finding that matters. When an HDA's child refers to a type Houdini cannot find, it creates an **Embedded dummy**: a node with the right name and parameters but no contents. It raises no error and no warning. It just outputs nothing, so everything downstream of it inside the asset is fed empty geometry. The HDAs carry fallback paths to the libraries the types came from, but all of them point at repos that no longer exist (`/Users/lucas/src/hou-immutable-methods`, `/Users/lsgalante/src/houdini-studio-utils`, `/home/lsgalante/src/houdini-studio-utils`, `/Users/lucas/src/hou-developer`), and SideFX Labs is not installed in this Houdini.
+
+Missing types, how many child nodes use them, and the current node that replaces them:
+
+| missing type | uses | replacement on disk |
+|---|---|---|
+| `im_delete::1.0` | 23 | lsgalante::im_delete::1.1 |
+| `l_s_galante::im_delete::1.1` | 8 | lsgalante::im_delete::1.1 |
+| `im_ramp_color::1.0` | 5 | lsgalante::im_color_ramp::1.1 (probably) |
+| `l_s_galante::im_cull::1.0` | 5 | lsgalante::im_cull::1.0 |
+| `im_orient::1.0` | 4 | lsgalante::im_orient::1.1 |
+| `im_normal::1.0` | 3 | lsgalante::im_normal::1.0 |
+| `im_reindex::1.0` | 3 | lsgalante::im_reindex::1.0 |
+| `labs::edge_smooth::1.0` | 2 | none: SideFX Labs |
+| `im_ramp_scalar::1.0` | 2 | lsgalante::im_float_ramp::1.0 or im_ramp_float (probably) |
+| `im_grid::1.0` | 2 | lsgalante::im_grid::1.0 |
+| `labs::attribute_normalize_vector::1.0` | 1 | none: SideFX Labs |
+| `l_s_galante::im_sort::1.0` | 1 | lsgalante::im_sort::1.1 |
+| `shapeshifter_time_switch::1.0` | 1 | lsgalante::developer_time_switch::1.0 |
+| `shapeshifter_detangle::1.0` | 1 | lsgalante::developer_surface_detangle::1.0 |
+| `lsg::dev::IMMMinvertmesh::1.0` | 1 | none found |
+| `im_skeletonize::1.0` | 1 | lsgalante::im_skeletonize::1.0 |
+| `lucas::dev::mycurve::1.0` | 1 | none found |
+| `lucas::dev::morphorotatevec::1.0` | 1 | none found |
+| `labs::quickmaterial::2.2` | 1 | none: SideFX Labs |
+| `im_best_fit::1.0` | 1 | none found |
+| `lucas::dev::imguide::1.0` | 1 | lsgalante::im_guide::1.1 (probably) |
+| `lucas::dev::imnearpoints::1.0` | 1 | none found (im_neighbours?) |
+
+Affected nodes and the dummy children inside them:
+
+| node | dummy children |
+|---|---|
+| `gem_mold_flange::1.0` | `/im_delete1` (im_delete::1.0), `/im_delete2` (im_delete::1.0), `/isolate_largest` (l_s_galante::im_cull::1.0), `/leading_edge_refine/leading_edge_smooth` (labs::edge_smooth::1.0), `/leading_edge_refine/im_cull2` (l_s_galante::im_cull::1.0), `/extract_longest` (l_s_galante::im_cull::1.0), `/im_delete3` (im_delete::1.0), `/im_delete5` (im_delete::1.0), `/im_delete6` (im_delete::1.0), `/im_sort` (l_s_galante::im_sort::1.0) |
+| `im_layout::1.0` | `/im_reindex1` (im_reindex::1.0), `/im_grid1` (im_grid::1.0), `/im_orient1` (im_orient::1.0), `/im_delete1` (l_s_galante::im_delete::1.1), `/im_orient2` (im_orient::1.0), `/im_reindex2` (im_reindex::1.0), `/im_grid2` (im_grid::1.0), `/im_orient3` (im_orient::1.0) |
+| `gem_mold_preprocess::1.0` | `/smooth_partition_boundary` (labs::edge_smooth::1.0), `/im_normal1` (im_normal::1.0), `/edge_collapse/im_normal1` (im_normal::1.0), `/im_reindex1` (im_reindex::1.0), `/im_delete1` (im_delete::1.0) |
+| `gem_mold_solver::1.0` | `/dopnet1/sopsolver1/im_normal1` (im_normal::1.0), `/dopnet1/sopsolver1/shapeshifter_time_switch1` (shapeshifter_time_switch::1.0), `/dopnet1/sopsolver1/shapeshifter_detangle1` (shapeshifter_detangle::1.0), `/im_delete1` (im_delete::1.0) |
+| `gem_skeleprep::1.0` | `/straight_skeleton_3d1` (im_skeletonize::1.0), `/im_delete1` (im_delete::1.0), `/im_delete2` (im_delete::1.0) |
+| `im_line::1.0` | `/im_ramp_color1` (im_ramp_color::1.0), `/im_delete1` (l_s_galante::im_delete::1.1), `/im_delete2` (l_s_galante::im_delete::1.1) |
+| `gem_flange_merge::1.0` | `/im_cull2` (l_s_galante::im_cull::1.0), `/im_delete1` (im_delete::1.0) |
+| `gem_halo_merge::1.0` | `/im_cull2` (l_s_galante::im_cull::1.0), `/im_delete1` (im_delete::1.0) |
+| `gem_mold_shell::1.0` | `/curvature_to_thickness` (im_ramp_scalar::1.0), `/im_delete1` (im_delete::1.0) |
+| `gem_sprue::1.0` | `/im_delete1` (im_delete::1.0), `/im_delete2` (im_delete::1.0) |
+| `gem_sprue_cut::1.0` | `/im_delete1` (im_delete::1.0), `/im_delete2` (im_delete::1.0) |
+| `gem_sprue_select::1.1` | `/im_delete1` (im_delete::1.0), `/im_delete2` (im_delete::1.0) |
+| `im_attractor::1.0` | `/im_ramp_color1` (im_ramp_color::1.0), `/im_ramp_scalar1` (im_ramp_scalar::1.0) |
+| `im_bevel::1.0` | `/mycurve1` (lucas::dev::mycurve::1.0), `/morphorotatevec1` (lucas::dev::morphorotatevec::1.0) |
+| `im_split::1.0` | `/im_delete1` (l_s_galante::im_delete::1.1), `/im_delete2` (l_s_galante::im_delete::1.1) |
+| `developer_surface_remesh::1.0` | `/subnet1/im_ramp_color1` (im_ramp_color::1.0) |
+| `developer_vector_direct::1.0` | `/attribute_normalize_vector1` (labs::attribute_normalize_vector::1.0) |
+| `gem_mold_root::1.0` | `/im_delete4` (im_delete::1.0) |
+| `gem_mold_structure::1.0` | `/im_orient1` (im_orient::1.0) |
+| `gem_partition::1.0` | `/IMMMinvertmesh1` (lsg::dev::IMMMinvertmesh::1.0) |
+| `gem_sprue_funnel::1.0` | `/im_delete2` (im_delete::1.0) |
+| `gem_sprue_select::1.0` | `/im_delete1` (im_delete::1.0) |
+| `gem_support::1.0` | `/volume_blast/im_delete1` (im_delete::1.0) |
+| `im_distrubution::1.0` | `/im_ramp_color1` (im_ramp_color::1.0) |
+| `im_onion::1.0` | `/quickmaterial1` (labs::quickmaterial::2.2) |
+| `im_orient::1.0` | `/im_best_fit1` (im_best_fit::1.0) |
+| `im_permutate::1.0` | `/im_delete1` (l_s_galante::im_delete::1.1) |
+| `im_point_proximity::1.0` | `/imguide1` (lucas::dev::imguide::1.0) |
+| `im_promote::1.0` | `/im_delete1` (l_s_galante::im_delete::1.1) |
+| `im_relax::1.0` | `/imnearpoints1` (lucas::dev::imnearpoints::1.0) |
+| `im_sort::1.0` | `/im_delete1` (im_delete::1.0) |
+| `im_stain::1.0` | `/im_ramp_color1` (im_ramp_color::1.0) |
+| `im_twist::1.0` | `/im_delete1` (l_s_galante::im_delete::1.1) |
+
+The fix is manual: open each asset, replace the dummy with the current type (parameters and wiring have to be carried over by hand, since the dummy keeps the old parameter values), and save. The whole `gem_mold_*` chain, `im_layout` and `im_line 1.0` are the worst hit.
+
+## 3. Cook failures
+
+Four `developer_*` nodes fail regardless of input because a VOP inside them does not compile. These are real breaks, not a consequence of the test input:
+
+- `developer_attribute_composite::1.0`: `composite/attribvop1`: Reference to undefined variable: op_start
+- `developer_float_migrate::1.1`: `proximity/attribvop1`: Reference to undefined variable: fval
+- `developer_vector_direct::1.0`: `multiplier/attribvop1`: No matching function for vector chs(string). Candidates are: string chs(string), string chs(string; float)
+- `developer_vector_from_scalar::1.0`: `near_pts/attribvop1`: Reference to undefined variable: P
+
+`im_pose` and `im_sample` also fail, but only because they need a second input the test did not supply. Eight GEM and IM nodes warn that a for-each block has no pieces, which is expected on a plain grid. Nothing else errored or warned.
+
+## 4. Parameters nothing reads
+
+For each top-level parameter the audit looked for a channel reference from any child parameter, a textual reference (`ch("../name")`, `chs`, `chramp`, the tuple component names such as `rangex`) in any child parameter or expression, or a button callback. 215 parameters on 81 SOPs matched none of those. Some may be read only by a `hidewhen` rule or a menu script, which this check does not count, so treat the list as candidates. Names like `newparameter` (4 nodes) and the `rnd_float_*` set on `developer_select`, where the wrangle reads `floatcov` instead, are clearly stale.
+
+| node | unreferenced parameters |
+|---|---|
+| `developer_analysis::1.0` | `enable_round`, `round_places`, `enable_prev` |
+| `developer_attribute_clip::1.0` | `range` |
+| `developer_attribute_combine::1.0` | `input_0`, `type_0`, `weight_0`, `x_0`, `y_0`, `z_0`, `input_1`, `type_1`, `weight_1`, `x_1`, `y_1`, `z_1` |
+| `developer_attribute_composite::1.0` | `output_attr` |
+| `developer_attribute_constant::1.0` | `class` |
+| `developer_attribute_remap::1.0` | `class`, `type` |
+| `developer_charge::1.0` | `release`, `amount` |
+| `developer_embryo::1.0` | `source` |
+| `developer_expire::1.0` | `attr` |
+| `developer_float_concentrate::1.0` | `global_intensity`, `global_cutoff`, `connectivity_depth` |
+| `developer_float_diffuse::1.1` | `connect_depth` |
+| `developer_float_migrate::1.1` | `connect_depth`, `infl`, `multiplier`, `multi_infl` |
+| `developer_lead::1.0` | `amt` |
+| `developer_normalize::1.0` | `type`, `method` |
+| `developer_select::1.0` | `rnd_float_coverage`, `rnd_float_coverage_seed`, `rnd_float_variation`, `rnd_float_variation_seed`, `rnd_float_multiplier`, `newparameter` |
+| `developer_surface_detangle::1.0` | `developer_iteration_ct` |
+| `developer_surface_remesh::1.0` | `transfer_method` |
+| `developer_surface_suture::1.0` | `distthresh`, `fusionthresh` |
+| `developer_vector_conform::1.0` | `weight_ramp` |
+| `developer_vector_direct::1.0` | `bias_vec_type`, `bias_vec_const`, `bias_vec_attr`, `bias_vec_infl`, `bias_scalar_unity`, `bias_scalar_infl`, `unity_multi_infl`, `unity_multi_attr` |
+| `developer_vector_migrate::1.1` | `input_reference`, `infl`, `multi`, `multi_infl`, `simbi_enable`, `simbi_amt`, `simbi_tol`, `simbi_weight` |
+| `developer_vector_unify::1.0` | `bias_radius`, `biasdisteff`, `biasm_ulti_attr` |
+| `developer_weight::1.0` | `attr`, `multiplier` |
+| `gem_build_area::1.0` | `machine`, `dimensions` |
+| `gem_mold_solver::1.0` | `thickness`, `frame` |
+| `gem_orient::1.0` | `group`, `start_dir` |
+| `gem_partition::1.0` | `filecachename` |
+| `gem_partition::1.1` | `filecachename` |
+| `gem_positioner::1.0` | `selection` |
+| `gem_prim_painter::1.1` | `sel_method` |
+| `gem_prim_painter::1.2` | `sel_method` |
+| `gem_screw::1.0` | `metric_length`, `unit_per_mm` |
+| `gem_sprue_select::1.0` | `mode` |
+| `gem_support::1.0` | `group_avoid` |
+| `im_arrow::1.0` | `attr`, `origin` |
+| `im_attractor::0.9` | `falloff_x`, `falloff_y`, `falloff_z`, `bias` |
+| `im_attractor::1.1` | `bias`, `falloff_x`, `falloff_y`, `falloff_z` |
+| `im_attribute_adjust::1.0` | `class`, `type` |
+| `im_bounds::1.0` | `ndivs` |
+| `im_bounds::1.1` | `boundsgeogrp`, `ndivs` |
+| `im_cache::1.0` | `ids`, `version`, `versions` |
+| `im_color::1.0` | `attr_out`, `l`, `a`, `b` |
+| `im_color_ramp::1.1` | `outputattrib`, `encoding`, `amt_a`, `chg_a`, `amt_b`, `chg_b`, `amt_c`, `chg_c` |
+| `im_connectivity::1.0` | `piece_attr`, `geo_class`, `gate` |
+| `im_count::1.0` | `elemattribtoggle`, `elemattrib`, `detailattribtoggle` |
+| `im_curl::1.0` | `axis_method`, `axis_preset`, `axis_attr` |
+| `im_curl::1.1` | `axis_method`, `axis_preset`, `axis_attr` |
+| `im_curl::1.2` | `axis_method`, `axis_preset`, `axis_attr` |
+| `im_distance::1.0` | `dir_attr` |
+| `im_distrubution::1.0` | `attrib`, `resolution` |
+| `im_float_ramp::1.0` | `component` |
+| `im_gate::1.0` | `attr_out` |
+| `im_group::1.0` | `promote` |
+| `im_guide::1.1` | `shape`, `origin_attr`, `dir_attr` |
+| `im_line::1.0` | `length`, `scale` |
+| `im_line::1.1` | `boundsscale`, `ramp`, `preset`, `add_preset`, `rm_preset` |
+| `im_membership::1.0` | `attr` |
+| `im_neighbours::1.0` | `method`, `normal_filter_toggle`, `normal_filter_tol` |
+| `im_normal::1.0` | `docompute` |
+| `im_number_generator::1.0` | `number` |
+| `im_onion::1.0` | `frame` |
+| `im_orient::1.0` | `partition_attr`, `source_vector_group_class`, `analysis_method_method` |
+| `im_permutate::1.0` | `class`, `type` |
+| `im_point::1.0` | `newparameter` |
+| `im_prim_distance::1.0` | `group`, `startpts`, `transferattributes`, `transfergroups` |
+| `im_ramp_float::1.0` | `component` |
+| `im_random_walk::1.0` | `component` |
+| `im_reindex::1.0` | `class` |
+| `im_relax::1.0` | `size`, `to`, `dense`, `seed` |
+| `im_remap::1.1` | `orangei`, `nrangei`, `rename`, `newname`, `keeporiginal` |
+| `im_sample::1.0` | `group`, `newparameter` |
+| `im_shadowbox::1.0` | `side_0`, `side_1`, `side_2`, `side_3`, `side_4`, `side_5` |
+| `im_sharpen::1.0` | `rad` |
+| `im_shrink::1.1` | `curvedir` |
+| `im_sort::1.0` | `start_method`, `output` |
+| `im_sort::1.1` | `method`, `start_method`, `output` |
+| `im_stain::1.0` | `enable`, `attr`, `coloring`, `coloring_attr`, `color`, `length`, `ramp`, `presets`, `new`, `remove`, `colors`, `randomize`, `encoding`, `handles`, `labelparm`, `l`, `l_change`, `labelparm2`, `a`, `a_change`, `labelparm3`, `b`, `b_change` |
+| `im_star::1.0` | `len_attr` |
+| `im_transfer::1.0` | `pt_attrs`, `newparameter` |
+| `im_valence::1.0` | `nbr_attr_name` |
+| `im_vdb_visualize_intersections::1.0` | `help` |
+
+The two Object assets (`gem_build_area`, `im_cam`) are excluded: their unreferenced parameters are the standard object transform and render pages.
+
+## 5. Bypassed children
+
+Bypassed nodes inside a locked asset are usually experiments that were never removed:
+
+- `developer_analysis::1.0`: `/round`
+- `developer_metamax::1.0`: `/timeshift1`
+- `developer_surface_remesh::1.0`: `/subnet1/tridivide1`
+- `developer_volume_miasma::1.0`: `/isooffset1`
+- `gem_mold_flange::1.0`: `/collapse_suite/P_avg1`
+- `gem_mold_preprocess::1.0`: `/remove_stray_prims1`
+- `gem_mold_root::1.0`: `/root_shape/group2`, `/root_shape/dissolve1`
+- `gem_mold_shell::1.0`: `/polyreduce1`
+- `gem_sprue::1.0`: `/blast4`
+- `gem_sprue_preprocess::1.0`: `/compile_end1`, `/compile_begin1`, `/color1`
+- `im_attractor::0.9`: `/attribwrangle4`, `/im_remap1`
+- `im_attractor::1.1`: `/attribwrangle4`, `/im_remap1`
+- `im_neighbours::1.0`: `/groupcombine3`
+- `im_relax::1.0`: `/attribwrangle1`
+- `im_remap::1.1`: `/attribdelete1`
+- `im_shadowbox::1.0`: `/triangulate1`
+- `im_sharpen::1.0`: `/attribblur1`
+- `im_valence::1.0`: `/group1`
+
+## 6. Versions, names, menus, help
+
+- **15 types ship more than one version**, all marked current, so the tab menu offers every one of them: `developer_surface_remesh` (1.0, 1.1), `gem_partition` (1.0, 1.1), `gem_prim_painter` (1.0, 1.1, 1.2), `gem_sprue_select` (1.0, 1.1), `im_attractor` (0.9, 1.0, 1.1), `im_bounds` (1.0, 1.1), `im_curl` (1.0, 1.1, 1.2), `im_line` (1.0, 1.1), `im_orient` (1.0, 1.1), `im_remap` (1.0, 1.1), `im_select` (1.0, 2.0), `im_shrink` (1.0, 1.1), `im_soft_transform` (1.0, 1.1), `im_sort` (1.0, 1.1), `im_transfer` (1.0, 1.1). `im_attractor` goes 0.9, 1.0, 1.1. Old versions that no scene needs can be removed, or hidden from the tab menu.
+- `im_grid` and `gem_build_area` each exist in two categories (COP and SOP; Object and SOP). That is legal, just easy to confuse.
+- **Typo**: `im_distrubution`.
+- **Labels**: `im_cam` is labelled `im_cam` and `im_blaster` is `IM Blaster` with two spaces. Every other label matches its type name.
+- **Tab menu**: `im_vdb_visualize_intersections` has no submenu, so it lands at the top level of the tab menu. Everything else sorts into `Immutable Methods/*`, `Developer/*` or `GEM`; two nodes sit in bare `Immutable Methods` and 20 in bare `Developer`.
+- **Help**: only `gem_orient` has embedded help. The other 197 have none.
+- **Icons**: 8 nodes carry their own SVG (`im_bounds`, `im_box`, `im_count`, `im_cull`, `im_grid`, `im_line 1.1`, `im_skeletonize`, `im_wave`); the rest use the generic subnet icon.
+- **Hardcoded paths**: `im_multistain` reads two preset JSON files from `/Users/lucas/src/hou-immutable-methods/presets/`, which does not exist on this machine. Separately, 29 nodes carry fallback library paths to the old repos listed in section 2; those are informational and only consulted when a type is missing.
+- **Event scripts**: all 23 `PythonModule` sections and the three Python `OnCreated`/`OnUpdated` handlers compile. `developer_solver` and `gem_mold_solver` have HScript `OnCreated` handlers, correctly flagged as non-Python.
+- **Saved with**: every asset's embedded fallbacks reference `/opt/hfs21.0`, i.e. they were last saved from Houdini 21.0.
+
+## 7. developer.md is out of date
+
+The operator list in `developer.md` uses **Scalar** names (`Scalar Diffuse`, `Scalar Migrate`, …) while the nodes on disk are `developer_float_*`, and it still lists `Subdivide`, `Remesh`, `Detangle`, `Combine`, `Constant` under their pre-rename names. 34 of its 55 items match no node, and 30 of the 51 `developer_*` nodes on disk are not in the document, including the whole `developer_attribute_*` family, `developer_time_analysis`, `developer_charge` and `developer_release`.
+
+## Method and limits
+
+- Loaded with `hou.hda.definitionsInFile` and `installFile`, then instantiated in `/obj`, `/img` and a scratch geo. Locked HDAs in `hython` load their contents lazily, so each instance was unlocked with `allowEditingOfContents()` before inspection. Nothing was saved.
+- Dummy children were identified by `type().definition().libraryFilePath() == "Embedded"`.
+- Cooking used a 10x10 grid on each required input at frame 1. Nodes built for the SOP solver were cooked standalone, so an error there means the VEX does not compile, not that the node misbehaves in a sim. Nothing was cooked on real input data.
+- The parameter-usage check is textual and channel-reference based. It does not follow `hidewhen`, menu scripts, or Python that builds a parameter name at runtime.
+- Viewer states, handles, and anything needing `hou.ui` were not exercised.
+
+## Appendix: every definition
+
+| type | ver | category | submenu | inputs | parms | unread | dummies | bypassed | cook |
+|---|---|---|---|---|---|---|---|---|---|
+| `developer_analysis` | 1.0 | Sop | Developer | 1-2 | 13 | 3 | 0 | 1 | ok |
+| `developer_attribute_clip` | 1.0 | Sop | Developer/Attribute | 0-1 | 1 | 1 | 0 | 0 | ok |
+| `developer_attribute_combine` | 1.0 | Sop | Developer/Attribute | 1-2 | 18 | 12 | 0 | 0 | ok |
+| `developer_attribute_composite` | 1.0 | Sop | Developer/Attribute | 1-2 | 5 | 1 | 0 | 0 | failed |
+| `developer_attribute_constant` | 1.0 | Sop | Developer/Attribute | 0-1 | 5 | 1 | 0 | 0 | ok |
+| `developer_attribute_promote` | 1.0 | Sop | Developer/Attribute | 1-1 | 4 | 0 | 0 | 0 | ok |
+| `developer_attribute_remap` | 1.0 | Sop | Developer/Attribute | 0-1 | 9 | 2 | 0 | 0 | ok |
+| `developer_charge` | 1.0 | Sop | Developer | 0-1 | 2 | 2 | 0 | 0 | ok |
+| `developer_core` | 1.0 | Sop | Developer/Volume | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `developer_cull` | 1.0 | Sop | Developer | 1-1 | 2 | 0 | 0 | 0 | ok |
+| `developer_develop` | 1.0 | Sop | Developer | 1-1 | 4 | 0 | 0 | 0 | ok |
+| `developer_embryo` | 1.0 | Sop | Developer | 0-2 | 14 | 1 | 0 | 0 | ok |
+| `developer_expire` | 1.0 | Sop | Developer | 1-1 | 1 | 1 | 0 | 0 | ok |
+| `developer_float_bleed` | 1.0 | Sop | Developer/Float | 0-1 | 2 | 0 | 0 | 0 | ok |
+| `developer_float_concentrate` | 1.0 | Sop | Developer/Float | 1-1 | 8 | 3 | 0 | 0 | ok |
+| `developer_float_diffuse` | 1.1 | Sop | Developer/Float | 1-1 | 9 | 1 | 0 | 0 | ok |
+| `developer_float_initialize` | 1.0 | Sop | Developer/Float | 0-1 | 6 | 0 | 0 | 0 | ok |
+| `developer_float_migrate` | 1.1 | Sop | Developer/Float | 1-1 | 13 | 4 | 0 | 0 | failed |
+| `developer_id` | 1.0 | Sop | Developer | 1-1 | 1 | 0 | 0 | 0 | ok |
+| `developer_lead` | 1.0 | Sop | Developer | 1-1 | 3 | 1 | 0 | 0 | ok |
+| `developer_measure` | 1.0 | Sop | Developer | 1-1 | 36 | 0 | 0 | 0 | ok |
+| `developer_metamax` | 1.0 | Sop | Developer | 1-1 | 3 | 0 | 0 | 1 | ok |
+| `developer_normalize` | 1.0 | Sop | Developer | 1-1 | 4 | 2 | 0 | 0 | ok |
+| `developer_panel` | 1.0 | Sop | Developer | 0-1 | 3 | 0 | 0 | 0 | ok |
+| `developer_region_center` | 1.0 | Sop | Developer | 1-1 | 3 | 0 | 0 | 0 | ok |
+| `developer_release` | 1.0 | Sop | Developer | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `developer_select` | 1.0 | Sop | Developer | 1-1 | 31 | 6 | 0 | 0 | ok |
+| `developer_solver` | 1.0 | Sop | Developer | 0-1 | 8 | 0 | 0 | 0 | ok |
+| `developer_submute_begin` | 1.0 | Sop | Developer | 1-1 | 2 | 0 | 0 | 0 | ok |
+| `developer_submute_end` | 1.0 | Sop | Developer | 2-2 | 2 | 0 | 0 | 0 | ok |
+| `developer_surface_adapt` | 1.0 | Sop | Developer/Surface | 1-1 | 8 | 0 | 0 | 0 | ok |
+| `developer_surface_detangle` | 1.0 | Sop | Developer/Surface | 1-3 | 4 | 1 | 0 | 0 | ok |
+| `developer_surface_open` | 1.0 | Sop | Developer/Surface | 1-1 | 0 | 0 | 0 | 0 | ok |
+| `developer_surface_remesh` | 1.0 | Sop | Developer/Surface | 1-1 | 60 | 1 | 1 | 1 | ok |
+| `developer_surface_remesh` | 1.1 | Sop | Developer/Surface | 1-1 | 59 | 0 | 0 | 0 | ok |
+| `developer_surface_subdivide` | 1.0 | Sop | Developer/Surface | 1-1 | 3 | 0 | 0 | 0 | ok |
+| `developer_surface_suture` | 1.0 | Sop | Developer/Surface | 2-2 | 2 | 2 | 0 | 0 | ok |
+| `developer_time` | 1.0 | Sop | Developer/Time | 0-0 | 2 | 0 | 0 | 0 | ok |
+| `developer_time_analysis` | 1.0 | Sop | Developer/Time | 1-1 | 2 | 0 | 0 | 0 | ok |
+| `developer_time_ramp` | 1.0 | Sop | Developer/Time | 0-0 | 3 | 0 | 0 | 0 | ok |
+| `developer_time_switch` | 1.0 | Sop | Developer/Time | 1-2 | 4 | 0 | 0 | 0 | ok |
+| `developer_vector_concentrate` | 1.0 | Sop | Developer/Vector | 1-1 | 8 | 0 | 0 | 0 | ok |
+| `developer_vector_conform` | 1.0 | Sop | Developer/Vector | 0-1 | 6 | 1 | 0 | 0 | ok |
+| `developer_vector_direct` | 1.0 | Sop | Developer/Vector | 1-1 | 12 | 8 | 1 | 0 | failed |
+| `developer_vector_from_scalar` | 1.0 | Sop | Developer/Vector | 1-1 | 6 | 0 | 0 | 0 | failed |
+| `developer_vector_initialize` | 1.0 | Sop | Developer/Vector | 0-1 | 8 | 0 | 0 | 0 | ok |
+| `developer_vector_migrate` | 1.1 | Sop | Developer/Vector | 1-1 | 14 | 8 | 0 | 0 | ok |
+| `developer_vector_rotate` | 1.0 | Sop | Developer/Vector | 0-1 | 5 | 0 | 0 | 0 | ok |
+| `developer_vector_unify` | 1.0 | Sop | Developer/Vector | 1-1 | 17 | 3 | 0 | 0 | ok |
+| `developer_vitality` | 1.0 | Sop | Developer | 1-2 | 1 | 0 | 0 | 0 | ok |
+| `developer_volume_miasma` | 1.0 | Sop | Developer/Volume | 0-1 | 0 | 0 | 0 | 1 | ok |
+| `developer_weight` | 1.0 | Sop | Developer | 0-1 | 2 | 2 | 0 | 0 | ok |
+| `gem_border` | 1.0 | Cop | GEM | 0-1 | 0 | 0 | 0 | 0 | - |
+| `gem_build_area` | 1.0 | Object | GEM | 0-1 | 77 | 74 | 0 | 0 | - |
+| `gem_build_area` | 1.0 | Sop | GEM | 0-1 | 3 | 2 | 0 | 0 | ok |
+| `gem_flange_merge` | 1.0 | Sop | GEM | 2-2 | 3 | 0 | 2 | 0 | ok |
+| `gem_flange_monoid` | 1.0 | Sop | GEM | 1-1 | 0 | 0 | 0 | 0 | ok |
+| `gem_graph` | 1.0 | Cop | GEM | 0-2 | 29 | 4 | 0 | 0 | - |
+| `gem_grid` | 1.0 | Cop | GEM | 0-1 | 6 | 0 | 0 | 0 | - |
+| `gem_halo_merge` | 1.0 | Sop | GEM | 2-2 | 3 | 0 | 2 | 0 | ok |
+| `gem_mold_flange` | 1.0 | Sop | GEM | 1-1 | 8 | 0 | 10 | 1 | ok |
+| `gem_mold_preprocess` | 1.0 | Sop | GEM | 1-1 | 3 | 0 | 5 | 1 | ok |
+| `gem_mold_root` | 1.0 | Sop | GEM | 1-2 | 4 | 0 | 1 | 2 | ok |
+| `gem_mold_shell` | 1.0 | Sop | GEM | 1-1 | 4 | 0 | 2 | 1 | ok |
+| `gem_mold_solver` | 1.0 | Sop | GEM | 0-1 | 12 | 2 | 4 | 0 | ok |
+| `gem_mold_structure` | 1.0 | Sop | GEM | 1-1 | 0 | 0 | 1 | 0 | ok |
+| `gem_orient` | 1.0 | Sop | GEM | 1-1 | 5 | 2 | 0 | 0 | ok |
+| `gem_page` | 1.0 | Cop | GEM | 0-0 | 3 | 0 | 0 | 0 | - |
+| `gem_partition` | 1.0 | Sop | GEM | 1-1 | 6 | 1 | 1 | 0 | ok |
+| `gem_partition` | 1.1 | Sop | GEM | 1-1 | 7 | 1 | 0 | 0 | ok |
+| `gem_positioner` | 1.0 | Sop | GEM | 1-1 | 2 | 1 | 0 | 0 | ok |
+| `gem_prim_painter` | 1.0 | Sop | GEM | 0-1 | 4 | 0 | 0 | 0 | ok |
+| `gem_prim_painter` | 1.1 | Sop | GEM | 0-1 | 9 | 1 | 0 | 0 | ok |
+| `gem_prim_painter` | 1.2 | Sop | GEM | 0-1 | 9 | 1 | 0 | 0 | ok |
+| `gem_scale` | 1.0 | Sop | GEM | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `gem_screw` | 1.0 | Sop | GEM | 0-1 | 4 | 2 | 0 | 0 | ok |
+| `gem_skeleprep` | 1.0 | Sop | GEM | 1-1 | 0 | 0 | 3 | 0 | ok |
+| `gem_sprue` | 1.0 | Sop | GEM | 1-1 | 3 | 0 | 2 | 1 | ok |
+| `gem_sprue_cut` | 1.0 | Sop | GEM | 1-1 | 3 | 0 | 2 | 0 | ok |
+| `gem_sprue_funnel` | 1.0 | Sop | GEM | 1-2 | 3 | 0 | 1 | 0 | ok |
+| `gem_sprue_preprocess` | 1.0 | Sop | GEM | 1-2 | 0 | 0 | 0 | 3 | ok |
+| `gem_sprue_select` | 1.0 | Sop | GEM | 1-1 | 2 | 1 | 1 | 0 | ok |
+| `gem_sprue_select` | 1.1 | Sop | GEM | 1-1 | 7 | 0 | 2 | 0 | ok |
+| `gem_sprue_shell` | 1.0 | Sop | GEM | 1-2 | 3 | 0 | 0 | 0 | ok |
+| `gem_support` | 1.0 | Sop | GEM | 0-1 | 8 | 1 | 1 | 0 | ok |
+| `gem_text_box` | 1.0 | Cop | GEM | 0-1 | 24 | 0 | 0 | 0 | - |
+| `im_arrow` | 1.0 | Sop | Immutable Methods/Utility | 0-1 | 2 | 2 | 0 | 0 | ok |
+| `im_attractor` | 0.9 | Sop | Immutable Methods/Deform | 1-1 | 11 | 4 | 0 | 2 | ok |
+| `im_attractor` | 1.0 | Sop | Immutable Methods/Deform | 0-2 | 21 | 0 | 2 | 0 | ok |
+| `im_attractor` | 1.1 | Sop | Immutable Methods/Move | 1-2 | 11 | 4 | 0 | 2 | ok |
+| `im_attribute_adjust` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 4 | 2 | 0 | 0 | ok |
+| `im_bend` | 1.0 | Sop | Immutable Methods/Move | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_bevel` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 0 | 0 | 2 | 0 | ok |
+| `im_blaster` | 1.0 | Sop | Immutable Methods/Layout | 1-1 | 9 | 0 | 0 | 0 | ok |
+| `im_bounds` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 14 | 1 | 0 | 0 | ok |
+| `im_bounds` | 1.1 | Sop | Immutable Methods/Analysis | 0-1 | 14 | 2 | 0 | 0 | ok |
+| `im_box` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 11 | 0 | 0 | 0 | ok |
+| `im_cache` | 1.0 | Sop | Immutable Methods/IO | 0-1 | 14 | 3 | 0 | 0 | ok |
+| `im_cam` | 1.0 | Object | Immutable Methods | 0-1 | 65 | 63 | 0 | 0 | - |
+| `im_clip` | 1.0 | Sop | Immutable Methods/Topology | 0-1 | 4 | 0 | 0 | 0 | ok |
+| `im_color` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 9 | 4 | 0 | 0 | ok |
+| `im_color_ramp` | 1.1 | Sop | Immutable Methods/Attribute | 0-1 | 15 | 8 | 0 | 0 | ok |
+| `im_connectivity` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 3 | 3 | 0 | 0 | ok |
+| `im_constant` | 1.0 | Sop | Immutable Methods/Attribute | 0-0 | 3 | 0 | 0 | 0 | ok |
+| `im_copy` | 1.0 | Sop | Immutable Methods/Layout | 0-2 | 2 | 0 | 0 | 0 | ok |
+| `im_count` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 6 | 3 | 0 | 0 | ok |
+| `im_cull` | 1.0 | Sop | Immutable Methods/Filter | 1-1 | 7 | 0 | 0 | 0 | ok |
+| `im_curl` | 1.0 | Sop | Immutable Methods/Deform | 0-1 | 5 | 3 | 0 | 0 | ok |
+| `im_curl` | 1.1 | Sop | Immutable Methods/Deform | 0-1 | 5 | 3 | 0 | 0 | ok |
+| `im_curl` | 1.2 | Sop | Immutable Methods/Move | 0-1 | 5 | 3 | 0 | 0 | ok |
+| `im_delete` | 1.1 | Sop | Immutable Methods/Attribute | 1-1 | 12 | 0 | 0 | 0 | ok |
+| `im_diagnostic` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 2 | 0 | 0 | 0 | ok |
+| `im_direction` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 2 | 0 | 0 | 0 | ok |
+| `im_dissolve` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 2 | 0 | 0 | 0 | ok |
+| `im_dissolve_point` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 1 | 0 | 0 | 0 | ok |
+| `im_distance` | 1.0 | Sop | Immutable Methods/Analysis | 0-2 | 4 | 1 | 0 | 0 | ok |
+| `im_distrubution` | 1.0 | Sop | Immutable Methods/Analysis | 1-2 | 20 | 2 | 1 | 0 | ok |
+| `im_dot` | 1.0 | Sop | Immutable Methods/Utility | 0-1 | 1 | 0 | 0 | 0 | ok |
+| `im_endpoints` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 4 | 0 | 0 | 0 | ok |
+| `im_evaluate_curve` | 1.0 | Sop | Immutable Methods/Topology | 0-1 | 5 | 0 | 0 | 0 | ok |
+| `im_extrude` | 1.0 | Sop | Immutable Methods/Topology | 0-1 | 8 | 0 | 0 | 0 | ok |
+| `im_fast_clip` | 1.0 | Sop | Immutable Methods/Visualize | 1-1 | 3 | 0 | 0 | 0 | ok |
+| `im_float_ramp` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 5 | 1 | 0 | 0 | ok |
+| `im_gate` | 1.0 | Sop | Immutable Methods/Filter | 0-1 | 12 | 1 | 0 | 0 | ok |
+| `im_gem` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_grid` | 1.0 | Cop | Immutable Methods | 0-1 | 6 | 0 | 0 | 0 | - |
+| `im_grid` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 9 | 0 | 0 | 0 | ok |
+| `im_group` | 1.0 | Sop | Immutable Methods/Filter | 1-2 | 10 | 1 | 0 | 0 | ok |
+| `im_group_split` | 1.0 | Sop | Immutable Methods/Filter | 0-1 | 2 | 0 | 0 | 0 | ok |
+| `im_guide` | 1.1 | Sop | Immutable Methods/Visualize | 0-1 | 9 | 3 | 0 | 0 | ok |
+| `im_inline` | 1.0 | Sop | Immutable Methods/Filter | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_invert_mesh` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 0 | 0 | 0 | 0 | ok |
+| `im_layout` | 1.0 | Sop | Immutable Methods/Layout | 0-1 | 10 | 0 | 8 | 0 | ok |
+| `im_line` | 1.0 | Sop | Immutable Methods/Create | 0-2 | 14 | 2 | 3 | 0 | ok |
+| `im_line` | 1.1 | Sop | Immutable Methods/Create | 0-2 | 15 | 5 | 0 | 0 | ok |
+| `im_lop` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_manipulator` | 1.0 | Sop | Immutable Methods/Move | 1-1 | 0 | 0 | 0 | 0 | ok |
+| `im_matcap` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 15 | 0 | 0 | 0 | ok |
+| `im_membership` | 1.0 | Sop | Immutable Methods/Analysis | 1-1 | 1 | 1 | 0 | 0 | ok |
+| `im_midpoint` | 1.0 | Sop | Immutable Methods/Analysis | 1-1 | 1 | 0 | 0 | 0 | ok |
+| `im_multistain` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 2 | 0 | 0 | 0 | ok |
+| `im_neighbours` | 1.0 | Sop | Immutable Methods/Topology | 0-1 | 12 | 3 | 0 | 1 | ok |
+| `im_normal` | 1.0 | Sop | Immutable Methods/Attribute | 1-1 | 48 | 1 | 0 | 0 | ok |
+| `im_notebook` | 1.0 | Sop | Immutable Methods/Utility | 0-1 | 1 | 0 | 0 | 0 | ok |
+| `im_number_generator` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 3 | 1 | 0 | 0 | ok |
+| `im_onion` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 6 | 1 | 1 | 0 | ok |
+| `im_orient` | 1.0 | Sop | Immutable Methods/Layout | 0-1 | 7 | 3 | 1 | 0 | ok |
+| `im_orient` | 1.1 | Sop | Immutable Methods/Layout | 0-1 | 2 | 0 | 0 | 0 | ok |
+| `im_permutate` | 1.0 | Sop | Immutable Methods/Attribute | 1-1 | 3 | 2 | 1 | 0 | ok |
+| `im_plane` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 3 | 0 | 0 | 0 | ok |
+| `im_point` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 4 | 1 | 0 | 0 | ok |
+| `im_point_mover` | 1.0 | Sop | Immutable Methods/Move | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_point_proximity` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 6 | 0 | 1 | 0 | ok |
+| `im_pose` | 1.0 | Sop | Immutable Methods/Layout | 1-1 | 0 | 0 | 0 | 0 | failed |
+| `im_prim_distance` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 4 | 4 | 0 | 0 | ok |
+| `im_prim_proximity` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 3 | 0 | 0 | 0 | ok |
+| `im_promote` | 1.0 | Sop | Immutable Methods/Attribute | 1-1 | 6 | 0 | 1 | 0 | ok |
+| `im_ramp_float` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 5 | 1 | 0 | 0 | ok |
+| `im_random_walk` | 1.0 | Sop | Immutable Methods/Topology | 0-1 | 4 | 1 | 0 | 0 | ok |
+| `im_range` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_reindex` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 3 | 1 | 0 | 0 | ok |
+| `im_relax` | 1.0 | Sop | Immutable Methods/Move | 1-1 | 5 | 4 | 1 | 1 | ok |
+| `im_remap` | 1.0 | Sop | Immutable Methods/Attribute | 0-1 | 13 | 0 | 0 | 0 | ok |
+| `im_remap` | 1.1 | Sop | Immutable Methods/Attribute | 0-1 | 18 | 5 | 0 | 1 | ok |
+| `im_remesh` | 1.0 | Sop | Immutable Methods/Topology | 0-1 | 3 | 0 | 0 | 0 | ok |
+| `im_ruler` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_sample` | 1.0 | Sop | Immutable Methods/Analysis | 0-2 | 8 | 2 | 0 | 0 | failed |
+| `im_scaffold` | 1.0 | Sop | Immutable Methods/Layout | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_scatter` | 1.0 | Sop | Immutable Methods/Layout | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_select` | 1.0 | Sop | Immutable Methods/Filter | 1-1 | 29 | 0 | 0 | 0 | ok |
+| `im_select` | 2.0 | Sop | Immutable Methods/Filter | 1-1 | 29 | 0 | 0 | 0 | ok |
+| `im_select_points` | 1.0 | Sop | Immutable Methods/Filter | 1-1 | 31 | 0 | 0 | 0 | ok |
+| `im_select_primitives` | 1.0 | Sop | Immutable Methods/Filter | 1-1 | 29 | 0 | 0 | 0 | ok |
+| `im_shadowbox` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 16 | 6 | 0 | 1 | ok |
+| `im_sharpen` | 1.0 | Sop | Immutable Methods/Move | 1-1 | 6 | 1 | 0 | 1 | ok |
+| `im_shortest_path` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 3 | 0 | 0 | 0 | ok |
+| `im_shrink` | 1.0 | Sop | Immutable Methods/Deform | 1-1 | 8 | 0 | 0 | 0 | ok |
+| `im_shrink` | 1.1 | Sop | Immutable Methods/Move | 1-1 | 9 | 1 | 0 | 0 | ok |
+| `im_skeletonize` | 1.0 | Sop | Immutable Methods/Analysis | 1-1 | 4 | 0 | 0 | 0 | ok |
+| `im_soft_transform` | 1.0 | Sop | Immutable Methods/Move | 1-2 | 1 | 0 | 0 | 0 | ok |
+| `im_soft_transform` | 1.1 | Sop | Immutable Methods/Move | 1-2 | 12 | 0 | 0 | 0 | ok |
+| `im_sort` | 1.0 | Sop | Immutable Methods/Analysis | 0-1 | 4 | 2 | 1 | 0 | ok |
+| `im_sort` | 1.1 | Sop | Immutable Methods/Topology | 0-1 | 4 | 3 | 0 | 0 | ok |
+| `im_special_square` | 1.0 | Sop | Immutable Methods/Create | 0-0 | 22 | 0 | 0 | 0 | ok |
+| `im_split` | 1.0 | Sop | Immutable Methods/Utility | 1-1 | 0 | 0 | 2 | 0 | ok |
+| `im_square` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 4 | 0 | 0 | 0 | ok |
+| `im_stain` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 26 | 23 | 1 | 0 | ok |
+| `im_star` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 6 | 1 | 0 | 0 | ok |
+| `im_switch` | 1.0 | Sop | Immutable Methods/Utility | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_transfer` | 1.0 | Sop | Immutable Methods/Attribute | 0-2 | 2 | 2 | 0 | 0 | ok |
+| `im_transfer` | 1.1 | Sop | Immutable Methods/Attribute | 0-2 | 4 | 0 | 0 | 0 | ok |
+| `im_transform` | 1.0 | Sop | Immutable Methods/Move | 0-1 | 4 | 0 | 0 | 0 | ok |
+| `im_triangle` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 1 | 0 | 0 | 0 | ok |
+| `im_twist` | 1.0 | Sop | Immutable Methods/Move | 0-1 | 2 | 0 | 1 | 0 | ok |
+| `im_valence` | 1.0 | Sop | Immutable Methods/Topology | 1-1 | 11 | 1 | 0 | 1 | ok |
+| `im_vdb_visualize_intersections` | 1.0 | Sop | | 2-2 | 2 | 1 | 0 | 0 | ok |
+| `im_vis_manager` | 1.0 | Sop | Immutable Methods/Visualize | 0-1 | 0 | 0 | 0 | 0 | ok |
+| `im_wave` | 1.0 | Sop | Immutable Methods/Create | 0-1 | 3 | 0 | 0 | 0 | ok |