[PR #5299] [CLOSED] fix(native): mark breakpoints that resolve only outside the target image #6866

Closed
opened 2026-11-01 21:43:40 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5299
Author: @DanielCvz1
Created: 10/19/2026
Status: ❌ Closed

Base: main ← Head: fix/breakpoint-outside-target


📝 Commits (1)

  • abd1911 fix(native): mark breakpoints that resolve only outside the target image

📊 Changes

2 files changed (+91 additions, -1 deletions)

View changed files

📝 src/native/NativeCallObservation.ts (+25 -1)
📝 tests/boundary/providers/native/nativeCallObservation.test.ts (+66 -0)

📄 Description

Summary

Fixes #5298.

observe_native_calls reported a breakpoint as resolved, and coverage as complete, when every one of its locations was in an image other than the target. LLDB resolves an unscoped name in every loaded image, so _main on an AppKit-linked executable resolves only to AppKit. This change reports that case as partial with an explicit limitation, the same way unresolved breakpoints are reported.

Problem and expected behavior

Smallest trigger: a function breakpoint without module whose name matches only outside the target, such as _main on an executable linked against AppKit. Violated invariant: coverage.status: "complete" should not hold when a requested breakpoint observes nothing in the target. The existing limitation already defines unresolved as "matched no code in any image loaded while observing", so a match in another image went unflagged.

Change and scope

nativeCallFacts in src/native/NativeCallObservation.ts gets a seventh partial-coverage cause next to the existing six, plus one limitation in the existing format. It claims the case only when it is provable: every location was retained (locations.length === location_count) and each one names a known image (module_path !== null) other than run.target_identity.module_path. Truncated location lists, locations with an unknown image and an unknown target identity stay undecided, because the existing limitations already report those cases. Both paths compared come from LLDB's own readback.

Not included: no new coverage field, no schema or contract change, and no change to breakpoint resolution or process launch.

Follow the contribution scope. Ordinary fix within existing boundaries; maintainer scope decision: not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: native call observation projection (nativeCallFacts).
  • Contribution scope fit and linked maintainer decision: ordinary fix inside an existing tool; not applicable.
  • CLI and MCP/tool-catalog contract: unchanged schema. For this case coverage.status becomes partial (an existing value) and limitations gains one string.
  • Provider, bridge, target-format, or platform compatibility: native-macos LLDB lane only; tracer and bridge unchanged.
  • Evidence, artifact, provenance, or reconstruction contract: none changed.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Expected effects (check known effects; use documentation-only on its own).
Unchecked items do not establish absence; leave uncertainties visible.

  • 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.

The tool still launches a process as before; this change adds no new effect beyond reading the captured run.

Evidence and regression coverage

  • Tests added or updated: one boundary test, observe_native_calls projection: reports breakpoints that missed the target, in tests/boundary/providers/native/nativeCallObservation.test.ts. It covers the provable case (all locations in AppKit) and three undecided cases: a target location present, a location with an unknown image, and omitted locations.

  • Base reproduction or other evidence: executed. On 71ae02c without the fix the new test fails (status: "complete", expected "partial"); with the fix it passes. Real LLDB run on the same executable and request, before and after:

    revision coverage.status new limitation
    71ae02c (base) complete none
    this PR partial Breakpoints 1 resolved only to code outside the target image; their calls in the target could not be observed.
  • User-visible CLI/MCP output (if applicable): the limitation above; reproduction steps are in #5298.

  • Remaining proof gaps: one host only (macOS 26.5.2, arm64); x86_64 untested; the MCP path shares this projection but was not exercised separately; the full test suite was not run locally (CI owns it).

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/native/nativeCallObservation.test.ts: on base, 1 failed and 9 passed (the new test); with the fix, 10 passed.
  • npm run check:fast: typecheck and lint passed.
  • npm run check: 6 of 6 tasks passed (typecheck, lint with 0 errors, oxfmt --check, knip, metadata), and architecture guards passed.
  • npm run verify:test-discovery: all 1,684 test files discovered exactly once.
  • node scripts/rea.mjs observe-native-calls <executable> <request> under real LLDB lldb-2100.0.17.203, before and after: results in the table above.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Callers that relied on complete for this case now get partial with a limitation, which is the intended correction.
  • Real Hopper/Ghidra, browser, or OS coverage: native-macos LLDB on macOS 26.5.2 arm64; Hopper and Ghidra not involved.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no new process, file or network effect.

Author readiness

Human owner: @DanielCvz1

  • 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.

Observed By Axon powered by Opus 5.5

🤖 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/5299 **Author:** [@DanielCvz1](https://github.com/DanielCvz1) **Created:** 10/19/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/breakpoint-outside-target` --- ### 📝 Commits (1) - [`abd1911`](https://github.com/morluto/rea/commit/abd19111f050dc5e7f0f00c0cc5e9bc31bca8073) fix(native): mark breakpoints that resolve only outside the target image ### 📊 Changes **2 files changed** (+91 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `src/native/NativeCallObservation.ts` (+25 -1) 📝 `tests/boundary/providers/native/nativeCallObservation.test.ts` (+66 -0) </details> ### 📄 Description ## Summary Fixes #5298. `observe_native_calls` reported a breakpoint as resolved, and coverage as `complete`, when every one of its locations was in an image other than the target. LLDB resolves an unscoped name in every loaded image, so `_main` on an AppKit-linked executable resolves only to AppKit. This change reports that case as `partial` with an explicit limitation, the same way unresolved breakpoints are reported. ## Problem and expected behavior Smallest trigger: a function breakpoint without `module` whose name matches only outside the target, such as `_main` on an executable linked against AppKit. Violated invariant: `coverage.status: "complete"` should not hold when a requested breakpoint observes nothing in the target. The existing limitation already defines unresolved as *"matched no code in any image loaded while observing"*, so a match in another image went unflagged. ## Change and scope `nativeCallFacts` in `src/native/NativeCallObservation.ts` gets a seventh partial-coverage cause next to the existing six, plus one limitation in the existing format. It claims the case only when it is provable: every location was retained (`locations.length === location_count`) and each one names a known image (`module_path !== null`) other than `run.target_identity.module_path`. Truncated location lists, locations with an unknown image and an unknown target identity stay undecided, because the existing limitations already report those cases. Both paths compared come from LLDB's own readback. Not included: no new `coverage` field, no schema or contract change, and no change to breakpoint resolution or process launch. Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). Ordinary fix within existing boundaries; maintainer scope decision: not applicable. ## Contract and boundary impact - Semantic owner and earliest changed stage: native call observation projection (`nativeCallFacts`). - Contribution scope fit and linked maintainer decision: ordinary fix inside an existing tool; not applicable. - CLI and MCP/tool-catalog contract: unchanged schema. For this case `coverage.status` becomes `partial` (an existing value) and `limitations` gains one string. - Provider, bridge, target-format, or platform compatibility: native-macos LLDB lane only; tracer and bridge unchanged. - Evidence, artifact, provenance, or reconstruction contract: none changed. - Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. Expected effects (check known effects; use documentation-only on its own). Unchecked items do not establish absence; leave uncertainties visible. - [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. The tool still launches a process as before; this change adds no new effect beyond reading the captured run. ## Evidence and regression coverage - Tests added or updated: one boundary test, `observe_native_calls projection: reports breakpoints that missed the target`, in `tests/boundary/providers/native/nativeCallObservation.test.ts`. It covers the provable case (all locations in AppKit) and three undecided cases: a target location present, a location with an unknown image, and omitted locations. - Base reproduction or other evidence: executed. On `71ae02c` without the fix the new test fails (`status: "complete"`, expected `"partial"`); with the fix it passes. Real LLDB run on the same executable and request, before and after: | revision | `coverage.status` | new limitation | |---|---|---| | `71ae02c` (base) | `complete` | none | | this PR | `partial` | `Breakpoints 1 resolved only to code outside the target image; their calls in the target could not be observed.` | - User-visible CLI/MCP output (if applicable): the limitation above; reproduction steps are in #5298. - Remaining proof gaps: one host only (macOS 26.5.2, arm64); x86_64 untested; the MCP path shares this projection but was not exercised separately; the full test suite was not run locally (CI owns it). 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/native/nativeCallObservation.test.ts`: on base, 1 failed and 9 passed (the new test); with the fix, 10 passed. - `npm run check:fast`: typecheck and lint passed. - `npm run check`: 6 of 6 tasks passed (typecheck, lint with 0 errors, `oxfmt --check`, knip, metadata), and architecture guards passed. - `npm run verify:test-discovery`: all 1,684 test files discovered exactly once. - `node scripts/rea.mjs observe-native-calls <executable> <request>` under real LLDB `lldb-2100.0.17.203`, before and after: results in the table above. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Callers that relied on `complete` for this case now get `partial` with a limitation, which is the intended correction. - Real Hopper/Ghidra, browser, or OS coverage: native-macos LLDB on macOS 26.5.2 arm64; Hopper and Ghidra not involved. - Package or release metadata impact: none. - Security, privacy, process, or containment review: no new process, file or network effect. ## Author readiness Human owner: @DanielCvz1 - [x] 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. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] 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. --- Observed By Axon powered by Opus 5.5 🤖 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-11-01 21:43:40 +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#6866
No description provided.