A full implementation and runtime execution of the Needle 2 transformer model (27 layers, 4-lane mHC routing, Engram Rings, CQ2/CQ4 hybrid quantization, and an Attention Pooling Confidence Head) written in pure JavaScript (ES5/ES6)[cite: 7]. The engine runs directly inside the web browser of a vintage 2016 Android 5.1.1 (Lollipop) device with only 1 GB RAM, achieving functional and operational parity with the official native C / Python reference implementation[cite: 3, 4, 7].
- Device: Lenovo Vibe C (A2020a40 / a1z)[cite: 7]
- SoC: Qualcomm Snapdragon 210 (MSM8909)[cite: 7]
- CPU: Quad-core ARM Cortex-A7 @ 1.1 GHz (32-bit ARMv7-A)[cite: 7]
- RAM: 1 GB LPDDR3 (~250–350 MB available application headroom)[cite: 7]
- OS: Android 5.1.1 (Lollipop, API Level 22)[cite: 7]
- Execution Environment: Firefox for Android (Gecko Engine) / Android System WebView[cite: 7]
- Host Machine: x86_64 Linux (Lubuntu)[cite: 7]
- Server: Standalone Node.js LAN server (zero external dependencies)[cite: 7]
- Reference Oracle: QPython 3 / Native C ARMv7 ELF binary (
needle-native-complete-oracle, A31)[cite: 3, 7] - Toolchain: Node.js, Android Debug Bridge (
adb), sed/awk[cite: 7]
The Needle 2 architecture was specifically engineered for extremely resource-constrained edge devices[cite: 7]:
- 27 Transformer Layers with hybrid quantization (CQ2 on linear projection layers, CQ4 on feed-forward blocks)[cite: 7].
- Multi-Head Routing (mHC 4-lane): Per-layer information stream branching, gating, and merging[cite: 7].
- Engram Rings: Local n-gram associative memory mechanism using circular accumulator buffers (taps 0..3)[cite: 7].
- Attention Pooling Confidence Head: Real-time confidence scoring module evaluating the necessity of structured tool calls[cite: 1, 2, 4, 7].
- FP32 Drift & Reasoning Loops: Accumulation of subtle floating-point differences between hardware ARM NEON assembly and JS engines (SpiderMonkey/V8) became pronounced by Layer 13, causing greedy decoding to get trapped in repetitive reasoning loops[cite: 7].
- Out of Memory (OOM / SIGSEGV exit -11): Strict Low-Memory Killer (LMK) heuristics on Android 5.1 immediately terminated any browser tab exceeding the low memory ceiling[cite: 7].
- Structured Grammar Constraints: Enforcing strict, deterministic JSON generation for function arguments without relying on bulky native parsing engines or GBNF libraries[cite: 7].
- Engram Rolling Hash Parity (
nativeEngramHash):- Harmonized the n-gram rolling hash implementation to match the native C arithmetic bit-for-bit[cite: 7].
- NEON CQ2 Sub4 Vector Kernel (
nativeIntDotCQ2Neon):- Replaced the naive scalar CQ2 kernel with an exact software emulation of the native packed NEON assembly dot product (
s01/s23signed accumulations), eliminating floating-point divergence[cite: 7].
- Replaced the naive scalar CQ2 kernel with an exact software emulation of the native packed NEON assembly dot product (
- CQ2 Dispatch Routing:
- Explicitly directed the following projection layers through the bit-exact NEON CQ2 kernel[cite: 7]:
engram.[01].(key_proj|value_proj)[cite: 7]layer.6.out_proj[cite: 7]layer.8.out_proj[cite: 7]layer.11.out_proj[cite: 7]
- Explicitly directed the following projection layers through the bit-exact NEON CQ2 kernel[cite: 7]:
- Engram Ring Native Cache (
EngramRing):- Migrated memory caching to
int8 + scale(32-wide quantization blocks) and resolved tap0 pipeline ordering: RAWV vectors are quantized and cached prior to evaluating taps 0..3[cite: 7].
- Migrated memory caching to
- Attention Pooling Head Integration:
- Introduced
engine.confidenceReset()prior to prompt framing prefill[cite: 7]. - Polled
engine.confidenceValue()during envelope finalization to populate the confidence metric[cite: 1, 2, 4, 7].
- Introduced
- Tokenizer Output Normalization (
normalizeGeneratedPieces):- Decoded SentencePiece whitespace markers (
\u2581) into standard spaces[cite: 2, 4, 7]. - Stripped byte-level newline delimiters
<0x0A>and applied a safe.trim()[cite: 2, 4, 7]. - Ensured
"reason": nullis cleanly assigned whenever no text generation precedes the tool call[cite: 2, 4, 7].
- Decoded SentencePiece whitespace markers (
- Rejection of WebAssembly / WASM SIMD:
- Rationale: Legacy mobile browsers on Android 5.1.1 (32-bit Cortex-A7) either lack WASM SIMD instructions entirely or suffer from instability and SIGSEGV crashes under heavy heap pressure[cite: 7]. Pure ES5/ES6 JavaScript using Typed Arrays (
Float32Array,Int8Array) guarantees universal execution[cite: 7].
- Rationale: Legacy mobile browsers on Android 5.1.1 (32-bit Cortex-A7) either lack WASM SIMD instructions entirely or suffer from instability and SIGSEGV crashes under heavy heap pressure[cite: 7]. Pure ES5/ES6 JavaScript using Typed Arrays (
- Rejection of Diagnostic Tracing Hooks in Production:
- Rationale: Trace hooks (
lanes=newLanes; if(this._a44Trace)...) used during diagnostic isolation caused significant garbage collection churn and latency[cite: 7]. These were stripped from the production runtime[cite: 7].
- Rationale: Trace hooks (
- Rejection of Hardcoded Reasoning / Branch Forcing:
- Rationale: The execution runtime does not artificially force tool call transitions[cite: 7]. The model autonomously decides between
<think>,<tool_call>, or regular conversational tokens based on native logits[cite: 7].
- Rationale: The execution runtime does not artificially force tool call transitions[cite: 7]. The model autonomously decides between
- Rejection of Arbitrary Confidence Calibration:
- Rationale: Rather than applying arbitrary linear scalers to artificially match native scores, the raw floating-point score is surfaced transparently (
confidence_calibrated_to_native: false)[cite: 1, 2, 4, 7].
- Rationale: Rather than applying arbitrary linear scalers to artificially match native scores, the raw floating-point score is surfaced transparently (
| Parameter | Native C / Python Oracle (QPython3 A31) | Pure-JS Engine (Firefox A2020a40) | Parity Status |
|---|---|---|---|
| Tool Execution | set_light({"on": true})[cite: 3, 7] |
set_light({"on": true})[cite: 1, 2, 4, 7] |
Bit-exact Match[cite: 7] |
| Direct Command ("Turn the lights on.") | Skip reasoning (reasoning: null)[cite: 3, 7] |
Skip reasoning (reasoning: null)[cite: 1, 7] |
Identical Flow[cite: 7] |
| Ambiguous Command ("It's too dark to see.") | Enters <think> state[cite: 3, 7] |
Enters <think> state[cite: 2, 4, 7] |
Identical Flow[cite: 7] |
| Reasoning Prefix (first 12 tokens) | "User complains about darkness. set_light..."[cite: 3, 7] |
"User complains about darkness. set_light..."[cite: 4, 7] |
Bit-exact Match[cite: 7] |
| Reasoning Suffix | "...to 'on' for better visibility."[cite: 3, 7] |
"...on to 'on' to reduce brightness."[cite: 4, 7] |
Float drift (L13)[cite: 7] |
| Confidence Output | 0.0004 (rounded to 4 decimals)[cite: 3, 7] |
0.00000417 (raw FP64 post-rollout)[cite: 4, 7] |
Fully Active[cite: 7] |
| RAM Footprint | ~25 MB (peak_ram_mb: 25.0)[cite: 3, 7] |
~35–45 MB[cite: 7] | Stable / Zero Crash[cite: 7] |
.
├── index.html # Web runner, UI, constrained decoding & token cleanup
├── engine-full.js # Patched Pure-JS runtime (A55 NEON CQ2 & Engram int8 cache)
├── cact-full.js # Quantized weights parser & loader (.cact)
├── tokenizer-full.js # Pure-JavaScript SentencePiece tokenizer
├── needle2.cact # Quantized model weights binary (~13.7 MB)
├── needle2_lan_server.js # Zero-dependency local LAN HTTP server
├── README.md # Project documentation
├── reports/ # Technical Markdown reports & evaluation logs
│ ├── a31-native-complete-oracle.md
│ ├── a54_layer8_diagnostic_report.md
│ └── a55_layer11_cq2_parity_report.md
└── diagnostics/ # Native ARMv7 binaries & Python validation probes (A31-A55)
[cite: 7]
node needle2_lan_server.js . 8000[cite: 7]
- Connect the mobile device to the same Wi-Fi network as the host machine[cite: 7].
- Identify the host IP address (
hostname -I)[cite: 7]. - Open the browser on the Android phone and navigate to[cite: 7]:
http://<HOST_IP>:8000/index.html
[cite: 7] 4. Input a prompt (e.g., "It's too dark to see." or "Turn the lights on.") and tap Run[cite: 1, 4, 7].