[PR #4318] [MERGED] fix(kuna): stream string scans instead of capping them at 16 MiB #6168

Closed
opened 2026-10-31 01:12:23 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4318
Author: @kaoru0822-kitauji
Created: 10/16/2026
Status: ✅ Merged
Merged: 10/16/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/kuna-stream-string-scan


📝 Commits (5)

  • 48abd8f fix(kuna): stream string scans instead of capping them at 16 MiB
  • 46f6fee fix(kuna): admit string scan text as it streams and drop sinks with their command
  • 0ce0dbd fix(kuna): type the stream-json tokenizer where it is imported
  • 8770e38 fix(kuna): bound key and number assembly in streamed Kuna JSON
  • 72f2de0 fix(kuna): stream the call graph instead of capping it at 32 MiB (#4329)

📊 Changes

20 files changed (+1408 additions, -271 deletions)

View changed files

📝 docs/kuna-provider.md (+2 -2)
📝 src/kuna/KunaCommand.ts (+5 -1)
📝 src/kuna/KunaJson.ts (+19 -11)
➕ src/kuna/KunaJsonStream.ts (+554 -0)
📝 src/kuna/KunaLimits.ts (+3 -2)
📝 src/kuna/KunaProjectExport.ts (+3 -4)
📝 src/kuna/KunaQueryWork.ts (+43 -1)
📝 src/kuna/KunaReferenceFiles.ts (+151 -74)
📝 src/kuna/KunaReferenceQueries.ts (+20 -29)
📝 src/kuna/KunaStringInventory.ts (+85 -54)
📝 src/kuna/KunaStringQueries.ts (+27 -47)
📝 src/kuna/KunaTargetCommands.ts (+3 -0)
📝 src/process/OwnedCommand.ts (+58 -11)
📝 tests/boundary/process/ownedCommand.test.ts (+70 -1)
📝 tests/boundary/providers/kuna/fakeKuna.ts (+19 -5)
📝 tests/boundary/providers/kuna/kunaCommandFailures.test.ts (+32 -3)
📝 tests/boundary/providers/kuna/kunaReferenceFiles.test.ts (+105 -11)
📝 tests/boundary/providers/kuna/kunaReferences.test.ts (+4 -1)
📝 tests/boundary/providers/kuna/kunaStringInventory.test.ts (+152 -13)
📝 tests/boundary/providers/kuna/kunaStrings.test.ts (+53 -1)

📄 Description

Summary

Kuna list_strings and search_strings failed on every real app above roughly 10 MB. REA buffered Kuna's whole string JSON and refused anything above 16 MiB, but Kuna writes about 290 bytes per row. REA now parses the scan as Kuna writes it, so these apps get answers. Refs #1957.

Problem and expected behavior

Trigger: rea search <app> ghostty --provider kuna on a thin arm64 app binary. On origin/main with real Kuna 1.833 (macOS arm64):

{"code":"resource_constraint","message":"kuna strings wrote more than 16777216 bytes of output.","retryable":false,
 "remediation":{"action":"REA buffers at most 16777216 bytes of kuna strings output, so repeating this request for this target fails the same way. Use another provider for it."}}
Target (thin arm64) Image kuna strings --json output Rows
Ghostty 20 MB 31.0 MB 107,587
Raycast 53 MB 29.7 MB 101,188
Firefox XUL 169 MB 178.8 MB 611,290

The 16 MiB cap came from no format or resource constraint, and the original validation only covered SQLite and zlib. Expected: a string question about a large target gets an answer, with memory bounded by what REA keeps rather than by the size of the transport.

Change and scope

  • runOwnedCommand (src/process/OwnedCommand.ts) accepts an optional stdout sink.
    • The sink receives stdout instead of the retained snapshot, and the command returns only after the sink finishes.
    • The pipeline follows the command's deadline signal, and a failed collection destroys the sink.
    • A failing stream is a collection failure. Existing callers are unchanged.
  • KunaJsonDocumentReader (src/kuna/KunaJsonStream.ts) owns the token mechanics.
    • It tokenizes with stream-json's synchronous jsonParser (already a dependency; its shape is declared at the import site because stream-json's typings omit it).
    • Every scalar arrives in chunks and is assembled only as far as it can matter:
      • keys up to 64 code units, past every kept field name, so an overlong key is skipped unmatched;
      • kept numbers up to 64 code units, beyond which the document is rejected. Exact u64 tokens are read through the shared kunaAddressFromJsonNumber, which parseKunaJson now uses too;
      • kept strings, which can carry target-derived text of any length, admitted against heap headroom as they grow.
    • Ignored members, fields and values are dropped unassembled.
    • Kept text and retained rows are admitted against live heap headroom as they grow, the same approach as JsonInputFile, instead of a fixed scan size. Kept text is copied out of the decoded chunk it was sliced from.
    • The first contradiction aborts Kuna instead of waiting for the rest of its output. An incomplete document is judged only after Kuna's own exit status.
  • KunaStringInventoryReader (src/kuna/KunaStringInventory.ts) keeps only the string-scan semantics: the same schema and fact checks per row as before. It replaces parseKunaStringInventory.
  • Kuna diagnostics keep an 8 MiB budget. KUNA_DIAGNOSTIC_BYTES is now shared with the project export, and KUNA_STRING_OUTPUT_BYTES is removed.
  • Not changed: string results and contracts, the complete-result semantics (no paging), the graph's 32 MiB buffer and the xref buffer.

Contribution scope: a fix inside the existing Kuna provider. No new authority, target execution, injection, mutation or protection recovery. A maintainer scope decision is not applicable. There are no new dependencies and no new MCP tool names or input fields.

Contract and boundary impact

  • Semantic owner and earliest changed stage: KunaStringInventoryReader owns parsing and validation of the string scan; runOwnedCommand gains an optional stdout sink.
  • Contribution scope fit and linked maintainer decision: fix within existing boundaries; not applicable.
  • CLI and MCP/tool-catalog contract: unchanged. Large targets now answer instead of returning resource_constraint.
  • Provider, bridge, target-format, or platform compatibility: same Kuna command and arguments. Unknown JSON members are still tolerated, as the previous non-strict schema did.
  • Evidence, artifact, provenance, or reconstruction contract: raw_result.strings keeps its digest, size, scope, policy and counts. The SHA-256 now covers the streamed bytes, which are the same bytes as before.
  • Target selection, authority, upstream behavior, and cleanup details: Kuna now stops on the first rejected row. Process ownership and cleanup still go through runOwnedCommand.
  • Generated metadata, package, or installation impact: none.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated:
    • kunaStrings.test.ts: a 24 MiB scan answers. It fails on base with the 16 MiB resource_constraint.

    • kunaStrings.test.ts: a contradictory first row followed by a hang returns AnalysisOutputError within about 1 s. On base it waits for the 60 s project deadline.

    • kunaStrings.test.ts: the oversize-retention case now floods stderr past KUNA_DIAGNOSTIC_BYTES, keeping coverage that deterministic buffer failures are retained until close.

    • kunaStringInventory.test.ts now drives the reader through 1–3 byte chunks (multi-byte UTF-8 across chunk boundaries, digest equal to the whole text). It also covers:

      • truncated, trailing, array-root and empty documents, and invalid UTF-8;
      • a textual address, referencing functions, and ignored and __proto__ members;
      • an early abort signal;
      • refusal on heap headroom (mocked getHeapStatistics), both for a retained row and for a kept string while it is still unterminated;
      • a 4 MiB ignored member completing with a single heap sample.

      The existing contradiction cases are kept.

    • ownedCommand.test.ts:

      • a sink receives 256 KiB beyond a 1 KiB diagnostic budget, and the command waits for a slow final;
      • a failing sink is a collection failure;
      • a sink still in final when the deadline elapses is destroyed.
  • Base reproduction: shown above for Ghostty, Raycast and XUL with real Kuna 1.833.
  • User-visible CLI output after the change, for rea search t/ghostty ghostty --provider kuna: ok, inventory_count: 107587, selected_count: 383, raw_result.strings.bytes: 30952152.
  • Remaining proof gaps:
    • No Linux host run for this change.
    • Kuna 1.876 was exercised for strings only through the CLI on a small fixture, not on large apps.
    • The headroom refusal is covered only with a mocked heap.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run test:focused -- tests/boundary/providers/kuna/*.test.ts tests/boundary/process/ownedCommand.test.ts: 22 files, 231 tests passed.
  • npm run check:fast (typecheck and lint): passed.
  • npm run knip, npm run docs:check, npm run jscpd: passed.
  • npx tsc --noEmit -p tsconfig.reverse-tools-mutation.json: passes. This is the partial project the Reverse tools quality lane checks; it failed on the earlier .d.ts augmentation and is fixed in 0ce0dbd41.
  • npm run format:check: clean for the changed files. It reports one existing issue in src/adb/AdbProvider.ts on main, which this PR does not touch.
  • REA_KUNA_COMMAND=<kuna 1.833 macos-arm64> npm run verify:kuna on macOS 26.7.1 arm64: passed, MCP workflow including strings, cleanup: "complete". Strings: inventory_count 4, cold scan 501 ms, warm search 2 ms.

Performance

Same CLI question, rea search <target> ghostty --provider kuna, run as a cold CLI process each time. Real Kuna 1.833 on macOS arm64, three samples each. Peak RSS is for the whole process family (REA plus Kuna), sampled every 50 ms. CPU is family user+sys time.

Final code, measured with a load average of about 4 (base and head runs interleaved):

Target Base (origin/main) This PR
zip (208 KB) ok, 1.10–1.91 s, 1.59–2.15 s CPU, 483–487 MiB ok, 1.06–1.14 s, 1.53–1.59 s CPU, 494–500 MiB
Ghostty resource_constraint, 1.11–1.17 s, 501–509 MiB ok, 1.42–1.43 s, 2.08–2.13 s CPU, 549–553 MiB
Raycast resource_constraint, 1.30–1.78 s, 552–596 MiB ok, 1.70–1.72 s, 2.59–2.68 s CPU, 598–609 MiB
XUL resource_constraint, 2.56–2.69 s, 1447–1507 MiB ok, 4.04–4.07 s, 5.56–5.61 s CPU, 1631–1634 MiB
  • Kuna's own scan of XUL peaks at about 1.26 GiB. REA's parse overlaps Kuna's writing; in a CPU profile, REA is idle for 2.4 s of the 5.4 s while Kuna works.
  • Reader alone, on XUL's saved 179 MB JSON: 1.53 s, about 350 MiB RSS, and 156 MB heap retained after GC for 611,290 rows. Without detaching kept text from its decoded chunk, the same rows retained 278 MB. A buffered JSON.parse of the same file with the cap lifted takes 2.5 s at a 1.65 GiB peak.
  • Agent output tokens (--token-count), same question: base returns a 194-token error for all three apps. This PR returns 691 (XUL), 755 (Raycast) and 53,644 (Ghostty, 383 matching rows). The search result contract is unchanged and has no paging.
  • Repeated searches in the same session reuse the parsed inventory as before (warm search 2 ms in the lane).
  • Not measured: model billing, and runs on Linux or Windows.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: real Kuna 1.833 (and 1.876 on a small fixture) on macOS arm64. No Linux run.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review:
    • Kuna is still launched only through runOwnedCommand ownership and cleanup.
    • Rejecting the output stops Kuna early.
    • The parser never executes target content.
    • __proto__ and other unknown members are skipped, not assigned.

Author readiness

Human owner: @Kaoru0822

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4318 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/16/2026 **Status:** ✅ Merged **Merged:** 10/16/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/kuna-stream-string-scan` --- ### 📝 Commits (5) - [`48abd8f`](https://github.com/morluto/rea/commit/48abd8fb6ad89c5aa7ba6e402085d5c2f7854371) fix(kuna): stream string scans instead of capping them at 16 MiB - [`46f6fee`](https://github.com/morluto/rea/commit/46f6feee751dda27a7e8453885ab7eef921b32b1) fix(kuna): admit string scan text as it streams and drop sinks with their command - [`0ce0dbd`](https://github.com/morluto/rea/commit/0ce0dbd412e86ab5cc1f7f66865cc9e436451bfb) fix(kuna): type the stream-json tokenizer where it is imported - [`8770e38`](https://github.com/morluto/rea/commit/8770e3833bf05acd1910905e988e358ccfb9fc45) fix(kuna): bound key and number assembly in streamed Kuna JSON - [`72f2de0`](https://github.com/morluto/rea/commit/72f2de07f5e51b2aa3a76c03d2216fb427a69a21) fix(kuna): stream the call graph instead of capping it at 32 MiB (#4329) ### 📊 Changes **20 files changed** (+1408 additions, -271 deletions) <details> <summary>View changed files</summary> 📝 `docs/kuna-provider.md` (+2 -2) 📝 `src/kuna/KunaCommand.ts` (+5 -1) 📝 `src/kuna/KunaJson.ts` (+19 -11) ➕ `src/kuna/KunaJsonStream.ts` (+554 -0) 📝 `src/kuna/KunaLimits.ts` (+3 -2) 📝 `src/kuna/KunaProjectExport.ts` (+3 -4) 📝 `src/kuna/KunaQueryWork.ts` (+43 -1) 📝 `src/kuna/KunaReferenceFiles.ts` (+151 -74) 📝 `src/kuna/KunaReferenceQueries.ts` (+20 -29) 📝 `src/kuna/KunaStringInventory.ts` (+85 -54) 📝 `src/kuna/KunaStringQueries.ts` (+27 -47) 📝 `src/kuna/KunaTargetCommands.ts` (+3 -0) 📝 `src/process/OwnedCommand.ts` (+58 -11) 📝 `tests/boundary/process/ownedCommand.test.ts` (+70 -1) 📝 `tests/boundary/providers/kuna/fakeKuna.ts` (+19 -5) 📝 `tests/boundary/providers/kuna/kunaCommandFailures.test.ts` (+32 -3) 📝 `tests/boundary/providers/kuna/kunaReferenceFiles.test.ts` (+105 -11) 📝 `tests/boundary/providers/kuna/kunaReferences.test.ts` (+4 -1) 📝 `tests/boundary/providers/kuna/kunaStringInventory.test.ts` (+152 -13) 📝 `tests/boundary/providers/kuna/kunaStrings.test.ts` (+53 -1) </details> ### 📄 Description ## Summary Kuna `list_strings` and `search_strings` failed on every real app above roughly 10 MB. REA buffered Kuna's whole string JSON and refused anything above 16 MiB, but Kuna writes about 290 bytes per row. REA now parses the scan as Kuna writes it, so these apps get answers. Refs #1957. ## Problem and expected behavior Trigger: `rea search <app> ghostty --provider kuna` on a thin arm64 app binary. On `origin/main` with real Kuna 1.833 (macOS arm64): ```json {"code":"resource_constraint","message":"kuna strings wrote more than 16777216 bytes of output.","retryable":false, "remediation":{"action":"REA buffers at most 16777216 bytes of kuna strings output, so repeating this request for this target fails the same way. Use another provider for it."}} ``` | Target (thin arm64) | Image | `kuna strings --json` output | Rows | | --- | ---: | ---: | ---: | | Ghostty | 20 MB | 31.0 MB | 107,587 | | Raycast | 53 MB | 29.7 MB | 101,188 | | Firefox `XUL` | 169 MB | 178.8 MB | 611,290 | The 16 MiB cap came from no format or resource constraint, and the original validation only covered SQLite and zlib. Expected: a string question about a large target gets an answer, with memory bounded by what REA keeps rather than by the size of the transport. ## Change and scope - `runOwnedCommand` (`src/process/OwnedCommand.ts`) accepts an optional stdout sink. - The sink receives stdout instead of the retained snapshot, and the command returns only after the sink finishes. - The pipeline follows the command's deadline signal, and a failed collection destroys the sink. - A failing stream is a collection failure. Existing callers are unchanged. - `KunaJsonDocumentReader` (`src/kuna/KunaJsonStream.ts`) owns the token mechanics. - It tokenizes with stream-json's synchronous `jsonParser` (already a dependency; its shape is declared at the import site because stream-json's typings omit it). - Every scalar arrives in chunks and is assembled only as far as it can matter: - keys up to 64 code units, past every kept field name, so an overlong key is skipped unmatched; - kept numbers up to 64 code units, beyond which the document is rejected. Exact u64 tokens are read through the shared `kunaAddressFromJsonNumber`, which `parseKunaJson` now uses too; - kept strings, which can carry target-derived text of any length, admitted against heap headroom as they grow. - Ignored members, fields and values are dropped unassembled. - Kept text and retained rows are admitted against live heap headroom as they grow, the same approach as `JsonInputFile`, instead of a fixed scan size. Kept text is copied out of the decoded chunk it was sliced from. - The first contradiction aborts Kuna instead of waiting for the rest of its output. An incomplete document is judged only after Kuna's own exit status. - `KunaStringInventoryReader` (`src/kuna/KunaStringInventory.ts`) keeps only the string-scan semantics: the same schema and fact checks per row as before. It replaces `parseKunaStringInventory`. - Kuna diagnostics keep an 8 MiB budget. `KUNA_DIAGNOSTIC_BYTES` is now shared with the project export, and `KUNA_STRING_OUTPUT_BYTES` is removed. - Not changed: string results and contracts, the complete-result semantics (no paging), the graph's 32 MiB buffer and the xref buffer. Contribution scope: a fix inside the existing Kuna provider. No new authority, target execution, injection, mutation or protection recovery. A maintainer scope decision is not applicable. There are no new dependencies and no new MCP tool names or input fields. ## Contract and boundary impact - Semantic owner and earliest changed stage: `KunaStringInventoryReader` owns parsing and validation of the string scan; `runOwnedCommand` gains an optional stdout sink. - Contribution scope fit and linked maintainer decision: fix within existing boundaries; not applicable. - CLI and MCP/tool-catalog contract: unchanged. Large targets now answer instead of returning `resource_constraint`. - Provider, bridge, target-format, or platform compatibility: same Kuna command and arguments. Unknown JSON members are still tolerated, as the previous non-strict schema did. - Evidence, artifact, provenance, or reconstruction contract: `raw_result.strings` keeps its digest, size, scope, policy and counts. The SHA-256 now covers the streamed bytes, which are the same bytes as before. - Target selection, authority, upstream behavior, and cleanup details: Kuna now stops on the first rejected row. Process ownership and cleanup still go through `runOwnedCommand`. - Generated metadata, package, or installation impact: none. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: - `kunaStrings.test.ts`: a 24 MiB scan answers. It fails on base with the 16 MiB `resource_constraint`. - `kunaStrings.test.ts`: a contradictory first row followed by a hang returns `AnalysisOutputError` within about 1 s. On base it waits for the 60 s project deadline. - `kunaStrings.test.ts`: the oversize-retention case now floods stderr past `KUNA_DIAGNOSTIC_BYTES`, keeping coverage that deterministic buffer failures are retained until close. - `kunaStringInventory.test.ts` now drives the reader through 1–3 byte chunks (multi-byte UTF-8 across chunk boundaries, digest equal to the whole text). It also covers: - truncated, trailing, array-root and empty documents, and invalid UTF-8; - a textual address, referencing functions, and ignored and `__proto__` members; - an early abort signal; - refusal on heap headroom (mocked `getHeapStatistics`), both for a retained row and for a kept string while it is still unterminated; - a 4 MiB ignored member completing with a single heap sample. The existing contradiction cases are kept. - `ownedCommand.test.ts`: - a sink receives 256 KiB beyond a 1 KiB diagnostic budget, and the command waits for a slow `final`; - a failing sink is a collection failure; - a sink still in `final` when the deadline elapses is destroyed. - Base reproduction: shown above for Ghostty, Raycast and XUL with real Kuna 1.833. - User-visible CLI output after the change, for `rea search t/ghostty ghostty --provider kuna`: `ok`, `inventory_count: 107587`, `selected_count: 383`, `raw_result.strings.bytes: 30952152`. - Remaining proof gaps: - No Linux host run for this change. - Kuna 1.876 was exercised for strings only through the CLI on a small fixture, not on large apps. - The headroom refusal is covered only with a mocked heap. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run test:focused -- tests/boundary/providers/kuna/*.test.ts tests/boundary/process/ownedCommand.test.ts`: 22 files, 231 tests passed. - `npm run check:fast` (typecheck and lint): passed. - `npm run knip`, `npm run docs:check`, `npm run jscpd`: passed. - `npx tsc --noEmit -p tsconfig.reverse-tools-mutation.json`: passes. This is the partial project the Reverse tools quality lane checks; it failed on the earlier `.d.ts` augmentation and is fixed in 0ce0dbd41. - `npm run format:check`: clean for the changed files. It reports one existing issue in `src/adb/AdbProvider.ts` on main, which this PR does not touch. - `REA_KUNA_COMMAND=<kuna 1.833 macos-arm64> npm run verify:kuna` on macOS 26.7.1 arm64: passed, MCP workflow including strings, `cleanup: "complete"`. Strings: `inventory_count` 4, cold scan 501 ms, warm search 2 ms. ### Performance Same CLI question, `rea search <target> ghostty --provider kuna`, run as a cold CLI process each time. Real Kuna 1.833 on macOS arm64, three samples each. Peak RSS is for the whole process family (REA plus Kuna), sampled every 50 ms. CPU is family user+sys time. Final code, measured with a load average of about 4 (base and head runs interleaved): | Target | Base (`origin/main`) | This PR | | --- | --- | --- | | zip (208 KB) | ok, 1.10–1.91 s, 1.59–2.15 s CPU, 483–487 MiB | ok, 1.06–1.14 s, 1.53–1.59 s CPU, 494–500 MiB | | Ghostty | `resource_constraint`, 1.11–1.17 s, 501–509 MiB | ok, 1.42–1.43 s, 2.08–2.13 s CPU, 549–553 MiB | | Raycast | `resource_constraint`, 1.30–1.78 s, 552–596 MiB | ok, 1.70–1.72 s, 2.59–2.68 s CPU, 598–609 MiB | | XUL | `resource_constraint`, 2.56–2.69 s, 1447–1507 MiB | ok, 4.04–4.07 s, 5.56–5.61 s CPU, 1631–1634 MiB | - Kuna's own scan of XUL peaks at about 1.26 GiB. REA's parse overlaps Kuna's writing; in a CPU profile, REA is idle for 2.4 s of the 5.4 s while Kuna works. - Reader alone, on XUL's saved 179 MB JSON: 1.53 s, about 350 MiB RSS, and 156 MB heap retained after GC for 611,290 rows. Without detaching kept text from its decoded chunk, the same rows retained 278 MB. A buffered `JSON.parse` of the same file with the cap lifted takes 2.5 s at a 1.65 GiB peak. - Agent output tokens (`--token-count`), same question: base returns a 194-token error for all three apps. This PR returns 691 (XUL), 755 (Raycast) and 53,644 (Ghostty, 383 matching rows). The search result contract is unchanged and has no paging. - Repeated searches in the same session reuse the parsed inventory as before (warm search 2 ms in the lane). - Not measured: model billing, and runs on Linux or Windows. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: real Kuna 1.833 (and 1.876 on a small fixture) on macOS arm64. No Linux run. - Package or release metadata impact: none. - Security, privacy, process, or containment review: - Kuna is still launched only through `runOwnedCommand` ownership and cleanup. - Rejecting the output stops Kuna early. - The parser never executes target content. - `__proto__` and other unknown members are skipped, not assigned. ## Author readiness Human owner: @Kaoru0822 - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:12:23 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6168
No description provided.