335 lines
20 KiB
Markdown
335 lines
20 KiB
Markdown
# Native Linux desktop validation
|
||
|
||
Executed 2026-10-13 on Ubuntu 24.04 x86-64 in WSL inside the CPU-only Windows VM.
|
||
This is native Linux compilation and an isolated virtual-display interaction
|
||
check, not a Linux installer, physical desktop, GPU, or clean-machine certificate.
|
||
|
||

|
||
|
||
Actual embedded desktop at `657de3d`, with a three-file fixture and real Google
|
||
embeddings. The unrelated lower results illustrate the relevance gate that
|
||
remains open. The displayed times are single observations, not percentiles.
|
||
|
||
## Source and build
|
||
|
||
- Baseline `6b78c8b`: embedded-frontend Release build passed in 25m 49s.
|
||
- Validated snapshot `99748bd`: embedded-frontend Release build passed in 4m 17s
|
||
after refreshing copied source mtimes. An earlier attempt reused stale Cargo
|
||
path-dependency artifacts because Git archive preserved old mtimes; it failed
|
||
with missing new service exports. The corrected build recompiled all shared
|
||
searchi crates. No Rust implementation change was needed for this failure.
|
||
- Frontend `index-DUwy7lJE.js`, SHA-256
|
||
`614562a0804df91452d9d6be0210b543dd035ff7defe99e779cc448488026132`.
|
||
- Executable SHA-256
|
||
`c08b208d1cc3225d9c6a9a7581920eb5cf4fd9105a5620bd2dc57eaac33d671a`.
|
||
- Rust/Cargo 1.99.0; two logical CPUs, 2.8 GiB memory and 1 GiB swap;
|
||
Cargo jobs limited to one. WebKitGTK 4.1 development package
|
||
`2.52.6-0ubuntu0.24.04.1`, GTK 3 `3.24.41-4ubuntu1.3`.
|
||
- Normal verified Linux CPU/Vulkan worker and pinned Linux FFmpeg resources were
|
||
staged in an isolated ext4 source tree. Windows resources were not modified.
|
||
`ldd` found no missing executable libraries on this provisioned Ubuntu host.
|
||
|
||
The build uses `cargo build --manifest-path apps/desktop/src-tauri/Cargo.toml
|
||
--release --features custom-protocol --locked -j1`. Build logs are retained under
|
||
`/home/karl/.cache/searchi-validation/desktop-{baseline,final-99748bd}-build.log`.
|
||
|
||
## Strict CPU rendering and inference
|
||
|
||
The initial Xvfb attempt failed because WSLg's `/tmp/.X11-unix` socket directory
|
||
was not writable. The working session verified a distinct mount namespace,
|
||
made mounts private, and bound a QA-owned socket directory inside that namespace.
|
||
It masked `/dev/dxg` with `/dev/null` and masked `/dev/dri` if present. It changed
|
||
no persistent WSLg mounts or user configuration. The app ran as karl, with an
|
||
owned session/process group and separate settings/index directories.
|
||
|
||
Xvfb disabled GLX; the app used `GDK_BACKEND=x11`,
|
||
`LIBGL_ALWAYS_SOFTWARE=1`, `GALLIUM_DRIVER=llvmpipe`,
|
||
`MESA_LOADER_DRIVER_OVERRIDE=llvmpipe`, `WEBKIT_DISABLE_DMABUF_RENDERER=1`,
|
||
`WEBKIT_DISABLE_COMPOSITING_MODE=1`, and `SEARCHI_FORCE_CPU=1`.
|
||
Model setup reused verified cached Google assets. Explicit worker/media helper
|
||
overrides were used, so this session does not prove installed resource discovery.
|
||
Process inspection of Xvfb, the app, WebKit processes, and the Google worker found
|
||
no GPU device descriptors or Vulkan/D3D provider mappings; their `/dev/dxg` was
|
||
the null device (major 1, minor 3).
|
||
|
||
## Actual UI interactions
|
||
|
||
On the `99748bd` snapshot, the native embedded app:
|
||
|
||
- Rendered the branded light theme and reported Google CPU readiness.
|
||
- Opened its folder form and an actual GTK Browse dialog. Synthetic per-key path
|
||
entry in GTK produced completion/tree-model warnings; cancel worked. Pasting
|
||
the absolute fixture path in the app's folder form successfully indexed three
|
||
real document/code files, then automatically built three Google segments.
|
||
- Searched `cancel the supplier partnership` and placed the supplier agreement
|
||
first, with its real termination passage and literal match highlights.
|
||
- Preserved a collapsed `Why this result?` detail; expanding it showed a concise
|
||
explanation and reopening/collapsing did not change the selected passage.
|
||
- Accepted Ctrl+K and arrow navigation, changing the selected result and preview
|
||
to `retry.rs`, then back to the agreement.
|
||
- Applied an `rs` extension restriction and returned only the source file.
|
||
- Enabled Performance details, showed granular local traces, and copied a
|
||
12,917-byte timing report. Inspection found no source paths or remembered query
|
||
text in the copied JSON.
|
||
|
||
Captures came directly from pinned FFmpeg X11 capture, including fresh
|
||
1080-by-760 app-area captures with `-draw_mouse 0`; no screenshot pixels were
|
||
edited. Raw captures and timing/GPU audits are local ignored QA evidence in
|
||
`.searchi/qa/linux-native-*.png` and the native `desktop-qa-99748bd` directory.
|
||
The remembered search displayed a basic backend sample of 236 ms and displayed
|
||
response sample of 474 ms. A separate debug `retry` query showed 4,371 ms backend
|
||
and 4,564 ms final displayed response. These single samples are not startup,
|
||
first-input, paint, large-corpus, or warm p95 benchmarks.
|
||
|
||
## Independent scheduling regression
|
||
|
||
The actual Google `budget_google_cpu` test passed on Linux in 129.60s, using
|
||
the normal verified worker with CPU forced: total budget 2, foreground query
|
||
thread 1, indexing thread 1, query sample 142.015 ms, admission sample 0.444 ms,
|
||
six background document encoder calls. This proves the tested concurrent
|
||
admission contract; it does not establish scale or native UI latency targets.
|
||
Log: `/home/karl/.cache/searchi-validation/budget-google-linux-99748bd.log`.
|
||
|
||
## Remaining scope
|
||
|
||
The `99748bd` interaction evidence excludes the later watcher milestone.
|
||
Installer/resource discovery, window-manager chrome, theme/contrast/accessibility
|
||
coverage, media previews, physical GPU fallback/recovery, clean-machine ABI,
|
||
upgrades/signing, macOS, and large-corpus performance remain separate gates.
|
||
|
||
## Watcher milestone: `657de3d`
|
||
|
||
The isolated source was refreshed from the committed snapshot and paired with
|
||
the matching `index-64het56E.js` frontend. Source mtimes were refreshed before
|
||
Cargo invocation. Executed checks:
|
||
|
||
- Workspace: **124 passed, 19 ignored**, zero failures; native compilation took
|
||
2m 25s. Ignored actual-model tests are not counted as executed here.
|
||
- Desktop Release unit tests: **28 passed**, including actual Linux inotify
|
||
create/update/rename/delete, bounded-event retry/overflow and shutdown tests;
|
||
compilation took 1m 49s and test execution 1.74s.
|
||
- Actual Google mixed-media reuse regression: **one passed in 67.95s**, including
|
||
same-stat media invalidation, revision tokens and reused vector publication.
|
||
Normal verified worker, real models and pinned FFmpeg helpers; CPU forced.
|
||
- Fresh embedded-frontend Release executable built in 1m 49s; SHA-256
|
||
`746571a151cea5151b0ed9feef87db98f41cb62512a6bc9eb7b7b6404dd015a5`.
|
||
|
||
Logs are retained as `workspace-linux-657de3d.log`,
|
||
`desktop-tests-linux-657de3d.log`, `media-google-linux-657de3d.log`, and
|
||
`desktop-final-657de3d-build.log` under the native validation cache.
|
||
|
||
The current native UI used a fresh settings/index directory and the same
|
||
verified private CPU display setup. Captures targeted the actual X11 window ID,
|
||
whose inspected geometry was x=0, y=0, width=1080, height=760. Its worker loaded
|
||
`libggml-cpu-zen4.so`, one inference thread, zero process swap; no GPU mappings
|
||
or descriptors were observed. After initial indexing, WSL reported 539 MiB
|
||
used, 2.3 GiB available and zero swap. No validation compiler or independent
|
||
model test was running during the following UI samples.
|
||
|
||
The first remembered query had inherited the previously enabled Performance
|
||
details preference from WebKit local storage; `SEARCHI_DATA_DIR` isolates Rust
|
||
settings/index, not that WebKit preference. Its debug sample was 70.852765 ms
|
||
native, 68.644667 ms query embedding, 67.261 ms worker inference, 13 tokens and
|
||
a query-vector cache miss. First displayed response was 70 ms; final displayed
|
||
response was 273 ms. After disabling Performance details, the distinct query
|
||
`end the supplier agreement` showed 89 ms native / 300 ms displayed. These
|
||
different-query samples do not establish normal/debug overhead or p95. The
|
||
earlier 4.371s sample remains valid evidence, with no inferred cause.
|
||
|
||
Actual UI filesystem lifecycle checks required no manual Reindex action:
|
||
|
||
1. Changed `sixty` to `seven` while preserving exact file size and mtime. The
|
||
live passage updated automatically; active generation moved 1 to 2, retaining
|
||
three chunks. Recorded SHA-256 values differed despite matching metadata.
|
||
2. Created `orbit.txt`. The app counted four files and immediately showed its
|
||
actual `orbital` keyword passage while Google indexing was working: a single
|
||
sample of 1.2 ms backend / 88 ms displayed. Generation 3 contained four chunks.
|
||
3. Renamed it to `satellite.txt`. The UI preview and indexed path changed, the
|
||
old path disappeared, and generation 4 retained four chunks.
|
||
4. Deleted it. The path disappeared from both UI and index; generation 5 returned
|
||
to three chunks.
|
||
|
||
Raw mutation snapshots are in native `desktop-qa-657de3d/watch-mutations.jsonl`;
|
||
UI captures are local `.searchi/qa/linux-current-*.png`. The copied debug report
|
||
is `.searchi/qa/linux-current-timing-remembered-debug.json`.
|
||
Both UI sessions ended through their owned cleanup path: the app process group
|
||
terminated, Xvfb exited successfully, and subsequent process inspection found no
|
||
remaining app/WebKit/worker/Xvfb/DBus/clipboard helpers. The outer `/dev/dxg`
|
||
remained the real device after private namespace teardown.
|
||
|
||
The interactions also exposed two unresolved product observations. Background
|
||
filesystem refreshes displayed `SHOWN 83537 MS` / `SHOWN 108592 MS` despite
|
||
roughly 1–2 ms backend samples, including idle time since the original input;
|
||
these are not fresh search latency measurements. During replacement, selection
|
||
advanced to another valid result and stayed there when the replaced passage
|
||
returned. After deleting the only orbital file, three unrelated semantic
|
||
neighbors remained: deleted-source suppression worked, but no-relevant-match
|
||
calibration remains a separate search-quality gate.
|
||
|
||
## Watcher UI corrections: `8b993b2`
|
||
|
||
A fresh native embedded Release build paired this committed snapshot with
|
||
`index-Bi37oidC.js`. Cargo completed successfully in 2m 40s with one build job.
|
||
Executable SHA-256:
|
||
`981dc04fb1e57e4c48bd1a12d64ec300ca73e7696d76aad25cd8153b780c8132`.
|
||
Frontend SHA-256:
|
||
`ee3b297dff382f2f14a87a88e345f1deb8dae0f77f6d70e0444d916b3cf197de`.
|
||
Build log: native `desktop-postfix-8b993b2-build.log`. An earlier command failed
|
||
before Cargo because the inherited Windows PATH contained spaces; the corrected
|
||
command used an explicit Linux-only PATH.
|
||
|
||
The executed post-fix session used separate XDG cache/config/data directories
|
||
in addition to isolated Rust settings/index. Performance details started
|
||
unchecked, confirming that prior WebKit preferences were not reused. It reused
|
||
the verified private namespace, CPU software Xvfb and explicit native worker
|
||
helper paths; no physical GPU or installer resource discovery was tested.
|
||
|
||
Actual native UI checks, without a manual Reindex action:
|
||
|
||
1. The remembered query `cancel the supplier partnership` found the supplier
|
||
passage. One basic sample showed 93 ms native / 296 ms displayed.
|
||
2. After enabling Performance details, waiting more than 30 seconds, and changing
|
||
`sixty` to `seven` with identical size and mtime, the preview updated and
|
||
returned to the supplier selection. The copied report identified
|
||
`trigger: filesystem_refresh`; its preserved `original_input` measured
|
||
first response 20 ms and final response 140 ms. The independent refresh
|
||
measured first response 31 ms and final response 4,164 ms, with 1.9 ms native
|
||
search. The final displayed time includes actual background indexing/readiness
|
||
and retry scheduling; it is not the idle interval or native inference cost.
|
||
This corrects the earlier idle-clock defect without proving a warm p95 target.
|
||
3. Moved the selected supplier file out of the indexed fixture. The UI showed
|
||
two files and temporarily selected `retry.rs`. Restoring the same supplier
|
||
path brought the selection and preview back automatically.
|
||
4. Repeated the removal, explicitly clicked `Garden notes.txt` while the supplier
|
||
was absent, then restored the supplier. The UI retained the explicit garden
|
||
selection despite the supplier becoming the first result again.
|
||
|
||
The copied timing JSON contains neither remembered query text nor source paths.
|
||
Local ignored evidence: `.searchi/qa/linux-postfix-timing-refresh.json`,
|
||
`linux-postfix-{update-ready,absent,restored,override-selected,override-restored2}.png`,
|
||
`linux-postfix-cpu-audit.json`, and `linux-postfix-mutations.jsonl`. Native
|
||
`desktop-qa-postfix` retains the owned session logs and complete fixture. One
|
||
capture caught a transient black rectangle over a hovered row; a fresh capture
|
||
after moving the pointer away was clean. This isolated software-display check
|
||
does not close native visual/accessibility or physical-desktop gates.
|
||
|
||
The CPU audit found no GPU descriptors or provider mappings in the app, WebKit,
|
||
Xvfb or Google worker. The worker used `libggml-cpu-zen4.so`, one thread and zero
|
||
process swap; their private `/dev/dxg` was the null device (1:3). Owned shutdown
|
||
ended the app group with SIGTERM and Xvfb with status zero. Subsequent process
|
||
inspection found no remaining app/worker/WebKit/Xvfb/DBus/clipboard helpers,
|
||
and the outer `/dev/dxg` remained the real device (hex a:102).
|
||
|
||
## Native query-role validation: `5d9cfc4`
|
||
|
||
Executed on the same provisioned Ubuntu 24.04 x86-64 WSL host. The isolated
|
||
normal `auto` worker was rebuilt with one job, retaining Vulkan and CPU modules.
|
||
All inference used `SEARCHI_FORCE_CPU=1`; the benchmark additionally requested
|
||
`--device cpu` and checked that no Vulkan module loaded. Windows staged resources
|
||
were not changed. Worker SHA-256:
|
||
`b52d50a1e676bd4bf64124daff1c4ce83d86a8bde01e4eaf09838cbb24a4c28f`.
|
||
|
||
Actual Google checks passed:
|
||
|
||
- `query_context_cpu`: one passed in **42.88 s**, covering query role/context
|
||
negotiation, unchanged real vectors/ranking, multilingual CodeRetrieval,
|
||
exact 512-token boundary, nonfatal oversized rejection, indexing/media guards
|
||
and full-context document windows. Compilation took 1m 06s.
|
||
- CLI/MCP `actual_google_cli_and_mcp_use_query_role_with_cited_results`: one
|
||
passed in **38.73 s**, including real indexing with the full role, foreground
|
||
CLI search, retained MCP query role/context and guarded source excerpts.
|
||
|
||
Logs remain in the native cache as `query-role-native-build.log`,
|
||
`query-context-linux-test.log`, and `query-context-linux-mcp.log`. These tiny
|
||
fixtures establish native role/client correctness, not representative relevance
|
||
or a release package gate.
|
||
|
||
After correctness tests and other agents' downloads were terminal, a paired
|
||
benchmark ran six fresh workers, alternating order, three per role, one inference
|
||
thread. Cached model bytes were verified once in **241.48 ms** before process
|
||
trials; process startup excludes that verification and desktop preparation.
|
||
|
||
| Median observed measurement | Indexing 2048 | Query 512 |
|
||
| --- | ---: | ---: |
|
||
| Startup to ready | 717.08 ms | 564.02 ms |
|
||
| First query IPC/inference | 67.13 ms | 66.89 ms |
|
||
| Ready PSS | 405,303,296 bytes | 405,278,720 bytes |
|
||
| Ready RSS | 406,806,528 bytes | 406,773,760 bytes |
|
||
| Ready private dirty resident pages | 103,739,392 bytes | 103,735,296 bytes |
|
||
| After query PSS | 410,157,056 bytes | 410,001,408 bytes |
|
||
|
||
Linux resident/PSS observations were effectively unchanged. They must not be
|
||
reported as the Windows private commitment saving; this benchmark does not
|
||
measure Linux virtual commitment. The startup samples are small cached-process
|
||
observations, not cold disk, actual first UI input, pressure behavior or warm p95
|
||
proof. Mapped model pages contribute to resident/PSS figures; do not sum them
|
||
as independent model allocations across workers. Raw paired samples are retained
|
||
locally in `.searchi/qa/query-context-linux.json`; native benchmark output is
|
||
`query-context-linux-benchmark.log`. The benchmark itself also checked nonfatal
|
||
rejection of a direct indexing operation followed by a successful code query.
|
||
|
||
All owned test and benchmark handles ended successfully. Subsequent process
|
||
inspection found no surviving Google workers, Cargo or Rust compiler processes.
|
||
Native desktop packaging with this new worker, actual GPU, macOS and
|
||
representative performance remain open.
|
||
|
||
## Genuine first-use media download: `9aae3f8`
|
||
|
||
Native embedded Release build passed in 2m 52s, using matching
|
||
`index-STH19o-O.js`. Executable SHA-256:
|
||
`229312e05629555956c659a83d56fa3dcc9e8830736a062c9208ce704ce11fa6`;
|
||
frontend SHA-256:
|
||
`dc3ee20bc7bb3eda347c142ee9fab3e10b8d17037402d21c5cc6de1a5f0dd967`.
|
||
The isolated resource override used the normal Linux query-role worker
|
||
`b52d50a1e676bd4bf64124daff1c4ce83d86a8bde01e4eaf09838cbb24a4c28f`.
|
||
|
||
The fresh owned `desktop-qa-earlytext` directory isolated XDG cache/config/data,
|
||
settings, index, decoded scratch and model cache. Initially only the verified
|
||
309,855,456-byte backbone was present, hardlinked from the verified native cache.
|
||
A fixture contained three document/code files and a small BMP. The app's
|
||
HTTPS_PROXY/HTTP_PROXY pointed only its own process environment to an owned
|
||
loopback CONNECT proxy at `127.0.0.1:18943`, throttled to 4 MiB/s. The proxy
|
||
forwarded opaque TLS to real Hugging Face/CDN HTTPS; there was no TLS interception,
|
||
production URL override or global network change.
|
||
|
||
Actual native UI evidence:
|
||
|
||
- While the genuine projector download was incomplete (202,664,870-byte partial,
|
||
no installed projector), generation 1 contained three text chunks. The UI
|
||
reported text search ready and media preparation in progress. The first
|
||
actual remembered input found the supplier passage: one basic observation of
|
||
**84 ms native / 293 ms displayed**. This is not cold startup or warm p95.
|
||
- Closing owned proxy tunnels and rejecting further CONNECT attempts caused
|
||
three download attempts to fail and removed the partial file. Generation 1
|
||
and query worker PID 397 remained usable. Expanded model details showed
|
||
media setup failure, text availability and an actual Retry model setup button.
|
||
- Restoring proxy forwarding and clicking that UI button restarted the genuine
|
||
pinned download. A separate cached debug rerun during retry measured
|
||
**2.0 ms native / 44 ms first / 138 ms final displayed**; it is not the first
|
||
user input. Its copied timing report contained no query text or source paths.
|
||
- Verified full projector installation produced the exact 554,821,024 bytes and
|
||
SHA-256 `c4a8a52691ecef40618438928bdf9e68379b854e24166f292592353db0aab64f`.
|
||
Generation 2 contained four chunks, including image content. The retained
|
||
CPU query worker stayed PID 397 through failure, retry and promotion. Explicit
|
||
selection of `retry.rs` remained selected when the image entered ahead of it.
|
||
|
||
This interaction uncovered a separate semantic-activation timing defect:
|
||
full-media promotion reused the prior search measurement and displayed
|
||
**SHOWN 143,928 ms** despite an 8.0 ms native search. The copied report retained
|
||
`trigger: user_search` and the old three-chunk context. This value includes
|
||
media download/idle time and must not be presented as fresh search latency.
|
||
Watcher refresh timing was already corrected; semantic readiness/activation
|
||
needs the equivalent independent refresh measurement and another native retest.
|
||
|
||
Local ignored evidence: `.searchi/qa/linux-earlytext-*.png`,
|
||
`linux-earlytext-{retry-search,promotion-search}.json`, `linux-earlytext-states.jsonl`
|
||
and `linux-earlytext-cpu-audit.json`. Native `desktop-qa-earlytext` retains proxy
|
||
events, logs and fixture data. The owned proxy helper is
|
||
`.searchi/linux-validation/opaque_proxy.py`. The private GPU-masked software
|
||
display audit found no GPU providers or descriptors; the query worker used Zen4
|
||
CPU, one thread and zero swap. Both owned UI/proxy handles ended successfully,
|
||
Xvfb exited zero, and process inspection found no surviving app, worker, WebKit,
|
||
DBus, clipboard, display or proxy helpers. Outer `/dev/dxg` remained real.
|
||
Physical desktop, installed resource discovery, representative relevance,
|
||
first-install cold storage, p95, GPU and macOS gates remain open.
|