Files
searchi/docs/LINUX-SPEECH-0.1.6.md
T

180 lines
10 KiB
Markdown
Raw Permalink Normal View History

# Linux speech client portability check
2026-10-13, Ubuntu 24.04 WSL x86-64. Immutable source snapshot from commit
`9bc7221`; existing isolated Cargo cache and target, locked offline dependencies.
`SEARCHI_FORCE_CPU=1` throughout. No model inference or GPU execution occurred.
Executed checks:
```sh
cargo test -p searchi-speech --locked --offline
cargo check -p searchi-cli --locked --offline
SEARCHI_TEST_PYTHON=python3 cargo test -p searchi-speech actual_subprocess_timeout_and_overflow_are_reaped --locked --offline -- --ignored --nocapture
```
Five default unit tests passed. The real owned-subprocess transport test also
passed: timeout and oversized framing reaped their child processes; only the
typed transport failure was eligible for recovery. The genuine native speech
model test remained ignored. CLI compilation passed, including the shared
speech/service/assets dependencies, without desktop dependencies.
Recorded command output: speech compilation 11.67 seconds; headless dependency
check 7.28 seconds; real transport test 0.14 seconds. These are build/test durations,
not inference or search performance measurements.
Snapshot: `/home/karl/.cache/searchi-validation/linux-source-9bc7221`.
This closes a client portability check only. It does not prove the Linux native
speech worker, model setup, runtime packaging, recognition quality, desktop UI
or GPU operation. Published Linux downloads remain version 0.1.4.
## Native runtime preparation
A normal auto runtime diagnostic build from that immutable snapshot was started in
`/home/karl/.cache/searchi-validation/speech-auto-016`. It included Vulkan
compilation and no GPU inference. It was deliberately cancelled after inspection
confirmed that it predates the relocation correction, rather than due to a wait
timeout. The exact owned builder command line was verified before terminating
its process tree; its original tool session then reported terminal exit 1.
No runtime from that incomplete build is releasable.
Inspection exposed an unverified release path: speech packaging flattened shared
libraries without checking ELF dependency closure or their build-tree lookup
paths. The builder now checks every staged ELF for origin-only RUNPATH and
declared dependencies, allowing a system Vulkan loader only for the dynamic
Vulkan module. Three builder tests passed, including rejection of build-tree
paths, missing libraries and a Vulkan dependency on the CPU worker.
The CMake configuration now gives Linux shared targets their own `$ORIGIN`
RUNPATH; this is required because executable RUNPATH is not transitive.
Actual configuration and a separate native `ggml-base` build passed in
`speech-rpath-check-016`. `readelf` verified that the resulting library has
RUNPATH `$ORIGIN`; generated executable link flags use the same path.
This narrow library check does not establish complete runtime relocation.
The original snapshot does not contain this correction. Its output must not be
released as corrected evidence. A corrected normal auto build from immutable
commit `61afa08` is now running in
`/home/karl/.cache/searchi-validation/speech-auto-61afa08`. Next: wait for its
terminal result, inspect the complete ELF closure, then validate the runtime
outside the build tree with `LD_LIBRARY_PATH` unset and forced CPU recognition.
Linux staging now invokes the same ELF closure verification after manifest,
architecture and CPU/acceleration checks. A valid inventory cannot bypass this
check; missing `readelf` also fails staging. Six targeted staging tests passed,
including inspected ELF coverage, failure propagation and Windows independence.
The same six tests subsequently passed directly on Ubuntu 24.04 (0.409 seconds).
The upcoming real CPU test fixture was prepared from the unchanged verified
English WAV (source SHA-256
`0aa1fa97d367d987bfb3bb01d7eca11db77a544552ccb8dc0a78ad74d0b496ea`).
Exact mono 16-kHz signed PCM16 samples were converted to float32 by division by
32768, preserving all 360192 samples. PCM SHA-256:
`56948226ac5a0ad4b70523a856dad0851929c7067957f339e9a5b30fc9b369ce`.
Fixture preparation succeeded; native recognition has not yet been executed.
## Headless release preparation
The locked offline Linux release build of `searchi-cli` and
`searchi-extract-worker` from source `61afa08` passed in 58.38 seconds.
The extraction helper was staged with its current source fingerprint and
verified. CLI executable: 21921224 bytes, SHA-256
`f7602d41eeab80c74e00014ab51297223eae651755707b341951c2e624807d94`.
This is compilation and provenance evidence, not a new published archive.
`tools/package_linux.py --speech-runtime PATH` now includes a verified normal
speech runtime in its isolated `speech-runtime/` directory. The worker is
executable; inventory, libraries and approved notices are included. Archive
instructions explain speech-model setup and indexing, and metadata identifies
speech as experimental. Omitting this parameter preserves reproduction of older
speech-free packages. New speech-enabled releases must provide it.
Twenty-one focused package tests passed, including archive hashes/permissions,
instructions, and rejection of internal CPU artifacts, tampering, absent notices
and invalid ELF closure while preserving an existing output. These use fixture
artifacts and do not replace the pending genuine native-runtime verification.
The same 21 packaging tests also passed directly on Ubuntu (1.317 seconds).
Package preparation from immutable source `36bd510` verified 21 normal Google
runtime records, four pinned decoder/notice records and current extraction-worker
provenance. The stripped release CLI is 17560544 bytes, SHA-256
`51523b1b20e5afcd2ea81a9c824148262f79ea8360ad411c1ce8a97278290d2f`.
Its actual `setup --help` and `embed --help` accepted the speech options used in
archive instructions. No model inference was performed in these preparation checks.
At this preparation point, native compilation and the queued relocated test
were still pending. Their completed evidence follows below.
## Completed normal runtime and genuine CPU recognition
The corrected normal auto build from source `61afa08` subsequently completed
successfully. All 25 runtime records passed origin-only ELF dependency closure.
The runtime was staged outside its build directory with 29 verified records
(including inventory and approved notices); its self-test passed with
`LD_LIBRARY_PATH` and `LD_PRELOAD` unset.
The actual Rust native integration test also passed in 79.42 seconds. It copied
the runtime to supplementary-Unicode paths, ran real recognition on all 360192
English samples twice with forced CPU, verified stable passages/source bounds,
and confirmed persistent model reuse. First/warm ASR was 29.879/38.614 seconds;
warm model loading was zero and fallback cost zero. These single shared-VM
functional timings are not a clean performance benchmark or broad quality score.
Inventory SHA-256:
`a033ed36d33c43601d219ec17e57c3e561ad6c25eee1556ffbb054f306c5e4a9`.
Worker SHA-256:
`b801b733c4212efa0afd28146df5bc6e85e9419314f5c9616355c38ebd4e7110`.
The 25 inventoried runtime files total 59234912 bytes.
Actual test log SHA-256:
`e651a80e2a980adeb309af28643cf3a33bc184899510fb7054a79327fb5900b7`.
Ignored raw evidence is in `speech-auto-61afa08/relocated-verification.json` and
`relocated-native-cpu.log` under the WSL validation cache.
Linux GPU execution, shared-service packaged speech/Google retrieval and public
archive delivery remain open. Archive construction is now underway.
The first complete archive passed all 60 extracted file/permission records and
both installed-layout self-tests, but at 109314948 bytes it exceeds Gitea's
100-MiB upload limit. SHA-256:
`9ae7fa9a203c6471cfd6bdd82ac5bf81683813c15fe652595976344fbbf96084`.
It is retained as an unpublished candidate. XZ packaging now uses a 64-MiB
dictionary (preset 9) to compress duplicate decoder/runtime code across large
ELF files; client decompression needs roughly 65 MiB. All 21 package tests
passed after this compression change. No runtime files are removed.
## Genuine packaged shared-service retrieval
The first archive's complete extracted layout then passed a genuine CPU-only
CLI integration: index the unchanged English recording, encode raw media and
recognized passages using the bundled workers, and search through Google
EmbeddingGemma 2. The known-positive request returned `semantic_speech` with
a `timestamp_ms` citation to the indexed recording and a nonempty snippet.
No build-tree loader paths or helper overrides were used; ordinary bundled
decoder discovery was exercised. This one-source derived request proves the
packaged integration, not independent relevance or precise alignment quality.
Raw report SHA-256:
`f1104fe526d3908066e5030e5ff989fc57e0aae6dea171a7b1ed20e639c38d08`.
Evidence: `headless-speech-functional-016/report.json` in the WSL validation cache.
Final recompression is underway and must preserve every packaged byte and mode
before this evidence can be applied to the upload candidate.
## Published delivery and upload configuration
Karl explicitly requested adjusting the Gitea limit instead of recompressing.
The owned recompression process was cancelled and reported terminal exit 1;
the compression change was reverted. The original fully verified 109314948-byte
archive above was published with [v0.1.6](https://tea.karlcom.de/karl/searchi/releases/tag/v0.1.6).
Public unauthenticated full-byte download matched SHA-256
`9ae7fa9a203c6471cfd6bdd82ac5bf81683813c15fe652595976344fbbf96084`.
The separate checksum is published alongside it.
Gitea now explicitly allows 256 MiB per release file. Only the `tea.karlcom.de`
nginx proxy host was changed from `100m` to `257m`, with both NPM's persistent
database and generated configuration updated after backups. nginx validation
and reload passed. The actual 109-MB upload succeeded over the protected LAN
HTTPS origin, retaining certificate verification and the Infisical-managed
origin header. Gitea Actions remain disabled. Cloudflare's separate external
upload cap is not changed by these local settings; public downloads work.
The configuration diagnostics accidentally exposed an origin protection value
in tool output. No value is recorded here or committed. It was subsequently
rotated through protected Infisical storage; all matching Cloudflare/NPM
consumers were updated, the old value is rejected and public access verified.
Native Linux desktop 0.1.6, GPU, macOS,
clean-machine installation and broader quality gates remain open.