# Work Summary: Native Runtime Refactor, Shell Wrapper Cleanup & Stdin Protocol Fixes (2026-02-20) ## Problem Python sensors (e.g., `python_example.counter_sensor`) were being executed by `/bin/sh` instead of `python3`, causing `import: not found` errors. Root cause was two-fold: 1. **All sensors hardcoded to `core.builtin` runtime** — `PackComponentLoader::load_sensors()` ignored the sensor YAML's `runner_type` field and assigned every sensor the `core.builtin` runtime. 2. **`core.builtin` runtime defaulted to `/bin/sh`** — The `InterpreterConfig` default was `/bin/sh`, so runtimes with no `execution_config` (like `core.builtin`) got shell as their interpreter, causing Python scripts to be interpreted as shell. Additionally, the shell wrapper script had a hard dependency on `python3` for JSON secret parsing, and pre-existing security test failures were discovered caused by a stdin protocol conflict between parameters and secrets. ## Changes ### Architecture: Remove "builtin" runtime concept Replaced the separate `core.builtin` runtime with `core.native`. Runtime detection is now purely data-driven via `execution_config` in the runtime table — no special-cased runtime names. - **Deleted** `packs/core/runtimes/sensor_builtin.yaml` - **Fixed** `packs/core/runtimes/native.yaml` — removed `/bin/sh -c` interpreter; empty `execution_config` signals direct binary execution - **Changed** `InterpreterConfig` default `binary` from `"/bin/sh"` to `""` (empty = native) - **Updated** `interval_timer_sensor.yaml` — `runner_type: native` ### Sensor runtime resolution - **Fixed** `PackComponentLoader::load_sensors()` — reads `runner_type` from each sensor's YAML definition and resolves to the correct runtime via `resolve_runtime()`. Defaults to `native`. - **Added** `resolve_runtime()` method returning `(Id, String)` — both ID and ref - **Updated** runtime mappings — `builtin`, `standalone` → `core.native` - **Updated** `load_core_pack.py` — per-sensor runtime resolution from YAML instead of hardcoded `core.builtin` - **Updated** `seed_core_pack.sql` — references `core.native` instead of `core.builtin` ### Shell wrapper: remove Python dependency The shell wrapper script (`generate_wrapper_script`) previously used `python3 -c` to parse JSON secrets from stdin into a bash associative array. This created a hard dependency on Python being installed, which violates the principle that core services must operate without supplemental runtimes. - **Replaced** runtime JSON parsing with Rust-side secret injection — secrets are now embedded directly as `ATTUNE_SECRETS['key']='value'` entries at script generation time - **Added** `bash_single_quote_escape()` helper for safe bash string embedding - **Changed** wrapper execution from `bash -c