Keep complete decoded string records in Hopper's existing search inventory and directly project literal matches, removing the redundant full record projection and superseded value-only representation. Record real Linux CLI/MCP correctness and Evidence checks, shorter warm queries, negative whole-task costs, native coverage gaps and resource stops. Fixes #5010. Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
14 KiB
Hopper literal search: reuse decoded records
For #5010, the bridge now keeps
the existing decoded records in its sorted search inventory and projects only
matches. Previously, every positive literal search called _string_inventory
again, sorting all native object addresses and building another complete map
before selecting records. The value-only _strings representation and the
intermediate match list have been removed.
This removes repeated work at its owner. Three paired SQLite workflows found shorter warm queries, but did not demonstrate an overall task speedup: whole elapsed and CPU were worse. Token estimates were effectively unchanged; no memory improvement was established. The curated receipt keeps individual measurements, equality checks and failed attempts.
Representation and reuse boundary
The existing (id(document), kind) search cache now holds references to full
records rather than just their decoded values. The existing string-record
owner still performs byte decoding, encoding inference and unknown handling.
Matching reads record.value; output copies the selected record with its
address, retaining native display, encoding/extent metadata and decoding
failures. The original document lifetime and annotation invalidation apply.
This does not add another cache or duplicate decoded payloads. Both CLI and
MCP use the same bridge through the existing application workflow. Regex keeps
its supervised worker implementation.
The lookup remains a linear scan of recognized native strings. A complete inventory is still decoded for the first exhaustive search, and returned hits still consume output and retained Evidence. This change does not introduce pagination, broader binary string discovery or a new context contract.
Pinned real-provider scope
Baseline: REA 6.7.0 at c12d9eda87aa5a022ee7e18ea96d8d03bfd12e96, Node
24.18.0, Debian 12 x86-64, Linux 6.1.0-53-cloud-amd64. All paired tasks used
the same compiled runtime SHA-256
0809b5004f214efa4b79775d5fda796eaecf4ad5756c55ee3b9d7cf82d91b750.
Baseline and candidate bridge digests are recorded separately in the receipt;
the baseline file was mounted read-only over the bridge for baseline runs.
The official Hopper 6.6.0 Linux demo package
was authenticated through REA's production publisher verifier: 35,748,722
bytes, SHA-256
59705e50f7ebf9104abe1e72ac3949bed1a8e43ec67a8c9510a1c5056c200d27,
primary signing fingerprint 7C2D73BAFAF5B9A710A69DA1A26DF815099B1BCD.
The extracted launcher digest was
b2271008fb82bf14cfae5c3644cdde2b11fc6804bd7c99d67032ec1b1942d53c.
Normal demo activation used an owned private Xvfb display.
The host's glibc 2.36 could not satisfy this package's GLIBC_2.38 requirement.
Analysis therefore ran in a user-mapped private Ubuntu Base 24.04.5 namespace
with glibc 2.39, Qt6/X11 and embedded Python 3.12. The
rootfs archive
matched its official HTTPS checksum, SHA-256
e77b6f10c2590cef872b33ee9f635a0e3fd1f57fb074c0e52b5c7f56147a0c86;
its publisher signature was not independently verified. Related libraries were
installed only into that private image. Actual rea setup and vendor package
post-install scripts were not executed. Native Debian installation and other
operating systems remain unqualified.
| Artifact | Bytes | Independent oracle |
|---|---|---|
| Small authored C ELF | 17,360 | Source input * 7 + 13 and ELF symbol |
| Source-built conformance ELF | 22,584 | Fixture source, known literal bytes and symbol addresses |
Shipped Debian libsqlite3.so.0.8.6 |
1,437,848 | GNU objdump: version function returns 3040001 |
Artifact digests, compiler and flags are in the receipt. No target was executed. The small ELF was a baseline setup/decompilation smoke test; the conformance ELF had baseline/candidate semantic and CLI/MCP checks. SQLite supplied the repeated performance cohort. A constant-return oracle does not establish whole-program correctness, ABI inference or complex-investigation effectiveness.
Completed task and correctness
Each of three baseline/candidate pairs used a fresh Hopper process and the same public stdio MCP workflow, including catalog discovery and 17 tool calls:
- Open the SQLite copy and inspect
binary_session. - Search
sqlite_masterin case-sensitive literal mode, then repeat six times. - Read
list_stringsas a full-inventory validation oracle; compare all matching records, including their metadata, with the selected result. - Check broader
sqlitesearch, regex, case-insensitive and absent-pattern queries against their expected native inventory scope. - Resolve
sqlite3_libversion_number, decompile it, check its constant against independent objdump, and close the binary and MCP transport. - Verify unchanged target bytes and cleanup of the owned process family.
There were 1,437 recognized string objects, 19 sqlite_master matches and 74
broader sqlite matches. Applicable decoded hit bytes were also checked
against file contents. All 42 Evidence payloads across the three pairs matched
on normalized and raw facts, identity, subject, provider/profile, authority,
confidence, limitations, relationship coverage, locations and evidence links.
Live environment observations were excluded from cross-session equality.
The real conformance workflows each completed 70 public calls, including six
expected errors. They exercised Unicode symbol identity, literal metacharacters,
case/regex modes, annotation cache invalidation, typed string fragments,
display escaping and source-byte checks using the existing real-provider
verifier. CLI fragment_tail search returned the same normalized facts and
Evidence ID as MCP on both revisions (2,293 stdout bytes each).
Native recognition remains qualified: the full 4,120-byte source literal and some known UTF-8, ellipsis and Latin-1 literals were not recognized. Their file bytes were verified, while decoded native-object coverage remains unverified. The fragmented 549-byte source literal was recognized as separate objects; matching does not pretend to join those fragments. Escaped text and literal backslash-n were distinguished. Real UTF-16 provider decoding was not qualified; the focused boundary fixture covers that representation separately. Empty search results establish absence only within the native typed-object inventory.
Measurements
Runs were serial and ordered B1/C1, C2/B2, B3/C3. C2 first stopped under the host memory guard; its separate completed retry supplies the C2 row. OS caches were not flushed. “Cold” means the first string query in a fresh provider; “warm” means six repeats within that provider.
Medians across the three completed sessions per revision:
| Cost | Baseline | Candidate |
|---|---|---|
| Per-run median warm query | 14.849 ms | 12.628 ms |
| Six warm queries, total | 100.202 ms | 75.552 ms |
| Whole SDK workflow | 86.583 s | 90.786 s |
| Whole guarded workflow | 89.384 s | 93.630 s |
| Family CPU at payload exit | 88.333 s | 92.590 s |
| Kernel family peak, including file cache | 1,438.4 MiB | 1,440.0 MiB |
Warm-query medians were lower in all three pairs, although one baseline run was particularly variable. Whole guarded elapsed was about 4.7% worse and CPU about 4.8% worse. The first query accounted for 65.2–71.2 seconds on baseline and 72.3–77.5 seconds on candidate; that interval includes native preparation. Do not interpret this cohort as end-to-end acceleration or dismiss the unfavorable rows.
A separate pair moved the existing procedure_address call before the
first string search, keeping the same 17 calls and equivalent facts/Evidence.
Most preparation cost then occurred in that unchanged lookup: 67.949 seconds
baseline versus 94.358 seconds candidate, before the changed search path ran.
The subsequent first string query took 329.254 versus 337.533 ms; total guarded
elapsed was 89.096 versus 113.917 seconds. This locates substantial cost outside
literal projection and preserves the negative whole-task result. It does not
prove its cause, establish a cold-query improvement or justify pooling the
reordered pair with the original cohort.
Resource and context accounting
Every heavy task used an owned cgroup v2 family: 8 GiB hard limit, 7 GiB early stop, zero swap, one CPU quota and affinity, 192 tasks, 3,072 MiB Node heap, and one heavy job at a time. Host admission required 16 GiB available; tasks stopped below 8 GiB. Later long runs added admission at 24 GiB sustained for 20 seconds without relaxing the family guard.
Family counters include the namespace, native engine, MCP client/runtime, validation and cleanup, including charged file cache. SDK wall time includes catalog discovery and correctness assertions. Admission wait is outside the guarded time and recorded separately where available; older waits and outer guard/systemd costs were not measured. Payload-exit CPU, kernel memory peak, limit counters and owned cleanup were verified while an observer remained. Final counters after the scope disappeared remain unknown. Completed paired payloads observed zero memory-limit, OOM/OOM-kill and task-limit events.
The unchanged catalog advertised 207 tools, 3,158,927 serialized bytes,
SHA-256 a1851aa1bfe3d72d6be6bec130519dbdfc1ee49288320cfac0144ced77755c61.
Offline tiktoken 0.12.0 cl100k_base estimates for every completed SQLite
comparison were effectively unchanged (medians across three runs):
| Serialization counted once | Baseline estimate | Candidate estimate |
|---|---|---|
| Full catalog page array | 805,330 | 805,330 |
| Named tool requests | 361 | 361 |
| Raw replies | 259,809 | 259,811 |
| Total above | 1,065,500 | 1,065,502 |
| Text reply blocks alone, overlapping the raw count | 126,832 | 126,833 |
Whole raw estimates ranged from 1,065,496–1,065,500 on baseline and 1,065,500–1,065,506 on candidate. The small variations include live environment observations; there is no context reduction.
The full inventory and extra controls are validation overhead included in these totals. Raw replies may contain text and structured copies. Actual model usage, prompts, initialization/protocol framing, client filtering/rendering or replay and independent-oracle context were not measured. The receipt separates other tasks and the interrupted transcript's persisted lower bound; it does not count an unrecorded in-flight request or reply as observed. No model-token saving or agent-reasoning advantage is claimed.
Failed attempts and verification
The receipt preserves setup, diagnostic, failed and completed costs separately:
- Initial private-rootfs configuration failed on an unmapped package GID, then on the harness PATH; ordinary pending configuration completed successfully.
- One low-host-memory probe was refused before creating a payload.
- The first MCP harness used a relative path, correctly refused by the public input boundary. A later custom-runtime launch lacked libXtst6, which the production dependency list already includes. Both were harness/setup errors.
- Two unchanged-baseline launches timed out at bridge startup. An owned-display observation showed completed native analysis but a Python bootstrap failure. Adding only the missing embedded Python library made the baseline pass; #5015 records the separate installer dependency hypothesis and its unverified actual-installer scope.
- C2 stopped after 82.607 seconds when host available memory crossed the unchanged stop threshold. Its sampled family peak was 1,517,019,136 bytes and last observed CPU 78.255 seconds. Payload-exit/final counters are unknown; it is incomplete and excluded from completed-run statistics.
- An initial
test:localinvocation rejected built boundary projects before running tests. The documentedtest:focusedinvocation then passed all 35 tests in five files, covering string search, regex, bridge facade and real-provider verifier behavior. Those local tests do not themselves qualify a native engine; the public native workflows above provide that evidence.
npm run check:fast also passed (typecheck and lint both cached). Build and
metadata preparation passed before the native workflows. npm run docs:check
passed its cached metadata checks and all five README consistency tests.
Reproduction uses node scripts/rea.mjs --mcp with an explicitly configured
Hopper launcher and private display. Drive the named calls above with absolute
target paths, retain full replies and compare independently verified bytes,
facts and Evidence. For the source fixture, compile
tests/conformance/c/fixture.c with
gcc -O0 -g -fno-inline -fno-omit-frame-pointer -fno-pie -no-pie.
Debug build paths can change rebuilt artifact digests. The shipped SQLite
digest pins the measured artifact rather than every build of its package.
The focused local gate was:
npm run test:focused -- \
tests/boundary/providers/hopper/hopperStringSearch.test.ts \
src/hopper/HopperRegexSearch.test.ts \
tests/boundary/providers/hopper/hopperBridgeFacade.test.ts \
tests/conformance/providers/hopper/realHopperSearch.test.ts \
tests/conformance/providers/hopper/realHopperExhaustiveSearch.test.ts