22 KiB
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-256614562a0804df91452d9d6be0210b543dd035ff7defe99e779cc448488026132. - 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 33.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.
lddfound 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 partnershipand 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
rsextension 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:
- Changed
sixtytosevenwhile 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. - Created
orbit.txt. The app counted four files and immediately showed its actualorbitalkeyword passage while Google indexing was working: a single sample of 1.2 ms backend / 88 ms displayed. Generation 3 contained four chunks. - Renamed it to
satellite.txt. The UI preview and indexed path changed, the old path disappeared, and generation 4 retained four chunks. - 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:
- The remembered query
cancel the supplier partnershipfound the supplier passage. One basic sample showed 93 ms native / 296 ms displayed. - After enabling Performance details, waiting more than 30 seconds, and changing
sixtytosevenwith identical size and mtime, the preview updated and returned to the supplier selection. The copied report identifiedtrigger: filesystem_refresh; its preservedoriginal_inputmeasured 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. - 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. - Repeated the removal, explicitly clicked
Garden notes.txtwhile 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 ofretry.rsremained 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.
Semantic-activation clock correction: 19d949f
The focused retest used an immutable committed source snapshot and matching
index-DYGZ2Wy5.js, separately from subsequent glass-UI work. Native embedded
Release build passed in 3m 23s. Executable SHA-256:
247746c289cd153e7bd70cadbbdbe3a92aa918caa374ad8557196815bd9182fe;
frontend SHA-256:
46b1a070c3f8cbe3b11471f049e071eb8e0e8a30e98be3e045256301f9759aec.
The normal Linux query-role worker remained the previously verified b52d50...
binary. The owned desktop-qa-activation session isolated XDG and Rust data,
reused the earlier four-file fixture and complete verified model cache, and made
no model download or proxy changes. Startup established full generation 1 in
the new data directory; the measured rebuild therefore activated 1 to 2.
Actual native UI checks:
- Enabled Performance details and typed a new
end the supplier contractquery. Its copied report measured 60 ms debounce, 111 ms first displayed response, 845 ms final displayed response and a 632 ms native hybrid observation. These single samples are not first-launch, cold storage or warm p95 proof. - Explicitly selected
retry.rs, then left the completed query idle for about 87 seconds before clicking the actual Rebuild semantic index button. - The new generation retained four chunks. The copied refresh report had
trigger: semantic_activation, 13 ms first / 135 ms final displayed and 2.4 ms native; it excluded the long idle interval. Its separateoriginal_inputpreserved the original 60/111/845 ms measurements. - The report context reflected current
semantic_generation: 2andindexed_chunks: 4. Automatic lexical and hybrid refresh kept the explicitretry.rspreview/selection, and the warmed CPU query worker stayed PID 387 through activation. Copied reports excluded query text and source paths.
Local ignored evidence: .searchi/qa/linux-activation-{initial-search,search}.json,
linux-activation-{initial-trace,selected,refreshed-trace,selection-retained}.png,
linux-activation-states.jsonl and linux-activation-cpu-audit.json. The previous
9aae3f8 143,928 ms report is retained as historical defect evidence and was not
overwritten. The private software-display audit again found no GPU descriptors
or providers; the worker used Zen4 CPU, one thread and zero swap. Owned shutdown
ended the app group and Xvfb successfully; subsequent process inspection found
no app, worker, WebKit, DBus, clipboard or display helpers remaining, and outer
/dev/dxg remained the real device. This closes the tested activation-clock
regression, not the broader native UX, p95, installer, GPU or macOS gates.
