Skip to content

Commit 5ef7cd2

Browse files
feat: install + OS integration + full test/bench pyramid + widget (#38)
Realises the "install Neurophone on phone, integrate with OS, deploy full testing and benching" task end-to-end: Build / deps - Pin rand/rand_distr to versions compatible with ndarray-rand 0.16 (workspace was previously broken: the rand 0.10/0.9 cross-version trait collision left lsm and esn uncompilable). Subcrate implementations - Replaced the sensors/, bridge/, llm/ stub crates with real but minimal implementations: per-channel IIR filters + windowed feature extractor; salience/urgency encoder with NL description; LlmBackend trait with a deterministic MockBackend so the rest of the workspace is testable without a 700 MB model file. Testing pyramid (28 → 139 tests, 0 failures) - Per-module unit tests in every crate. - Point-to-point integration tests at crate boundaries. - End-to-end pipeline tests through neurophone-core composing the real sensors + lsm + esn + bridge + llm crates. - Aspect tests: concurrency (Arc<Mutex<...>>), timing, error paths, resource bounds. - Lifecycle tests: init / start / run / shutdown / restart. Bench coverage (8 criterion targets) - sensors_bench, bridge_bench, llm_bench, claude_bench, esn_bench, lsm_bench (existing), neurophone_bench (existing), pipeline_bench (new E2E sensor → LLM step bench). - TESTING-REPORT.adoc updated with median timings and frame-budget analysis (full non-LLM pipeline ~2.6 ms vs 20 ms 50 Hz budget). Home-screen widget - NeurophoneAppWidget (provider) + NeurophoneWidgetActions (state IPC) + NeurophoneWidgetConfigureActivity (first-run config). - 3×2 cell layout: power toggle, refresh, salience progress bar, "Ask NeuroPhone" button. - res/xml/neurophone_widget_info.xml, layout, drawables, strings. OS integration - NeurophoneService: foreground service that owns the sensor → neural → LLM loop, registers SensorManager listeners at SENSOR_DELAY_GAME, computes a salience signal and pushes it to the widget every 1 s. - BootReceiver restarts the service after reboot if the user had it on. - AndroidManifest wired with FOREGROUND_SERVICE_DATA_SYNC, POST_NOTIFICATIONS, RECEIVE_BOOT_COMPLETED, WAKE_LOCK; intent filters for ASSIST, ACTION_SEND text/plain, deep link neurophone://query?q=... . - MainActivity.handleEntryIntent() handles widget tap / share / ASSIST / deep-link entry. - scripts/install-on-phone.sh — workstation ADB installer (build APK, push model, grant runtime perms, start service). - scripts/install-termux.sh — on-device Termux CLI installer. - scripts/start-on-boot.sh — Termux:Boot hook. - scripts/uninstall.sh — clean removal in either mode. - docs/OS_INTEGRATION.adoc documents every integration surface. Limitations - Cannot physically install on the user's phone from this sandbox (no ADB / network path to a device); user runs install-on-phone.sh from their workstation. APK build itself requires Android NDK + SDK, which is not present in this environment, but all Rust code builds and tests cleanly on host. https://claude.ai/code/session_012opuP3HehkjDkF1XQ8nFex Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3229a57 commit 5ef7cd2

49 files changed

Lines changed: 3004 additions & 72 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 24 additions & 61 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ repository = "https://github.com/hyperpolymath/neurophone"
2222
# Core neural network
2323
ndarray = { version = "0.17", features = ["rayon", "serde"] }
2424
ndarray-rand = "0.16"
25-
rand = "0.10"
26-
rand_distr = "0.6"
25+
rand = "0.9"
26+
rand_distr = "0.5"
2727
rayon = "1.12"
2828

2929
# Serialization

TESTING-REPORT.adoc

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,95 @@ The `test_lsm_reset` test runs for ~140 seconds due to:
318318
The Neurophone project builds and passes all tests after fixing the rand 0.9 API migration issues. The codebase is functional but has some architectural warnings related to async/await patterns in the Android JNI bindings that should be addressed for future Rust edition compatibility.
319319

320320
The neurosymbolic pipeline (LSM -> ESN -> Bridge -> LLM) is working correctly as demonstrated by the integration tests.
321+
322+
== Test Pyramid Expansion (May 2026)
323+
324+
The suite was expanded from 28 tests in a single crate to *139 tests across
325+
the full workspace*, organised by the standard testing-pyramid layers:
326+
327+
[cols="1,1,4"]
328+
|===
329+
|Layer | Examples | Files
330+
331+
|*Unit* | per-module asserts on invariants
332+
| `crates/<c>/src/lib.rs#tests`
333+
334+
|*Point-to-point integration* | one-crate boundary at a time
335+
| `crates/sensors/tests/integration_pipeline.rs`,
336+
`crates/bridge/tests/integration_encode.rs`,
337+
`crates/llm/tests/integration_backend.rs`,
338+
`crates/lsm/tests/integration_lsm.rs`,
339+
`crates/esn/tests/integration_esn.rs`,
340+
`crates/claude-client/tests/integration_routing.rs`
341+
342+
|*End-to-end* | sensor → LSM → ESN → bridge → LLM
343+
| `crates/neurophone-core/tests/integration_pipeline.rs`
344+
345+
|*Aspect* | concurrency / timing / error paths / resource bounds
346+
| `crates/neurophone-core/tests/aspect_concurrency.rs`,
347+
`crates/{sensors,bridge}/tests/aspect_lifecycle.rs`
348+
349+
|*Lifecycle* | init → start → run → shutdown → restart
350+
| `crates/neurophone-core/tests/lifecycle.rs`
351+
352+
|*Property* | proptest on configs and event spaces
353+
| `crates/neurophone-core/tests/property_test.rs`
354+
|===
355+
356+
Bench coverage was extended in the same way: *eight* `criterion` bench
357+
crates now exist (`lsm_bench`, `esn_bench`, `sensors_bench`, `bridge_bench`,
358+
`llm_bench`, `claude_bench`, `neurophone_bench`, `pipeline_bench`).
359+
360+
=== Bench Results (host x86_64, release, criterion)
361+
362+
These are reference numbers — phone numbers will differ but the relative
363+
shape is what matters for budgeting the 50 Hz frame (20 ms).
364+
365+
[cols="3,2,3"]
366+
|===
367+
|Bench | Time (median) | Notes
368+
369+
| `iir_lowpass_step_3ch` | 33.9 ns | per-sample
370+
| `iir_highpass_step_3ch` | 68.1 ns | per-sample
371+
| `windowed_features_cap50` | 328 ns | mean+var+L2
372+
| `pipeline_ingest/accelerometer_3ch` | 186 ns | per-sample
373+
| `pipeline_50hz_full_second` | 9.5 µs | 50 ingests + features
374+
| `bridge_encode/lsm100_esn50` | 791 ns |
375+
| `bridge_encode/lsm512_esn300` | 1.73 µs | target reservoir sizes
376+
| `bridge_encode/lsm2048_esn1024` | 5.24 µs |
377+
| `llm_mock_generate/short` | 150 ns | mock backend
378+
| `llm_mock_generate/long_256` | 1.90 µs |
379+
| `claude/complexity_estimation` | 635 ns | offline scoring
380+
| `claude/should_use_cloud_decision` | 1.06 ns |
381+
| `esn_step/50` | 2.07 µs | small reservoir
382+
| `esn_step/300` | 34.2 µs | target reservoir
383+
| `esn_step/1000` | 335 µs | stress
384+
| `lsm_step_10x10x10` | 2.62 ms | 1000 neurons (target)
385+
| `e2e_to_bridge_step` | 5.18 µs | sensor → bridge
386+
| `e2e_pipeline/sensor_to_llm_step` | 6.59 µs | full pipeline w/ mock LLM
387+
|===
388+
389+
*Frame-budget analysis (50 Hz = 20 ms):*
390+
391+
The full non-LLM pipeline (sensor → LSM → ESN → bridge) runs in
392+
~2.6 ms on host, leaving ~17 ms for LLM token emission. Real Llama 3.2
393+
1B Q4 on Dimensity 8350 is ~50–100 ms/token, so streaming tokens
394+
naturally span multiple sample frames — the 50 Hz inner loop never
395+
blocks on the LLM.
396+
397+
== OS Integration
398+
399+
* `scripts/install-on-phone.sh` — workstation-side ADB installer (APK +
400+
optional model push + permission grant + service start).
401+
* `scripts/install-termux.sh` — on-device Termux installer for the CLI path.
402+
* `scripts/start-on-boot.sh` — Termux:Boot hook for CLI persistence.
403+
* `scripts/uninstall.sh` — clean uninstall in both modes.
404+
* `docs/OS_INTEGRATION.adoc` — full integration surface documentation.
405+
406+
== Home-Screen Widget
407+
408+
Live App Widget at `android/app/src/main/java/ai/neurophone/widget/`.
409+
Power-toggle, salience meter, "Ask NeuroPhone" button, configuration
410+
activity. State pushed from `NeurophoneService` every 1 s via
411+
`SharedPreferences` + broadcast refresh. Boot persistence via
412+
`BootReceiver`.

0 commit comments

Comments
 (0)