[GH-ISSUE #8186] [Design] Make decoded Swift declarations discoverable when procedure categories are unknown #6469

Open
opened 2026-11-01 21:11:23 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @morluto on GitHub (Oct 30, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8186

Before submitting

  • I searched the open and closed issues and pull requests for a related discussion. #1187 addressed an empty modern Swift inventory; #5341 added nominal metadata decoding. #7501 and #7518 concern a different incorrect nested-type classification. #8185 concerns Objective-C class-label recovery.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This discussion does not include credentials, private samples, or sensitive target data.

Decision needed

How should an agent discover decoded Swift declarations when analyze_swift_types can identify Swift procedures but cannot categorize their manglings? Should REA point to inspect_native_dispatch_metadata when that different, target-scoped reader is available?

Context and evidence

On macOS arm64, REA at 47fa6ab3795d547207001ffb01643c0aa39dcad8 plus unrelated Kuna baseline/doctor changes, using Ghidra 12.1.4 and Kuna 1.986, I compiled but did not execute this owned fixture with swiftc -Onone -module-name SwiftAudit:

public protocol AuditAction { func apply(_ value: Int) -> Int }
public struct AuditRecord: AuditAction {
    public let flags: Int
    @inline(never) public func apply(_ value: Int) -> Int { flags + value }
}
public enum AuditStatus { case ready, failed }
@inline(never) public func auditEntry(_ value: Int) -> Int { AuditRecord(flags: 3).apply(value) }
print(auditEntry(4))

In real MCP sessions, analyze_swift_types({}) returned 24 Swift procedure observations with Ghidra and 42 with Kuna, all under other and explicitly unclassified. It warned that some categories could not be established; Kuna also reported unavailable symbol inventory. In the same sessions, inspect_native_dispatch_metadata({"max_records":100}) decoded AuditRecord as a struct, AuditStatus as an enum, the AuditRecord: AuditAction conformance, and a dispatch slot from the Mach-O metadata. Both tools returned Evidence.

The classifier source intentionally leaves substituted manglings unknown. This fixture includes names with substitutions such as _$s10SwiftAudit0B6RecordV5applyyS2iF; that explains the relevant limitation as a source-derived inference, not an assertion that all unclassified names have the same cause. No autonomous agent trial or general Swift coverage was measured.

Expected interaction with targets

Read existing files or captured data.

Boundary details (optional)

These tools answer different questions: categorized procedure names are not an inventory of type declarations, and decoded nominal metadata does not establish the category of every procedure. Preserve unclassified observations and all metadata coverage, target/slice identity, input limits and provider availability. The observed local reader behavior is on macOS for one fixture.

Options and tradeoffs

Consider a conditional, scoped recovery hint, clearer tool descriptions, or an intentionally designed combined investigation workflow. A richer mangling decoder is another option, but must preserve unknowns for unsupported substitutions, nested contexts, and extensions; it should not guess categories from display names. Do not silently merge declarations and procedures or imply a complete inventory.

Verification available so far

I have a prototype or observed results.

Success criteria and open questions

An agent seeking type declarations can discover the separately scoped metadata route when available and understand when neither route is exhaustive. Exercise literal and substituted manglings, metadata-only and symbol-only cases, unavailable readers, and partial/truncated results.

Originally created by @morluto on GitHub (Oct 30, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8186 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related discussion. #1187 addressed an empty modern Swift inventory; #5341 added nominal metadata decoding. #7501 and #7518 concern a different incorrect nested-type classification. #8185 concerns Objective-C class-label recovery. - [x] I understand the contribution scope must be reviewed before integration; open questions are welcome here. - [x] This discussion does not include credentials, private samples, or sensitive target data. ### Decision needed How should an agent discover decoded Swift declarations when `analyze_swift_types` can identify Swift procedures but cannot categorize their manglings? Should REA point to `inspect_native_dispatch_metadata` when that different, target-scoped reader is available? ### Context and evidence On macOS arm64, REA at `47fa6ab3795d547207001ffb01643c0aa39dcad8` plus unrelated Kuna baseline/doctor changes, using Ghidra 12.1.4 and Kuna 1.986, I compiled but did not execute this owned fixture with `swiftc -Onone -module-name SwiftAudit`: ```swift public protocol AuditAction { func apply(_ value: Int) -> Int } public struct AuditRecord: AuditAction { public let flags: Int @inline(never) public func apply(_ value: Int) -> Int { flags + value } } public enum AuditStatus { case ready, failed } @inline(never) public func auditEntry(_ value: Int) -> Int { AuditRecord(flags: 3).apply(value) } print(auditEntry(4)) ``` In real MCP sessions, `analyze_swift_types({})` returned 24 Swift procedure observations with Ghidra and 42 with Kuna, all under `other` and explicitly unclassified. It warned that some categories could not be established; Kuna also reported unavailable symbol inventory. In the same sessions, `inspect_native_dispatch_metadata({"max_records":100})` decoded `AuditRecord` as a struct, `AuditStatus` as an enum, the `AuditRecord: AuditAction` conformance, and a dispatch slot from the Mach-O metadata. Both tools returned Evidence. The classifier source intentionally leaves substituted manglings unknown. This fixture includes names with substitutions such as `_$s10SwiftAudit0B6RecordV5applyyS2iF`; that explains the relevant limitation as a source-derived inference, not an assertion that all unclassified names have the same cause. No autonomous agent trial or general Swift coverage was measured. ### Expected interaction with targets Read existing files or captured data. ### Boundary details (optional) These tools answer different questions: categorized procedure names are not an inventory of type declarations, and decoded nominal metadata does not establish the category of every procedure. Preserve unclassified observations and all metadata coverage, target/slice identity, input limits and provider availability. The observed local reader behavior is on macOS for one fixture. ### Options and tradeoffs Consider a conditional, scoped recovery hint, clearer tool descriptions, or an intentionally designed combined investigation workflow. A richer mangling decoder is another option, but must preserve unknowns for unsupported substitutions, nested contexts, and extensions; it should not guess categories from display names. Do not silently merge declarations and procedures or imply a complete inventory. ### Verification available so far I have a prototype or observed results. ### Success criteria and open questions An agent seeking type declarations can discover the separately scoped metadata route when available and understand when neither route is exhaustive. Exercise literal and substituted manglings, metadata-only and symbol-only cases, unavailable readers, and partial/truncated results.
Author
Owner

@morluto commented on GitHub (Oct 30, 2026):

Further real MCP recovery probe on the same fixture (Kuna 1.986 and Ghidra 12.1.4):

  • With Kuna, analyze_swift_types({"category":"structs","pattern":"AuditRecord"}) returned total 0 and no unclassified rows, even though inspect_native_dispatch_metadata had returned that exact declaration name. The retained mangled names use Swift word substitutions such as _$s10SwiftAudit0B6RecordV5applyyS2iF, so the literal name is not a substring of the provider's name.
  • Filtering instead for Record returned 10 unclassified observations with the existing category-unknown warning. Passing two returned mangled names to REA's demangle_swift produced SwiftAudit.AuditRecord.flags.getter : Swift.Int and SwiftAudit.AuditRecord.apply(Swift.Int) -> Swift.Int with demangler provenance. This is a useful manual path, not a guarantee that shortening a name finds every member.
  • For Ghidra, the exact AuditRecord filter returned 5 explicitly unclassified observations because its provider names include a demangled class context. The category remained unknown for these same substituted manglings.

The two results are consistent with different provider representations and literal filtering; they do not establish a contract violation. They show why an agent cannot automatically use a decoded declaration name as a complete procedure selector across providers. Any combined workflow should retain the input mangling/address, source and partial coverage, and avoid assuming a demangled textual match proves ownership or exhaustive declaration membership.

<!-- gh-comment-id:6532994520 --> @morluto commented on GitHub (Oct 30, 2026): Further real MCP recovery probe on the same fixture (Kuna 1.986 and Ghidra 12.1.4): - With Kuna, `analyze_swift_types({"category":"structs","pattern":"AuditRecord"})` returned total 0 and no unclassified rows, even though `inspect_native_dispatch_metadata` had returned that exact declaration name. The retained mangled names use Swift word substitutions such as `_$s10SwiftAudit0B6RecordV5applyyS2iF`, so the literal name is not a substring of the provider's name. - Filtering instead for `Record` returned 10 unclassified observations with the existing category-unknown warning. Passing two returned mangled names to REA's `demangle_swift` produced `SwiftAudit.AuditRecord.flags.getter : Swift.Int` and `SwiftAudit.AuditRecord.apply(Swift.Int) -> Swift.Int` with demangler provenance. This is a useful manual path, not a guarantee that shortening a name finds every member. - For Ghidra, the exact `AuditRecord` filter returned 5 explicitly unclassified observations because its provider names include a demangled class context. The category remained unknown for these same substituted manglings. The two results are consistent with different provider representations and literal filtering; they do not establish a contract violation. They show why an agent cannot automatically use a decoded declaration name as a complete procedure selector across providers. Any combined workflow should retain the input mangling/address, source and partial coverage, and avoid assuming a demangled textual match proves ownership or exhaustive declaration membership.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.

<!-- gh-comment-id:6538789846 --> @morluto commented on GitHub (Oct 31, 2026): Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.
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#6469
No description provided.