[PR #4070] [MERGED] fix(kuna): report a failed export as not retryable in its session #6034

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

📋 Pull Request Information

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

Base: main ← Head: fix/kuna-failed-export-not-retryable


📝 Commits (4)

  • b94558d fix(kuna): report a failed export as not retryable in its session
  • 62fe22b fix(kuna): keep a failed export's output and name the restart it needs
  • b54a877 fix(kuna): keep resource limits on a failed export's capability error
  • d8c0b6d refactor(kuna): carry a failed export's whole projection on its wrapper

📊 Changes

3 files changed (+132 additions, -2 deletions)

View changed files

📝 docs/kuna-provider.md (+1 -1)
📝 src/kuna/KunaSessionClient.ts (+49 -1)
📝 tests/boundary/providers/kuna/kunaProvider.test.ts (+82 -0)

📄 Description

Summary

A Kuna session builds its project export at most once. When the export fails, every later request that needs it (procedure_assembly, analyze_function, data-name address_name) got the stored failure back unchanged. For a timeout, MCP projected that as retryable: true with "Analysis took too long. Try a smaller request…". Repeating the request, or trying a smaller function, returned the same stored failure in about 1 ms, so an agent following the hint loops without any chance of success. Refs #1957.

Problem and expected behavior

Smallest trigger: REA_KUNA_PROJECT_TIMEOUT_MS=2000, cold cache, real Kuna 1.833, MCP on zip (arm64e):

procedure_assembly main  2592 ms  code=timeout retryable=true  "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues."
procedure_pseudo_code main  ok (single-function), project_export.state = "failed"
procedure_assembly main     1 ms  identical timeout error, retryable=true

Expected: the error says the export failed for this session, is not retryable as-is, and names what must change before reopening the target.

Change and scope

#awaitProject passes a failed build through exportUnavailable(operation, failure). It returns an AnalysisCapabilityUnavailableError with retryable: false that keeps:

  • cause: the original export error;
  • diagnostics.export_error, export_code and export_details: the cause's tag and its own projected code and details, carried whole. That covers captured Kuna output, resource limits, artifact-change path and reason, and the cause's diagnostics. The MCP/CLI projection does not recurse into cause, so hand-copying fields kept dropping some; that is what three review findings reported;
  • a user message: Kuna's project export failed, so <operation> is unavailable in this session: <reason>. <next step>

For a timeout, the next step is to set REA_KUNA_PROJECT_TIMEOUT_MS above N ms or raise REA_KUNA_JOBS in the environment that starts REA, then restart REA, because KunaProvider snapshots its environment at startup, and reopen the target. For a resource constraint (for example, an export larger than the cache cap), it is the cause's own remediation plus the same restart. For other failures, it is to resolve the failure and reopen the target. AnalysisCancelledError and errors with incomplete cleanup pass through unchanged, so cancellation and retained-cleanup reporting still work. Pseudocode is unaffected: it already falls back to single-function runs and reports the export failure in its limitations. docs/kuna-provider.md documents the behavior.

Not included: rebuilding a failed export within the same session. A deterministic timeout would just burn the same deadline again; reopening the target already starts a fresh build. Generic timeout retryability is unchanged for other providers.

Scope: an ordinary fix within the existing Kuna provider boundary; no maintainer scope decision applies.

Contract and boundary impact

  • Semantic owner and earliest changed stage: KunaSessionClient, the owner of "a session never rebuilds a failed export".
  • Contribution scope fit and linked maintainer decision: not applicable.
  • CLI and MCP/tool-catalog contract: no schema change. For these requests after a failed export, the error code changes from the cause's (timeout, resource_constraint, adapter failure) to capability_unavailable with retryable: false; the cause's tag stays in details.diagnostics.export_error.
  • Provider, bridge, target-format, or platform compatibility: Kuna only.
  • Evidence, artifact, provenance, or reconstruction contract: unchanged. The failure stays visible in raw_result.project_export of pseudocode answers.
  • Target selection, authority, upstream behavior, and cleanup details: no process or file change. Unproven-cleanup errors are not rewrapped.
  • 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: kunaProvider.test.ts gets "reports a failed export as not retryable in its session". It covers a timed-out export (fake hangs, 300 ms deadline), a failed export (exit-failure) and an export larger than a 1 MiB REA_KUNA_CACHE_MAX_BYTES. For both procedure_assembly and analyze_function it checks retryable: false, the exact next-step text, the cause's tag, and that the wrapper's projected diagnostics.export_details equals the cause's own projected details. It also spot-checks the limits or captured output. Every review fix fails this test on its previous head.

  • Base reproduction: both cases fail on the base revision (git stash of src/kuna).

  • Real Kuna 1.833, same trigger as above, after the fix:

    procedure_assembly main  2311 ms  code=capability_unavailable retryable=false
      "Kuna's project export failed, so procedure_assembly is unavailable in this session: Analysis operation timed out after 2000ms: kuna:decompile-project. To retry, set REA_KUNA_PROJECT_TIMEOUT_MS above 2000 ms or raise REA_KUNA_JOBS in the environment that starts REA. REA reads Kuna settings when it starts, so restart REA, then reopen the target."
      details.diagnostics: {export_error: "AnalysisTimeoutError", export_code: "provider_timeout",
                            export_details: {operation: "kuna:decompile-project", timeout_ms: 2000,
                                             captured_output: {stdout: "", stderr: "", exit_code: null, signal: "SIGKILL"}}}
    

    analyze_function returns the same shape in about 3 ms.

  • Cost: one error is larger (1431 vs 630 serialized bytes, including the cause's projected details) because it names the cause and the fix. In exchange, an agent following the old retryable: true hint repeated a request that could not succeed. Model tokens were not measured.

  • Remaining proof gaps: no Linux run; the resource-constraint branch (export larger than the cache cap) is source-derived, not exercised by a test.

  • 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: on the latest head, rebased onto main with the Kuna xrefs feature, 137 passed twice. One earlier full run hit a single failure in the untouched cache test "preserves concurrent results and reclaims capacity (pin: true)"; that file then passed 6/6 on its own. I did not establish the cause.
  • New tests on the base revision: 2 failed.
  • npm run check:fast: typecheck and lint passed.
  • npm run docs:check: passed.
  • REA_KUNA_COMMAND=… npm run verify:kuna (real Kuna 1.833, darwin/arm64): passed, process lineage verified, cleanup: "complete".
  • Real MCP timeout reproduction before and after, above.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Error codes change only for Kuna requests after a failed export, and the cause stays in diagnostics.
  • Real Hopper/Ghidra, browser, or OS coverage: real Kuna on macOS arm64 only.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no new side effects.

Author readiness

Human owner:

  • 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/4070 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/15/2026 **Status:** ✅ Merged **Merged:** 10/15/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/kuna-failed-export-not-retryable` --- ### 📝 Commits (4) - [`b94558d`](https://github.com/morluto/rea/commit/b94558d18b6a061f16558a5098484445ee89806c) fix(kuna): report a failed export as not retryable in its session - [`62fe22b`](https://github.com/morluto/rea/commit/62fe22b5fdc4df1e0a8644696392274223cefe98) fix(kuna): keep a failed export's output and name the restart it needs - [`b54a877`](https://github.com/morluto/rea/commit/b54a8774d7482ff991e096fb3612ace8cfa456c2) fix(kuna): keep resource limits on a failed export's capability error - [`d8c0b6d`](https://github.com/morluto/rea/commit/d8c0b6d0ee1995dd0a12275c0907aff5f120a457) refactor(kuna): carry a failed export's whole projection on its wrapper ### 📊 Changes **3 files changed** (+132 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `docs/kuna-provider.md` (+1 -1) 📝 `src/kuna/KunaSessionClient.ts` (+49 -1) 📝 `tests/boundary/providers/kuna/kunaProvider.test.ts` (+82 -0) </details> ### 📄 Description ## Summary A Kuna session builds its project export at most once. When the export fails, every later request that needs it (`procedure_assembly`, `analyze_function`, data-name `address_name`) got the stored failure back unchanged. For a timeout, MCP projected that as `retryable: true` with "Analysis took too long. Try a smaller request…". Repeating the request, or trying a smaller function, returned the same stored failure in about 1 ms, so an agent following the hint loops without any chance of success. Refs #1957. ## Problem and expected behavior Smallest trigger: `REA_KUNA_PROJECT_TIMEOUT_MS=2000`, cold cache, real Kuna 1.833, MCP on `zip` (arm64e): ``` procedure_assembly main 2592 ms code=timeout retryable=true "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." procedure_pseudo_code main ok (single-function), project_export.state = "failed" procedure_assembly main 1 ms identical timeout error, retryable=true ``` Expected: the error says the export failed for this session, is not retryable as-is, and names what must change before reopening the target. ## Change and scope `#awaitProject` passes a failed build through `exportUnavailable(operation, failure)`. It returns an `AnalysisCapabilityUnavailableError` with `retryable: false` that keeps: - `cause`: the original export error; - `diagnostics.export_error`, `export_code` and `export_details`: the cause's tag and its own projected code and details, carried whole. That covers captured Kuna output, resource limits, artifact-change path and reason, and the cause's diagnostics. The MCP/CLI projection does not recurse into `cause`, so hand-copying fields kept dropping some; that is what three review findings reported; - a user message: `Kuna's project export failed, so <operation> is unavailable in this session: <reason>. <next step>` For a timeout, the next step is to set `REA_KUNA_PROJECT_TIMEOUT_MS` above N ms or raise `REA_KUNA_JOBS` in the environment that starts REA, then restart REA, because `KunaProvider` snapshots its environment at startup, and reopen the target. For a resource constraint (for example, an export larger than the cache cap), it is the cause's own remediation plus the same restart. For other failures, it is to resolve the failure and reopen the target. `AnalysisCancelledError` and errors with incomplete cleanup pass through unchanged, so cancellation and retained-cleanup reporting still work. Pseudocode is unaffected: it already falls back to single-function runs and reports the export failure in its limitations. `docs/kuna-provider.md` documents the behavior. Not included: rebuilding a failed export within the same session. A deterministic timeout would just burn the same deadline again; reopening the target already starts a fresh build. Generic timeout retryability is unchanged for other providers. Scope: an ordinary fix within the existing Kuna provider boundary; no maintainer scope decision applies. ## Contract and boundary impact - Semantic owner and earliest changed stage: `KunaSessionClient`, the owner of "a session never rebuilds a failed export". - Contribution scope fit and linked maintainer decision: not applicable. - CLI and MCP/tool-catalog contract: no schema change. For these requests after a failed export, the error code changes from the cause's (`timeout`, `resource_constraint`, adapter failure) to `capability_unavailable` with `retryable: false`; the cause's tag stays in `details.diagnostics.export_error`. - Provider, bridge, target-format, or platform compatibility: Kuna only. - Evidence, artifact, provenance, or reconstruction contract: unchanged. The failure stays visible in `raw_result.project_export` of pseudocode answers. - Target selection, authority, upstream behavior, and cleanup details: no process or file change. Unproven-cleanup errors are not rewrapped. - Generated metadata, package, or installation impact: none. Expected effects: - [x] 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: `kunaProvider.test.ts` gets "reports a failed export as not retryable in its session". It covers a timed-out export (fake hangs, 300 ms deadline), a failed export (`exit-failure`) and an export larger than a 1 MiB `REA_KUNA_CACHE_MAX_BYTES`. For both `procedure_assembly` and `analyze_function` it checks `retryable: false`, the exact next-step text, the cause's tag, and that the wrapper's projected `diagnostics.export_details` equals the cause's own projected details. It also spot-checks the limits or captured output. Every review fix fails this test on its previous head. - Base reproduction: both cases fail on the base revision (`git stash` of `src/kuna`). - Real Kuna 1.833, same trigger as above, after the fix: ``` procedure_assembly main 2311 ms code=capability_unavailable retryable=false "Kuna's project export failed, so procedure_assembly is unavailable in this session: Analysis operation timed out after 2000ms: kuna:decompile-project. To retry, set REA_KUNA_PROJECT_TIMEOUT_MS above 2000 ms or raise REA_KUNA_JOBS in the environment that starts REA. REA reads Kuna settings when it starts, so restart REA, then reopen the target." details.diagnostics: {export_error: "AnalysisTimeoutError", export_code: "provider_timeout", export_details: {operation: "kuna:decompile-project", timeout_ms: 2000, captured_output: {stdout: "", stderr: "", exit_code: null, signal: "SIGKILL"}}} ``` `analyze_function` returns the same shape in about 3 ms. - Cost: one error is larger (1431 vs 630 serialized bytes, including the cause's projected details) because it names the cause and the fix. In exchange, an agent following the old `retryable: true` hint repeated a request that could not succeed. Model tokens were not measured. - Remaining proof gaps: no Linux run; the resource-constraint branch (export larger than the cache cap) is source-derived, not exercised by a test. - [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`: on the latest head, rebased onto main with the Kuna xrefs feature, 137 passed twice. One earlier full run hit a single failure in the untouched cache test "preserves concurrent results and reclaims capacity (pin: true)"; that file then passed 6/6 on its own. I did not establish the cause. - New tests on the base revision: 2 failed. - `npm run check:fast`: typecheck and lint passed. - `npm run docs:check`: passed. - `REA_KUNA_COMMAND=… npm run verify:kuna` (real Kuna 1.833, darwin/arm64): passed, process lineage verified, `cleanup: "complete"`. - Real MCP timeout reproduction before and after, above. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Error codes change only for Kuna requests after a failed export, and the cause stays in diagnostics. - Real Hopper/Ghidra, browser, or OS coverage: real Kuna on macOS arm64 only. - Package or release metadata impact: none. - Security, privacy, process, or containment review: no new side effects. ## Author readiness Human owner: <!-- @GitHub-handle --> - [ ] 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:11:20 +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#6034
No description provided.