mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 07:47:29 +00:00
[GH-ISSUE #8425] [Bug] Evidence retention refusal discards a completed direct observation #6600
Open
opened 2026-11-01 21:12:34 +00:00 by bsakaguchi
·
24 comments
No Branch/Tag specified
main
release-please--branches--main--components--rea-agents
release-please--branches--main--components--rea-agents--release-notes
codex/procedure-reference-stacked
codex/kuna-independent-retry
codex/byte-search-overlay-coverage
codex/open-failure-target-receipt
codex/kuna-xref-evidence
codex/ghidra-ambiguous-procedure-recovery
codex/function-source-bundle
codex/trace-function-integration-prototype
codex/snapshot-source-closure
codex/recorded-evidence-array-pages
codex/evidence-recovery-redesign
codex/trace-feature-address-scope
codex/call-discovery-scope
codex/ghidra-literal-candidate-evidence
codex/decompile-directory-independent-retry
codex/retry-provenance-base
codex/value-flow-capability-experiment
codex/ghidra-containing-instruction
cursor/readme-discord-button-ef9f
dependabot/github_actions/actions/setup-node-7.1.0
dependabot/github_actions/actions/upload-artifact-7.0.2
dependabot/npm_and_yarn/npm-minor-and-patch-d8d97ce6df
codex/kuna-1989
fix/8559-native-ui-fixture-ownership
fix/8555-go-verifier-mcp-ownership
codex/provider-capability-recovery
fix/8642-rizin-target-stdin
codex/ghidra-memory-effect-scope
codex/ghidra-annotation-entry-selector
codex/ghidra-readonly-recovery
codex/ghidra-regex-verifier-recovery
codex/evidence-discovery-view-guidance
fix/8545-bulk-append-overflow
fix/8428-navigation-refusal-alternatives
codex/address-context-recovery
codex/matching-member-limitations
codex/unknown-scope-contract
codex/evidence-view-guidance
feat/8373-native-trace-views
codex/ghidra-snapshot-verifier-binding
codex/elf-export-visibility
codex/evidence-view-recovery
codex/native-reference-cli-help
codex/provider-candidate-observation-scope
codex/kuna-session-verification
codex/ghidra-switch-lifetime-guidance
codex/pseudocode-paging-discovery
codex/clarify-evidence-view-support
codex/kuna-xrefs-selector-recovery
codex/context-capacity-recovery
codex/evidence-closure-large-links
codex/same-function-evidence-identity
codex/ghidra-verifier-inspected-jdk
codex/audit-guided-workflows
codex/crash-prompt-retained-dossiers
codex/analysis-view-error-recovery
codex/kuna-verifier-target-selection
codex/ghidra-selected-project-call-coverage
codex/docs-native-analysis-scope
codex/ghidra-java-socket-boundary
codex/ghidra-retained-snapshot-verifier
codex/ghidra-search-inventory-facts
fix/8284-zero-argument-parameter-bindings
fix/8198-ui-action-handler-offset
fix/8257-elf-entry-label-identity
fix/8304-deferred-output-schema-projection
fix/8277-call-path-computed-target-uncertainty
fix/pr-8089-conflicts
fix/ci-static-duplicate-export
dependabot/npm_and_yarn/lint-staged-17.6.0
dependabot/github_actions/actions/download-artifact-8.0.2
dependabot/npm_and_yarn/write-file-atomic-8.0.0
dependabot/npm_and_yarn/canonicalize-5.1.0
dependabot/github_actions/actions/cache/restore-6.1.0
dependabot/npm_and_yarn/toon-format/toon-4.4.0
dependabot/github_actions/actions/deploy-pages-5.0.1
codex/review-fixes-pr-2403
codex/review-fixes-pr-2400
codex/process-terminal-width
codex/test-brittleness-cleanup
verify/7167-browser-connect-macos
fix/7167-browser-connect
feat/native-matching-allowance-setting
feat/browser-scenario-dry-run
test/managed-caller-parameters-20261024
codex/parser-fortythird-boundaries
fix/6926-pinvoke-platform-decorations-20261023
fix/6889-har-body-encoding-20261023
fix/6888-sqlite-schema-budget-20261023
fix/dependency-security-gates-6708
cursor/evidence-overwrite-rebase-b4ac
feat/4057-verify-native-exports
fix/windows-acl-observer-overhead-20261022
cursor/erlang-beam-restack-4476
cursor/pe-certificate-review-bf32
fix/6116-javascript-application-fs-errors
fix/6061-unmapped-runtime-script-unknown
feat/browser-scenario-summary
fix/pe-certificates
codex/verify-3407
cursor/rebase-5699
cursor/rebase-5352
cursor/rebase-5600
cursor/fix-cli-schema-omission-10a8
codex/audit-hopper-shutdown-reasons-20261021
fix/demangle-swift-omitted-record
fix/nib-boolean-value-types
cursor/cancellation-partial-observation-a5ac
fix/ib-object-limit-reasons
fix/electron-fuse-limit-advice
fix/kuna-doctor-dangling-cache
fix/fixed-budget-refusal-advice
fix/js-ipc-listener-dedup
fix/js-return-member-provenance
fix/dmg-integrity-retry-advice
fix/ida-doctor-readiness
fix/kuna-version-probe-output-drain
fix/legacy-swift-runtime-name-matching
fix/dylib-lazy-load-commands
fix/browser-scenario-startup-cancel
fix/swift-nested-punycode-classification
fix/compare-unselected-scopes
fix/objc-method-budget-coverage
fix/dmg-mounted-root-observations
audit/ci-tests-20261019-round2
release/6.7.0
fix/wabt-cleanup-retry-resolution
fix/electron-fuse-elf-pe-architecture
fix/native-plist-descriptor-ownership
fix/kuna-caller-cleanup-ownership
experiment/atomic-codemode-20261016
review/first-contributor-3776
fix/call-resolution-full-read-cycles
fix/member-mutation-selection-repeat
experiment/atomic-re-tools-20261015
perf/member-mutation-lazy-origins
perf/static-network-mutation-index
fix/hopper-startup-lifecycle
audit/3050-windows-proof-20261015
feat/windows-window-capture-2183
audit/3049-windows-proof-20261015
audit/3735-macos-fixtures-20261015
fix/batch-decompile-null-pseudocode
fix/kuna-inventory-honors-jobs
experiment/browser-codemode-tool-design-20261015
fix/hopper-clean-runtime-argv
codex/review-2049-27f1b367
review-fixes/pr-2787-routing
fix/3360-scoped-this-emitters
fix/3367-replaced-global-effects
fix/3838-compact-any-value-items
test/hopper-download-probe-20261015
codex/windows-runtime-creation-red-green-20261015
codex/windows-readonly-root-red-green-20261015
codex/windows-root-share-red-green-20261015
codex/exp-1685-win-mcp-startup
codex/bug-sweep-20261015
investigate/2190-windows-package-phases
investigate/3543-macos-cli-deadline
perf/3281-reverse-tools-feedback-quality
fix/3406-hopper-doctor-fixture
fix/3341-wrapper-require-test-context
fix/3301-owned-uninstall-fixtures
fix/3164-compiler-input-ownership
fix/pcap-cleanup-stdout-newline-20261014
perf/interface-builder-summary
codex/review-fixes-pr-1977
fix/ghidra-effective-jvm-platform
fix/docs-turkish-rust-link-20261013
fix/main-maintenance-ci-20261010
fix/recover-binary-session-process-effects
codex/review-fixes-pr-2457
codex/ci-required-cancellation-gate
fix/main-format-baseline-20261013
fix/setup-preserve-entry-fields
cursor/restore-main-checks-1ffc
fix/ghidra-bridge-hashmap-import
codex/shared-ci-jadx-json-default-20261013
codex/shared-ci-ghidra-test-groups-20261013
codex/shared-ci-java-fixture-format-20261013
codex/fix-intrinsic-invocation-boundaries
test/release-preflight-reusable-jobs
test/js-parameter-provenance-expectation
fix/linux-hopper-verification-current
test/2419-ghidra-elf-probe-size
followup/pr-1544-native-ida
codex/fold-pr-2230-contribution
docs/readme-responsible-use
fix/issue-2064
fix/issue-2050
fix/issue-2053
fix/issue-1968
fix/issue-1945
experiment/codemode-bridge-20261011
fix/tool-effects-negative-wording-1904-20261012
fix/1842-electron-interop-provenance
feat/recover-javascript-multi-input
refactor/website-i18n-prep
fix/nativeaot-pe-virtual-extent
fix/browser-verifier-ci-hang
fix/pe-resources-input-selection
docs/beginner-friendly-guides
docs/beginner-setup-guide
fix/javascript-analysis-worker-1563
fix/1649-ghidra-duplicate-names
fix/javascript-export-keys-integration-1369
test/maintenance-boundary-contracts-20261011
review/javascript-export-keys-1369
review/process-live-progress-1483
test/javascript-1495-growth-ratio
fix/ci-escape-timing
docs/normalized-terminal-geometry-1450
release/6.3.0
archive/release-6.3.0-pr1381
release/6.2.0
fix/electron-preload-dynamic-override
fix/javascript-self-referential-bundler-edges
release/6.1.0
cursor/grok-client-cherry-pick-0b56
feat/signature-posture
feat/dyld-shared-cache
feat/artifact-integrity-policy
feat/pkg-inventory
release/6.0.0
chore/sync-release-5.0.0
release/5.0.0
cursor/cloud-agent-node-787e
fix/javascript-xhr-open-endpoints
review/pr-711-realpath-fallback-wording
cleanup/replay-confinement
codex/test-suite-performance
codex/issue-foundations
codex/address-open-issues-2026-07-20
agent/javascript-vite-rollup-esbuild-adapters
agent/process-cleanup
agent/triage-integration
agent/unknown-commands-registry
feat/mcp-identity-metadata
morlvps/issue_cleanup
codex/installer-redesign
morl/roadmap-investigation-core
morl/roadmap-investigation-docs
release-please--branches--main--components--rea
rea-agents-6.8.0
rea-agents-6.7.0
rea-agents-6.6.0
experiment/atomic-codemode-wait-runtime-20261016
rea-agents-6.5.0
rea-agents-6.4.0
rea-agents-6.3.0
rea-agents-6.2.0
rea-agents-6.1.0
rea-agents-6.0.0
rea-agents-5.0.0
rea-agents-4.1.0
rea-agents-4.0.1
rea-agents-4.0.0
rea-agents-3.2.1
rea-agents-3.2.0
rea-agents-3.1.0
rea-agents-3.0.0
rea-agents-2.7.0
rea-agents-2.6.0
rea-agents-2.5.1
rea-agents-2.5.0
rea-agents-2.4.0
rea-agents-2.3.0
rea-agents-2.2.0
rea-agents-2.1.0
rea-agents-2.0.0
rea-agents-1.7.0
rea-agents-1.6.0
rea-agents-1.5.0
rea-agents-1.4.0
rea-agents-1.3.0
rea-agents-1.2.0
rea-agents-1.1.0
rea-agents-1.0.0
rea-agents-0.5.0
rea-agents-0.4.0
rea-agents-0.3.0
rea-0.2.1
rea-0.2.0
Labels
Clear labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
Mirrored from GitHub Pull Request
question
roadmap
triage
No labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
question
roadmap
triage
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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#6600
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @morluto on GitHub (Nov 1, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8425
Before submitting
Area
Evidence, artifacts, or reconstruction
Observed behavior
A successful real Kuna
address_nameobservation is dropped from the MCP error when the investigation rejects its Evidence record for capacity. An instrumented production session captured the exact provider result_main, Kuna 1.986 identity, analysis profile and limitations during the same tool call. The caller receivedresource_constraintwith retention recovery but nopartial_observation; the investigation contained no Evidence records.Reproduction
BinarySessionwith the real Kuna provider andInvestigationRecords({maximumRepresentationBytes: 0}). This injects a test boundary; it is not a public configuration setting.executereturn. Open an owned arm64 Mach-O with the real REA MCP server and TypeScript SDK in-memory transport, and resolve its actual document identity.address_namefor a valid function address. The wrapper observed one successful returned provider result_mainwith its original provider/profile/limitations. The MCP response wasresource_constraintforrecord_evidenceand contained no completed observation; the Evidence bundle was empty. The executable digest remained unchanged and it was not executed.A default-allowance positive control from the related context investigation returned and retained direct name Evidence. This is one instrumented run under an artificial zero allowance; production-default exhaustion and other providers are unverified.
Expected behavior
Preserve the successfully completed observation and its provenance together with the retention error when delivery permits. A caller must be able to distinguish complete inline but unretained Evidence from a retained reference; never advertise a ledger reference for an uncommitted record. Define bounded delivery and recovery when a complete result cannot fit the MCP response budget, without losing the original retention diagnosis.
Impact and scope
An agent loses useful provider output even though the provider completed successfully. No claim is made about default-heap frequency, runtime execution, other transports, or autonomous agents. Failure during a multi-stage workflow has additional partial-success and cancellation considerations.
REA version
cb0cb206fb7baaea0c5eca7307c78280ed612963(draft #8424 stack); the affected shared delivery path predates that draft. Main has not been retested for this exact controlled case.Runtime and platform
Node 24.22.1, macOS arm64, Kuna 1.986, TypeScript MCP SDK 2.3.1.
Target and artifact context
Owned static arm64 Mach-O, SHA-256
ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d.Interface
MCP; actual server and SDK in-memory transport with instrumented session composition.
Earliest failure stage
Artifact or evidence registration.
Relevant output or evidence
Same direct call: admitted
address_namereturned_main; MCP returnedresource_constraint,details.operation: record_evidence,details.resource: capacity, with nodetails.partial_observation. The ledger was empty. The wrapper records the return before the MCP adapter attempts Evidence retention; it does not modify the provider result.Analysis or suspected cause
Source-derived:
registerEvidenceToolsconstructs the completed Evidence then passes the recording result toToolResultDelivery.toEvidenceToolResult; on recording failure that delivery method projects only the error. Another path inBinarySessionrecords some internal successful provider observations before returning and can similarly replace a successful execution with the retention failure; a separate exact same-call real-provider check is needed there. Existing partial-observation and response-overflow machinery may help, but their admission and memory limits need end-to-end verification before use.Additional context
#8421 concerns context-facet recovery after a capacity error; #8364 concerns exact composed Evidence handoff. This report covers loss of a completed direct tool observation and may affect other consumers of shared Evidence delivery; only the Kuna call above is runtime verified. Cancellation-specific partial recovery is #4276.
cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0
Composed batch capacity control
On unmodified main
293db94dd, production MCP registration with a simulated provider and an injected zero-byte Evidence ledger completed abatch_decompilepseudocode call. When the provider supplied no separate source record, the attemptedbatch_decompileEvidence retention failed and the caller received a capacity error without the completed batch. When the provider supplied a source Evidence record, that source's retention failed first and the same category of error was returned. Both left the ledger empty. The same controls ran on the experimental #8350 provenance prototype. This is an in-memory MCP boundary test with deliberate fault injection, not a real-provider reproduction or an estimate of default-capacity frequency; it shows that completed composed batches need consideration alongside the direct observation and source-publication paths.On stacked recovery PR #8444 head
5c8e5f869, the same simulated batch controls returned the completed batch as unretained Evidence when its own record was refused. When an upstream source record was refused first, the response contained only that source, not the completed batch. The latter case occurs on that PR alone; it does not require its separate #8384 combination. The PR description records the limitation.Real Ghidra instruction retention and delivery controls
On #8594
c5978bb26, production in-memory MCP registration with real Ghidra 12.1.4 and an injected 128 KiBInvestigationRecordsallowance returnedresource_constraintfromrecord_evidencewith no partial observation and no retained records in both full and compact profiles on the 3,000-slot fixture. Completion of the observation before the retention error is source-derived from the delivery path; the faulted call was not separately instrumented to count its rows. This is an injected boundary, not evidence of normal-capacity exhaustion.On #8444
92adb4252, the equivalent 3,001- and 24,001-reference controls returned the completed instruction aspartial_observation.kind: unretained-evidencein both profiles, with no retained record. At 48,001 references, the response instead explicitly reportedpartial_observation_omittedwithretention: unretained, the Evidence ID andmcp-response-limit; no record was retained. This is truthful omission, but a retained-parent view cannot recover it. All three are stress/controlled runs, not frequency estimates.A fresh one-shot
rea inspect-native-instructionusing #8444 on the unchanged 48,000-slot Mach-O produced all 48,001 references and the same Evidence ID as the omitted result. #8594's offline CLI view read its final reference from the saved CLI JSON. This is a new analysis that happened to match in this one test, not a guarantee across changed targets or projects. SHA-2567d80627b9c62f8c9ba59f21eb85919ac4354c7768270caa4c5374b2f0441dd42stayed unchanged; the fixture was never executed.Saved Ghidra project, exhausted authentication headroom
With real Ghidra 12.1.4/JDK 21 and draft #8444
cc2bd100a, a copied Ghidra project contained a deliberately synthetic historical disabled-analyzer report inserted using a headless script. In both MCP profiles,procedure_pseudo_codeat0x1000003e0with an injectedavailableAuthenticationBytes: () => 0returnedresource_constraintforrecord_evidencewithout a completed observation or an explicit completed-observation omission. The already-authenticatedhealthEvidence containing the historical report was retained. With normal authentication headroom and an injected zero retained allowance on the separate #8444/#8851 admission prototype, the same query returned that source and the completed decompilation as linked, unretained Evidence; with a 1 MB allowance both records were retained. The zero-headroom behavior also reproduced on that prototype.The metadata was synthetic; this tests reporting and publication, not whether that analyzer was actually disabled. REA did not modify the copied project or the target during the controls (target SHA-256
510a23fc3c152175b9977130b3b1711d580e47d22a085cdee6a4e0c9dea2c51a), and the target was not executed. No real OOM was induced. The tests do not yet isolate which application-level publication path drops the omission, so this is a reproduced outcome, not a completed root-cause diagnosis.Diagnosis and unmerged control: The direct MCP handler creates the primary Evidence, records the already-immutable project-history source, and then submits the primary. The ledger's authentication-headroom refusal occurs before it can authenticate and attach a partial record; the handler forwards that error without reporting that the primary completed but was omitted. A separate local prototype adds an omission at the direct MCP publication boundary. With the same real saved Ghidra project and injected zero headroom, both profiles retained the historical source and returned
completed_observation_omittedwithinsufficient-authentication-headroom; the project and target remained unchanged. Two new public-MCP controls fail on the unmodified combined baseline and pass with the prototype; the relevant suites passed 20 tests andcheck:fastpassed. This prototype is not in the PR: reason ownership, CLI and other Evidence-producing adapters, and preconstruction admission still need review before choosing the shared fix.CLI application-path comparison: Calling REA's
runDirectAnalysisapplication entry point with real Ghidra and the same copied project, an injected zero authentication-headroom policy and a 1 MB retained allowance completedprocedure_pseudo_codeand retained two records. With both zero headroom and zero retained allowance, it returned a capacity error containing the unretained historical source and an explicit completed-observation omission. This used the actual CLI application path with an injected session, not a public CLI process configured with a zero limit. The target was not executed or modified.Source inspection explains the difference in admission ordering: the CLI constructs and authenticates an immutable Evidence bundle before
importEvidenceBundle, whose authentication-headroom check is skipped for already-immutable bundles. Thus the CLI success does not establish safe low-heap construction; no real OOM was induced. The unmerged MCP-only omission prototype does not resolve this shared preconstruction concern.Shared admission experiment: A separate unmerged prototype shares one borrowed-observation admission function across session, direct MCP, and one-shot direct analysis before constructing primary Evidence. Real Ghidra saved-project controls with injected zero authentication headroom returned an explicit completed-observation omission in compact/full MCP and through the CLI application entry point; the historical source remained retained when capacity allowed. With normal headroom, zero retained capacity returned both source and completed result as unretained, and a 1 MB allowance retained both, for both MCP profiles and the direct application path. The project and target stayed unchanged. Four focused MCP suites passed (23 tests), the one-shot suite passed (7 tests), and
check:fastpassed. These are injected-policy controls, not actual OOM tests.The experiment remains outside this PR: provider-created source Evidence, broader composed/managed/tool paths, the cost and bounds of envelope/source-link preparation, cancellation/finalization, the CLI bundle's additional construction, and review of the shared ownership contract remain open. It is not yet a complete low-memory guarantee.
The unmerged shared-admission experiment no longer materializes the source-ID array before the headroom decision. It borrows an empty-link envelope and accounts for each ID incrementally using the existing JSON storage estimator; actual Evidence construction still creates the link array after admission. A public MCP stress control supplies 5,000 repeated references to one immutable source with an injected 100 KB authentication allowance: it retains the source and refuses the primary with an explicit omission and a reported estimate above that allowance. Repeated IDs are a synthetic boundary case, not a real-provider prevalence claim. The focused source-publication suite passed (15 tests), and
check:fastpassed. Real Kuna 1.990 (40,000-pointer fixture) and a real Ghidra 12.1.4 copied-project control also preserved the expected zero-headroom omission in both MCP profiles; their targets and the copied project were unchanged. Producer-created source Evidence and remaining admission/cancellation boundaries are still not covered.With the incremental-link admission experiment and normal authentication headroom, the real Kuna 1.990 40,000-pointer fixture under injected zero retained capacity returned the completed
xrefssource as unretained Evidence containing all 40,000 pointer rows in both MCP profiles; the ledger retained zero records and the unexecuted target hash stayed unchanged. Five focused recovery, lifecycle and snapshot suites passed (70 tests). This checks recovery of that source observation, not a completed 40,000-pointer trace or actual low-memory behavior.Ghidra provider-created history scope: The saved-project history schema accepts a fixed seed summary and at most 32 disabled-analyzer names of 120 characters, plus fixed-shape calling-convention summaries. On a disposable project with a deliberately synthetic 32-by-120 disabled-analyzer history report, real Ghidra 12.1.4 through MCP retained and linked the history source in both profiles. The normalized report payload was 4,972 JSON bytes; this excludes the Evidence envelope and is not a peak-memory measurement. REA left the project copy and target unchanged during the read. This bounds the tested history payload and does not establish a realistic large-record failure in this provider path. Other provider-created sources and overall low-headroom behavior remain unverified.
PR-base isolation: The shared admission prototype also applies independently on #8444 head
cc2bd100a, without #8851. On that isolated base, five focused recovery/snapshot suites passed (66 tests) andcheck:fastpassed. Real Ghidra 12.1.4 saved-project controls returned the explicit omission under injected zero authentication headroom in both MCP profiles and the one-shot application path. Real Kuna 1.986address_nameretained the normal result with capacity, and exposed it as unretained under injected zero retained capacity, in both profiles. Owned targets and the Ghidra project copy were unchanged during the reads. This prototype is not pushed to the PR; provider-created sources, finalization cancellation, other direct/composed paths and repeated-admission cost remain to be assessed.Cancellation during final close: On the isolated shared-admission prototype, two one-shot composition controls inject zero authentication headroom and cancel during final session close. With successful close, the resource refusal and explicit omission remain primary and cancellation is a secondary failure. With injected close failure, cleanup remains primary, the resource failure and omission remain visible, the target stays owned, and a subsequent close releases it. Both controls fail without the direct admission change and pass with it; the one-shot suite passed nine tests and
check:fastpassed. Cancellation and cleanup failures were simulated, not reproduced with real Ghidra or Kuna.Repeated-admission cost, preliminary: On macOS arm64 with real Kuna 1.990, a 24,000-pointer owned fixture and both #8444/#8851 locally combined, three alternating fresh-process runs compared the combined baseline with the unmerged shared-admission experiment. Each run made two full-schema MCP
xrefscalls in one session. Median first-call time was 819 ms baseline versus 927 ms experimental; median repeated-call time was 458 ms versus 491 ms. Median full-process elapsed time was 2.48 s versus 2.59 s. Summed process-family RSS sampled viapshad median peaks 1,178,352 KiB versus 1,260,848 KiB; this is sampled RSS and can count shared pages more than once. Sampled family CPU totals, lower bounds because short-lived processes can be missed, had medians 3.01 s versus 3.27 s. Values are host-specific, only three runs per variant, and not proof of a general regression.Both variants returned 24,000 addresses with identical hashes of the normalized address arrays and raw pointer arrays; the structured JSON serialization was 4,034,472 bytes in each. Evidence IDs varied between independent runs with fresh cache directories and were not compared across runs. The target hash stayed unchanged; it was not executed. Token use and full SDK response size were not measured. A fresh cache directory was used for each process; repeated calls share the same session. The prototype performs additional validation/estimation scans at session and adapter boundaries, so profiling and ownership-based reuse should be considered before integration; the timing does not isolate those scans as the sole cause.
Reuse shortcut invalidated: A controlled wrapper around a real Kuna 1.990
xrefscall copied the returned execution, changed its first normalized address to0xdeadbeef, and retained the original session Evidence ID. The combined baseline delivered0xdeadbeef; the unmerged reuse shortcut returned the earlier0x100004000instead, silently discarding the wrapper's result. The wrapper was an intentional test transformation, not a claim that Kuna emitted the changed address or that shipped REA currently has this bug. TheanalysisForAdmissionguard did not detect a wrapper aroundwithAdmittedAnalysis. The shortcut has been removed from the local prototype; the timings below describe the invalidated experiment and are not a proposed safe implementation. Safe reuse requires an owner-issued proof tied to the exact immutable observation and matching request semantics, or reconstruction. After removal, two focused MCP suites passed (21 tests).Retained-record reuse experiment: A separate, unmerged variant reuses a session-retained record for direct MCP delivery only when the execution and public Evidence parameters are the same object, no analysis wrapper is configured, and the retained ID resolves to the requested operation; all other paths keep normal admission and construction. The session strips provider-supplied Evidence IDs. This is an exploratory guard, not a proven general ownership contract.
In three alternating fresh-process comparisons on the same macOS arm64 24,000-pointer Kuna 1.990 workload described above, median baseline/experimental first calls were 800/696 ms and repeated calls 439/326 ms; whole-process elapsed was 2.36/2.17 s. Sampled summed process-family peak RSS medians were 1,375,616/1,166,592 KiB, with shared pages potentially counted twice; sampled CPU lower bounds were 3.03/2.74 s. Both returned 24,000 rows, identical hashes for address/pointer arrays, and 4,034,472 bytes of structured JSON. Token use was not measured. This is a small host-specific result, not a general speed guarantee.
Independent runs produced different full Evidence IDs because the raw Kuna output SHA changed, so a separate instrumented control compared the freshly reconstructed and reused Evidence IDs from the same real provider observation; they matched for initial and repeated calls. The instrumented reconstruction was excluded from timing. Four focused suites passed (64 tests). The target was unexecuted and unchanged. Parameter transformations, mutable/wrapped execution provenance, cancellation, other contracts, forged IDs, and ownership of the reuse proof still need explicit regressions before integration; neither reuse nor the parent admission patch is in #8444.
Session-owned proof experiment: A new unmerged variant binds an authenticated retained record to the exact session-issued execution object, uses immutable retained JSON for the Evidence-bearing fields, and checks the current session ledger, operation, and caller parameters before reuse. A copied or transformed execution has no proof; observations with separate source Evidence fall back. The controlled wrapper around real Kuna output that invalidated the previous shortcut now correctly delivered
0xdeadbeef. A separate same-observation control confirmed reconstructed and reused Evidence IDs matched for initial and repeated calls. The wrapper value is synthetic, not a Kuna finding. Four focused suites passed (64 tests);check:fastpassed.In a new three-runs-per-variant comparison of the 24,000-pointer Kuna 1.990 workload, median baseline/experiment first calls were 827/788 ms, repeated calls 467/355 ms, and full-process elapsed 2.47/2.40 s. Median summed process-family sampled peak RSS was 1,314,480/1,232,624 KiB, potentially double-counting shared pages; sampled CPU lower bounds were 3.22/3.05 s. Both returned 24,000 addresses and identical address/pointer hashes. These are small, host-specific measurements, not a general performance claim; token use was not measured. The unexecuted target was unchanged.
This proof experiment is not in #8444. It changes session-returned object ownership/immutability and needs public regressions for copied and in-place transformations, forged IDs, parameter changes, snapshot replay and source records, as well as review of cache semantics and resource lifetime. The earlier ID-only shortcut remains invalid.
@morluto commented on GitHub (Nov 1, 2026):
I tested a local exploratory patch, not a proposed production fix, that attaches the completed Evidence as a partial observation when recording fails in the shared MCP delivery and the binary session's internal recording path.
address_namecall returnedresource_constraintplus inlinepartial_observationcontaining_main, the original provider/profile and limitations. The ledger remained empty and noretained-evidencereference was offered. An admission-port observer confirmed this was the exact returned execution, not a later re-query.evidence_integrity_mismatch, but the patch still attached that invalid record aspartial_observation. Authentication and retention are different outcomes; a generic failure does not prove the offered record is authentic. A separate authentication-headroom refusal can happen before validation at all.resource_constraintwithoriginal_error_code: resource_constraint,retention: failed, and the subsequent retention failure; the connection remained usable. It did not deliver the completed result. This is a simulated large value, not real Kuna or Ghidra output, and CPU/memory were not measured.For the small real fixtures, minified JSON payloads using
o200k_basegrew from 130 to 718 tokens for the direct Kuna error and from 334 to 1,298 for the Ghidra context response. Those are single examples, not whole-task or performance measurements. Inline Evidence IDs are content identities, not proof the record exists in the session; a solution needs explicit retention state and bounded output. Source inspection also shows error projection may parse/copy a mutable partial before the transport checks its response budget, so representation expansion and available heap need review rather than assuming the wire limit alone bounds memory.The prototype has been removed from the working tree and was not opened as a PR. A production fix needs to distinguish authenticated completed observations from authentication failures, retain the original error and committed records, preserve the unretained-versus-reference distinction, and validate large/cancellation cases. Other real providers, Windows, default-heap exhaustion and autonomous-agent behavior remain unverified.
@morluto commented on GitHub (Nov 1, 2026):
Draft #8426 tests a narrower ledger-owned fix, stacked on #8424. Only a record that passed authentication but failed retention admission is supplied inline as
unretained-evidence; invalid and authentication-headroom refusals do not receive that claim. A real Kuna direct-call control and real Ghidra context control passed with injected small allowances, and the uncommitted IDs were not presented as retained references.A controlled oversized-result test reports the original capacity error and an explicit omission when the inline observation cannot fit. A second test verifies that oversized remaining diagnostics still produce a bounded fallback rather than recursively embedding another unretained record. These are simulated large values; production-default exhaustion, cancellation, Windows and CPU/memory impact are unverified. The separate aggregate handoff remains #8364.
@morluto commented on GitHub (Nov 1, 2026):
A controlled MCP boundary test found a blocking regression in draft #8426. With a production
BinarySession, an 8,000-byte injected Evidence allowance, a simulated provider returning a small name and a 6 MiB procedure name, the #8424 parent returned a successful context response containing the name and the procedure's capacity refusal. On #8426 the unretained Evidence embedded in that facet exceeds the 10 MiB MCP response budget after structured/text expansion, so the entire context response becomesresource_constraintand suggests using CLI JSON even thoughinspect_address_contextis MCP-only. The previously recorded name is still in the bundle, but the caller loses the aggregate response. Both compact and full advertised schema profiles reproduced this; the provider and allowance are controlled test inputs, not a real Ghidra or Kuna oversized observation.The draft must preserve fitting sibling facets when omitting an unretained observation, explicitly report that omission and its delivery constraint, and avoid fabricating a retained reference. Simply dropping all partial Evidence on every call would lose the small recoverable cases tested earlier. This is now called out as blocking in the PR body.
@morluto commented on GitHub (Nov 1, 2026):
Draft #8426 head
dd2b15bf4addresses the context-overflow regression reported above. For the controlled 6 MiB procedure result, both MCP schema profiles now preserve the successful name and a smaller unretained comment, while the omitted procedure record carries an explicit unretained/response-limit marker and its content ID. A two-large-facet case also preserves a smaller partial, and a separate oversized successful-facet control gets MCP operation guidance instead of nonexistent CLI advice. The real Ghidra and Kuna small-result controls still pass; no real provider produced the oversized test value.Omitted records remain unretained. Size ordering uses a bounded in-memory representation estimate, not exact wire size, and may omit more partials than an optimal ordering. If the rest of the context cannot fit, the tool returns its delivery constraint. Aggregate Evidence handoff remains #8364.
@morluto commented on GitHub (Nov 1, 2026):
Additional reproduction on draft #8426 at
dd2b15bf4cbbc5409d6ab15b6776e13ce18b7f78: a completed operation can still be lost if recording one of its source records fails first.With real Ghidra 12.1.4 / JDK 21 and the production
BinarySessionand MCP server,address_namereturnedaudit_checkpoint_evaluatefrom the provider alongside ahealthsource describing historical project analysis reports. With an injected zero-byte Evidence allowance, the caller receivedresource_constraintwith that unretainedhealthsource aspartial_observation, but the requested function name was absent; the ledger contained no records. The normal-allowance control returned the requested result with a link to the source, and retained both records. The selected Ghidra project was a disposable copy with synthetic historical report metadata inserted via headless Ghidra specifically for this test; it does not establish that any analyzer was actually disabled. REA left the project copy and static target unchanged, as verified by file digests; the target was not executed. This does not establish that the default allowance is exhausted in normal use.A separate synthetic-provider test gives the source and the primary result the same operation and parameters but different values. The error still contains only the source. Therefore operation and parameters alone cannot identify a partial as the requested result. Source-derived cause:
BinarySessionadmitsexecution.value.sourceEvidencebefore constructing and recording the primary Evidence and returns the first source failure immediately;registerEvidenceToolshas a similar source-first boundary. Other source-retention consumers should be assessed separately, not assumed reproduced.#8426 improves recovery of an authenticated record that fails admission, but does not preserve a completed primary observation when its source fails first. A follow-up should preserve the primary and source roles, source-retention status and provenance independently; avoid advertising a retained record or complete link closure when admission did not occur, and account for bounded response delivery.
Further source review:
executeComposedWorkflowandexecuteFunctionAnalysisEvidencesimilarly admit provider sources into a separate ledger and return the source failure before preserving the completed execution;retainAnalysisResultSourcesreturns a retention failure in place of an otherwise successful value. These are source-derived risks, not additional runtime reproductions. They suggest a shared ownership and result-model decision across direct and composed paths, followed by boundary tests for each changed consumer.Additional MCP boundary test using a synthetic provider, three distinct sources, and an injected 20,000-byte ledger: source 1 was retained, source 2 was refused and returned as the unretained partial, and source 3 was never attempted. Neither the successful primary result nor sources 1 or 3 appeared in the error. The public
get_evidence_bundledid expose source 1; a same-session retry reran the provider and failed at source 2 again without duplicating source 1. This is a controlled test, not a real-provider or default-capacity frequency claim. The regression matrix should cover already committed, refused, and unattempted sources separately, as well as the completed primary, duplicate retry, and bounded error delivery.A real Ghidra selected-project positive control at normal capacity exported both the name and synthetic project-history source via
export_evidence_bundle; import into a new target-free MCP session recovered identical records and a resolvable primary-to-source link. This verifies that particular happy path, not the failed multi-source path.@morluto commented on GitHub (Nov 1, 2026):
Additional controlled MCP source-order case on
458674fba: a synthetic provider returned three sources. I pre-retained source 3, then injected a 20,000-byte allowance so source 1 could be added and the larger source 2 was refused. Instrumenting the production recorder showed that the operation attempted only sources 1 and 2; source 3 was never attempted in that call, yet the public Evidence bundle contained both sources 1 and 3. A repeat attempted the same first two again without duplicating the first. The primary observation was still absent from the error.Consequently a recovery model must not equate
not attempted in this operationwithnot retained in the investigation: record-attempt outcome and current ledger membership are different facts. This is a simulated provider and artificial limit, not a claim that a real Ghidra or Kuna workload encountered this sequence. The zero-initial-state, source-2-refused control in the earlier comment remains a separate case.@morluto commented on GitHub (Nov 1, 2026):
The source-first loss also reproduces in a public composed MCP workflow on #8426 head
458674fba:compare_functionsthrough the production MCP server and TypeScript SDK in-memory transport. A separate call to the same comparison producer confirms the comparison completes and creates derived Evidence.analyze_functionsource inline; the completedcompare_functionsEvidence ID and result are absent, and the investigation contains no records.Both controlled cases passed. This is synthetic Evidence and injected capacity, not a real-provider or production-default exhaustion claim. The source-derived cause here is
registerFunctionComparisonToolcallingrecordEvidenceSourcesafter computation and returning its failure before delivering the already-computedevidence. The earlier real Ghidra case fails sooner, insideBinarySession, so fixing that session branch alone would leave this independent boundary. A coherent design needs to preserve completed primary observations across both paths, accurately distinguish source admission from ledger membership, and keep response-size and cancellation behavior bounded. #8426 does not yet resolve this composed case.A separate controlled MCP test sets the allowance to exactly the measured retained representation of the two source dossiers (27,564 bytes in this fixture). Both source writes succeeded, then the atomic derived-Evidence-plus-Unknown admission failed with
record_unknown/resource_constraint. The completed comparison was absent from the response and ledger; both input dossiers remained retained, and there were zero Unknown revisions. This is a separate post-source failure stage from the zero-byte case, again using synthetic dossiers and an injected allowance. The current PR'sEvidenceLedger.recordchange does not cover the atomic write. A regression should assert the atomicity and the primary result's actual retention state, including the associated Unknown, rather than silently persisting one half.One further control pre-retained the two inputs and the identical computed comparison, then filled the allowance to their measured size. The new comparison-and-Unknown write again failed, with no Unknown revision, but the public bundle still contained the preexisting primary. Thus even for the primary, failure to commit this atomic operation does not establish that the Evidence ID is absent from the investigation. Recovery must query or report actual membership and independently report that the requested Unknown mutation did not commit; it must not automatically label the primary unretained. One focused MCP case passed with synthetic inputs and an injected limit.
Follow-up: #8426 head
050362143now covers the atomic capacity stage after authentication. The ledger checks actual membership before returning either the preexisting retained reference or the authenticated unretained comparison; the refused write does not add an Unknown revision. Four public MCP tests cover both membership states under compact/full output profiles, and the earlier unretained-result test failed on the previous head. A further controlled test used two real Ghidra dossiers and a target-free MCP session with an injected capacity; it returned the completed unretained comparison. The source-first failures described above remain unresolved, and no default-capacity frequency claim is made.An additional source-authentication control on
050362143exercises a different failure than capacity. A synthetic provider returned a completedaddress_nameresult and a source record whose content was changed without updating its Evidence ID. Public MCP correctly returnedevidence_integrity_mismatch, retained no records, and omitted the completed primary. Separately constructing the primary Evidence showed that its own identity authenticates while its link merely contains the invalid source's claimed ID: authenticating the parent does not authenticate or retain its linked source. The focused MCP probe passed. This is deliberately malformed synthetic provider output, not a real Ghidra or Kuna reproduction. A recovery design must preserve the source integrity error and the primary observation without implying that the source link or closure has been authenticated; a source-capacity-only wrapper is insufficient.A candidate contract to evaluate is one failure carrying two explicitly labeled facts: the completed primary observation, and the source-admission failure (including any separately authenticated source partial). Source-attempt progress and actual ledger membership must remain distinct; a record may have existed before the operation. A retained reference is valid only while its owning session remains available, whereas a one-shot CLI must deliver an inline observation or an explicit omission. If a source fails authentication, preserve the original integrity failure and do not label the primary's linked source or closure authenticated. Apply response-size fallback independently and state which facts were omitted. The same application-level outcome should feed direct and composed MCP/CLI adapters without adding a provider-specific API wrapper. This is a design direction, not an implemented or validated contract; cancellation, final cleanup and retry need their own boundary checks.
A bounded-delivery control on
050362143further exercised the source-first case. A synthetic provider completed a smalladdress_nameprimary and supplied one authenticated source; an injected zero-byte ledger refused the source. With a small source, the response returned the unretained source and omitted the primary. With a source larger than the MCP receive buffer, the response instead explicitly marked the unretained source omitted, still omitted the small primary, preserved the originalresource_constraint, and left the connection usable. Both cases passed; the investigation stayed empty. This is synthetic oversized content and injected capacity, not a real-provider or default-capacity reproduction. A recovery should be able to omit the large source while still delivering the small primary when the remaining error fits, without claiming an authenticated source closure.Isolated source-publication experiment (not a proposed complete fix)
On a local worktree based on #8426
050362143, I prototyped carrying a separately labeled completed primary alongside the original source error, marking source closurenot-establishedand checking current ledger membership before returning a retained reference. For an invalid source ID, the experiment falls back to a raw unretained observation instead of manufacturing valid Evidence. Its delivery experiment tries bounded omission independently for the source and primary, including facet-local failures ininspect_address_context.A real selected-project Ghidra 12.1.4 zero-capacity control returned the real name and the refused synthetic project-history source separately; the target and project copy remained unchanged. A second real Ghidra one-shot application-entry test required the completed primary to preserve the caller's exact path; it failed before the CLI projection change and passed afterward. The provider sessions used test-injected ledger capacity, not production-default exhaustion. A final focused run passed 15 cases: direct small/oversized/invalid-source and preexisting-primary controls, aggregate context overflow, existing context overflow tests, and the real Ghidra one-shot control. These are scripted SDK/application tests, not an autonomous agent evaluation.
A follow-up prototype routes
compare_functionssource refusal through a shared helper: the prior public MCP regression now passes for both a missing primary and an already-retained primary, while preserving the failed source separately. The real Ghidra MCP and one-shot controls passed again after that refactor. The helper checks authentication headroom for an existing mutable completed record.A subsequent experiment guards provider recovery construction using the investigation owner's authentication-headroom policy; with injected zero headroom it preserves the original source error and explicitly marks the primary omitted. A synthetic one-shot control also exposed a preexisting retained primary as an unusable session reference; the experiment materializes it inline before one-shot cleanup and preserves the exact caller path. A malformed-source-ID control preserves caller path on the raw observation. Real Ghidra MCP and one-shot controls passed with the guard. The initial guard estimated the whole provider execution; the follow-up below narrows that estimate and still needs allocation-accounting review.
The prototype is not ready to integrate: other composed consumers have not been adapted; the recovery representation and headroom policy need review; late cancellation/final cleanup and full schema/host coverage remain unresolved.
check:fastpassed after restructuring the experimental test; an earlier run failed its function-length rule. The work remains uncommitted in an isolated worktree; no PR is presented as fixing these gaps.The initial preflight was too broad: a synthetic source containing non-JSON data caused it to omit an otherwise valid primary, and a large source could exhaust the guard even when the primary was small. A revised isolated experiment estimates the primary representation and the source-ID list without copying or validating source bodies. Both controls now preserve the primary and original source failure; a 5,000-source control with limited injected headroom explicitly omits the primary before constructing the ID list. A null or malformed source ID yields a raw observation instead of a fabricated Evidence link. Real Ghidra selected-project MCP and one-shot controls passed again. Source IDs and closure remain unverified. This is experimental; the estimator, other composed consumers, lifecycle, and schema coverage still require review.
@morluto commented on GitHub (Nov 1, 2026):
Additional controlled MCP coverage at the unpublished source-publication prototype based on #8426 (
050362143):compare_process_capturesandcompare_application_versionsboth succeeded with the authored inline contract examples and a normal investigation allowance; their completed comparison Evidence was retained.InvestigationRecords({ maximumRepresentationBytes: 0 }), each returnedresource_constraintwith the refused left input aspartial_observation, but no completed comparison observation. The ledger remained empty. Both producers compute the comparison before attempting to record the source, as confirmed by their adapter call order. The production MCP registration and SDK in-memory transport were used; no provider was launched. Two focused tests passed.This is a test-injected limit, not evidence of production-default exhaustion or autonomous-agent behavior. The prototype remains unpublished and the broader fix is not established by these controls.
@morluto commented on GitHub (Nov 1, 2026):
Another controlled boundary: source retention refusal plus a different facet's incomplete cleanup in
inspect_address_context.On #8426 head
050362143, a productionBinarySession/ MCP server with a synthetic provider and zero-byte injected Evidence allowance returned the refusedhealthsource inline for a directaddress_namecall. The same provider'saddress_namereturned a completed name and that source during the context request; a siblingcommentreturned a syntheticcleanup_incompletefailure namingcomment-owner. The aggregate response correctly reportedcleanup_incompleteand the owner, but contained neither the source partial nor the completed name; the investigation remained empty. One public SDK in-memory MCP test passed.The unpublished source-publication prototype also reproduced the loss: its direct call returned both the source and completed name, but its context response still contained neither when the sibling cleanup failed. One focused test passed. These are synthetic provider outcomes and an injected limit, not a real Ghidra/Kuna cleanup reproduction or default-capacity claim.
Source inspection:
contextFailureselects request-level or cleanup failures; a separate nonfatal capacity failure is not added as a secondary failure once a sibling causes the aggregate to fail. A fix must preserve cleanup ownership and the distinction between the completed facet and failed source, while bounding partial delivery and handling cancellation/finalization. Do not treat this reproduction as authority to discard the cleanup failure or as proof that every successful facet can always be retained. Related aggregate handoff design: #8364.@morluto commented on GitHub (Nov 1, 2026):
Finalization controls for the unpublished source-publication prototype:
read_bytescase pre-retained the primary, then forced its source write to fail at an injected representation limit. Cancellation arrived during final close. With close successful, the originalresource_constraint, refused source and materialized inline primary survived. With a controlled close refusal, the response reportedcleanup_incomplete, retained the cleanup resource and original capacity failure, and still carried both observations and the caller path. The session remained active after the controlled refusal; an explicit retry closed it. Both cases passed. Existing earlier-error precedence was preserved; this is not a claim that a separately canceled MCP request receives a response.analyze_functionobservation and refused project-history source. A test-controlled close refusal and cancellation during finalization producedcleanup_incompletewith the owner, originalresource_constraint, complete primary and caller spelling; explicit retry closed the real session. The target and all selected-project regular-file hashes were unchanged. One test passed. The close failure was injected, not a real Ghidra cleanup failure; the project history was synthetic, the target was not executed, and this exercised the shared one-shot application entry rather than a spawned CLI.sourcePublicationOneShotpassed four focused cases andcheck:fastpassed after adding the lifecycle controls. The context mixed-failure gap and other unpublished prototype limits remain open; these results do not establish all cancellation interleavings, default-capacity exhaustion, other hosts or cleanup failures from real providers.@morluto commented on GitHub (Nov 1, 2026):
I checked a tempting narrow fix for the mixed cleanup/source failure. In the unpublished prototype, I temporarily added the completed facet's error to the fatal cleanup error with
retainSecondaryFailure. Instrumentation confirmed one secondary error was retained, but the same public MCP regression still failed: the response reportedcleanup_incompleteand its cleanup owner, without either the source or the completed name. The change was reverted.Source inspection explains the result:
AnalysisErrorretains secondary failures for lifecycle composition, butprojectAnalysisErrordoes not automatically serialize those failures. A useful fix therefore needs an explicitly owned, bounded representation and projection for mixed facet outcomes, rather than only appending an error in memory. It also needs to avoid embedding oversized observations repeatedly inside cleanup diagnostics; that is a design constraint, not a separately reproduced overflow in this control. Synthetic provider, zero-byte injected ledger, no real-provider cleanup claim.@morluto commented on GitHub (Nov 1, 2026):
Completed native value trace lost while publishing its source
A controlled cross-PR test exposes another completed-result handoff, using real Kuna 1.986 with an injected zero-byte investigation retention allowance. The source-owned arm64 Mach-O was analyzed statically, not executed, and its SHA-256 remained unchanged. The public MCP SDK used production registration with an in-memory transport; both full and compact schema profiles were tested. The test instrumented the workflow return solely to verify whether the trace had completed before publication failed.
5c8e5f869alone, the trace completed with one procedure and the explicit unavailable-def-use unknown. The session then refused to retain the trace, and the publicresource_constrainterror returned the completedtrace_native_valuesrecord as unretained Evidence. This does not fix its separately known missing source citation (#8282).a20c186eb, the trace again completed with one procedure and the same type of unknown. Source retention then failed. The public error returned the unretainedanalyze_functionsource, but did not return the already-completedtrace_native_valuesresult. The session contained no records. Under the normal allowance the same combined workflow returned the trace, retained both records, and preserved the unknown.The observed boundary is narrower than a general production-capacity claim: the zero allowance was injected, the provider observation was real, and no natural exhaustion, stdio transport, Ghidra, cancellation, or cleanup failure was exercised in this control. The server-side workflow completes before
retainAnalysisResultSources; its failure replaces the successful composed result beforecreateWorkflowEvidenceruns. The ledger's partial observation correctly preserves the refused source, but that source is not the user's completed trace.This suggests preserving the completed workflow and the failed source as separate facts at the shared publication owner, with actual retention status and source closure marked unknown/not established. A candidate also needs pre-allocation/headroom and response-budget handling, plus CLI, cancellation, cleanup, and preexisting-primary controls; no fix is claimed here. Related: #8282, #8384, #8444.
@morluto commented on GitHub (Nov 1, 2026):
Exploratory recovery contract control
In an uncommitted isolated combination of #8384 and #8444, a small server-side experiment uses the existing completed-observation projection when source publication fails after the workflow has succeeded. The previous real-Kuna control now returns both the refused
analyze_functionsource and the unretainedtrace_native_valuesEvidence. The latter contains the completed normalized trace, links the returned source ID, and marks source closurenot-established; this passed in full and compact MCP schema profiles. Normal-capacity controls also passed.I then used an internal helper to construct separate canonical bundles from those two returned records, imported the trace and source into a fresh target-free stdio MCP session, and confirmed the trace result and source link were preserved and the source view resolved after its import, in both profiles. No provider ran during offline import. This demonstrates the records' semantics, not an existing user-friendly raw-error-to-bundle workflow or autonomous agent selection. My first offline probe incorrectly applied a filter to
detail: complete; a second incorrectly assumed an analysis view creates no extra Evidence record. The corrected probe checked the relevant exact IDs and results.This experiment is not a merge-ready fix: it materializes the workflow Evidence before a headroom admission check, and CLI parity, delivery budgets, already-retained primary, source publication cancellation, final cleanup and real Ghidra remain unverified. The recovery design should address those boundaries at a shared owner instead of duplicating unchecked construction in one adapter. Earlier failure control: https://github.com/morluto/rea/issues/8425#issuecomment-6555319689.
@morluto commented on GitHub (Nov 1, 2026):
One-shot CLI application control
The same interaction also occurs through the production one-shot CLI application entry
runDirectAnalysiswith real Kuna 1.986 and an injected zero-byte session-retention allowance. The test instrumented the workflow return to confirm the trace completed before recording failed; the source-owned target was not executed and its digest was unchanged. This calls the CLI application entry directly with injected dependencies; it is not a spawned CLI-process or terminal-output test.trace_native_valuesrecord and retained the caller's exact selected spelling, including./.analyze_functionsource; the completed trace and its caller-input path were absent. In both variants, normal-capacity execution succeeded and preserved the explicit unavailable-def-use unknown.This supports putting source-publication recovery in the shared workflow owner used by both adapters. The actual CLI output, cancellation and cleanup failures remain separate checks. Earlier MCP and prototype details: https://github.com/morluto/rea/issues/8425#issuecomment-6555319689 and https://github.com/morluto/rea/issues/8425#issuecomment-6555340869.
@morluto commented on GitHub (Nov 1, 2026):
Shared-owner and delivery controls (experimental)
I moved the previous server-only experiment into the shared workflow owner and used it from the MCP and one-shot CLI application paths. With real Kuna and an injected zero session-retention allowance, both routes returned the completed trace separately from the failed source; the CLI's completed trace retained the caller's exact selected path spelling. Normal-capacity controls passed. These tests exercised production adapters but used an in-memory MCP SDK transport and called the CLI application entry directly.
Two further deliberately injected controls passed:
cleanup_incompleteretained the capacity failure, cancellation and cleanup owner; retrying actual cleanup succeeded.The experiment is still not merge ready: it constructs workflow Evidence before proving authentication headroom. It also needs preexisting-primary and real Ghidra checks, a production-boundary regression rather than these temporary audit probes, and review of the generated response schemas and actual CLI transport. The injected final-close outcome is not a claim that Kuna naturally failed cleanup.
@morluto commented on GitHub (Nov 1, 2026):
Preexisting completed trace control
A further test exercised the shared-owner experiment with real Kuna 1.986 through production MCP registration and the SDK's in-memory transport, in both full and compact schema profiles. After a normal trace, the test directly cleared the injected test ledger while leaving the same provider session open, reinserted only the completed trace, and filled the remaining representation allowance with synthetic Evidence. Repeating the trace caused the missing source admission to fail. The error returned the source as unretained and the exact already-present trace as
retained-evidence, with source closurenot-established; membership checks confirmed the trace remained and source was absent. The target hash was unchanged and the target was not executed. This is a controlled internal ledger setup, not a claim thatreset_investigationretains an open provider or that ordinary workloads exhaust the ledger this way.An attempted cross-session control initially assumed the same trace ID would recur, but did not establish that: REA's private Kuna graph input path changes between sessions, changing the exact graph-document hash and thus the authenticated source and trace IDs. That distinct identity/design question is documented in #8459; the corrected control used a single live session instead. The experimental fix still needs pre-construction memory admission and other checks listed above.
@morluto commented on GitHub (Nov 1, 2026):
Real Ghidra capacity control
On the same uncommitted shared-owner experiment, I ran real Ghidra 12.1.4/JDK 21 against the same source-owned, unexecuted arm64 Mach-O through production MCP registration and the SDK's in-memory transport, compact profile. With normal retention the trace completed with two procedures and 19 nodes. With an injected zero-byte session allowance, the first
analyze_functionobservation completed but its admission failed before the trace completed. The error returned that unretained function Evidence; no completed trace was asserted or manufactured. The target SHA-256 stayed unchanged.This contrasts with the real Kuna control, where the whole trace completed before its source was published and refused. It supports preserving the boundary where the failure actually occurs rather than attaching a trace on every source error. The test invoked session/server close; this control did not independently verify process-family cleanup, other profiles, natural capacity exhaustion, or an existing Ghidra project.
@morluto commented on GitHub (Nov 1, 2026):
Recovery headroom: result-only admission is insufficient
I checked the existing REA JSON representation estimator against the completed-trace Evidence captured in the preceding controls. For the real Kuna record, the normalized result estimated 6,690 value bytes plus 3,398 serialized UTF-16 bytes; the whole Evidence envelope estimated 21,040 plus 8,836. For the real Ghidra record, the respective estimates were 99,460 + 30,810 versus 120,634 + 41,488. These are the repository's representation estimates, not measured heap or process RSS.
The gap can also grow with a workflow's derived metadata. A synthetic
batch_decompileresult with 100 resolved entries produced 100 Evidence locations. With a test-injected 153,776-byte authentication allowance, admitting only the result passed, while admitting the constructed envelope failed: its estimated authentication requirement was 266,464 bytes. No provider or target ran in this synthetic shape control.A recovery fix must therefore account for the complete envelope, derived locations, provider/profile data, source IDs and serialization before materializing it. Reusing the Evidence/profile owners to produce an accurately bounded draft is preferable to duplicating their field interpretation in CLI and MCP adapters. This is an allocation-design constraint; the shared recovery experiment still constructs the envelope before admission and is not merge ready.
@morluto commented on GitHub (Nov 1, 2026):
Deduplication matters when estimating derived locations
An upper bound of one Evidence location per batch item is safe as a byte estimate, but can refuse recovery unnecessarily when many items resolve to the same address. In a synthetic batch-shaped result of 500 repeated resolved addresses,
createWorkflowEvidenceproduced one deduplicated location. With a test-injected authentication allowance exactly equal to the existing estimator's requirement for the actual envelope, the actual envelope was admitted, while a draft charged for 500 locations was refused. With 500 unique addresses, the same calculation matched the actual envelope. The script constructs the Evidence first to establish this counterexample; it is not itself a pre-allocation solution or a process-memory measurement.To check applicability beyond synthetic shape, public stdio MCP on current REA
e18594b, using real Kuna 1.986 and real Ghidra 12.1.4 on the same source-owned Mach-O, acceptedbatch_decompilewith the same address twice. Each returned two successful items and exactly one address location. The input target was not executed and its digest stayed unchanged. These are two-item controls on one host, not a claim about a 500-item provider run or natural memory pressure.A bounded estimator should share the producer's resolved-address and deduplication rules while accounting for the memory needed to derive distinct locations; an unexamined one-per-item upper bound would change which otherwise-fitting answers can be recovered. This remains an open implementation question rather than a proposed cap.
@morluto commented on GitHub (Nov 1, 2026):
The duplicate-location counterexample also holds using the actual two-item
batch_decompileEvidence from each real-provider run above. I applied a test-injected authentication allowance equal to the existing estimator's requirement for that provider's completed envelope. The exact envelope was admitted in each case; a preflight that charged a separate generated location for each of the two items was refused, even though the Evidence owner deduplicated them to one location. The test used retained records offline; no provider ran during the estimator check. This is controlled boundary evidence, not a measurement of natural heap exhaustion. The calculation also used the already-constructed record to establish the counterexample, so a safe pre-construction implementation remains open.@morluto commented on GitHub (Nov 1, 2026):
Stdio and schema controls for the experiment
I ran the shared-owner experiment through a real MCP stdio process using the TypeScript SDK, real Kuna 1.986 and an injected zero-byte session retention allowance. The subprocess assembled the production server/session components with that injected limit; it was a test entrypoint, not the released
rea mcplauncher. In both full and compact schema profiles, the SDK received the typed capacity error containing the unretained source and unretained completed trace, the completed trace linked that exact source ID, and the Kuna unavailable-def-use unknown remained present. A subsequent session summary reported zero retained records andclose_binarysucceeded. The owned target hash remained unchanged and was not executed; process-family cleanup was not independently measured.Separately, I fetched
trace_native_valuesinput/output schemas from the prototype's actual stdio catalog and checked their declared dialect with Ajv 2020 in both profiles; the previously captured real-Kuna success matched each advertised output schema. Three error projections per profile (normal error plus two injected response-budget omissions) validated against REA's canonical error JSON Schema and Zod contract. MCP tool errors use the canonical error projection, not the tool's success output schema. The one-shot CLI application error also passed the canonical CLI envelope Zod check; no spawned CLI-process check is claimed.These controls strengthen transport evidence but do not resolve pre-construction headroom, which remains required before the experimental change is merge ready. Related admission counterexample: https://github.com/morluto/rea/issues/8425#issuecomment-6555503360.
@morluto commented on GitHub (Nov 1, 2026):
Exploratory distinct-location admission
I tried an offline incremental scan that holds distinct addresses and charges only the corresponding Evidence locations, instead of charging one location per input item. Against both captured two-item real-provider records and synthetic 500-item unique/repeated shapes, it reproduced the Evidence owner's exact ordered locations; with a test-injected zero allowance it rejected before adding any location. A separate explicit scratch allowance was included in the calculation.
This is only an algorithm probe, not a safe pre-construction implementation: the probe starts from an already-constructed Evidence envelope, and its assumed per-entry
Setscratch cost is not a proven V8 bound. A production design must construct a borrowed draft from the actual Evidence/profile owner, admit scratch before building it, preserve deduplication order, and validate the remaining serialization/authentication headroom without repeatedly rescanning the entire result. It must also decide how to preserve a raw unretained observation when full Evidence cannot safely be authenticated, without implying an Evidence ID or closure. No target/provider ran in this offline estimator probe.@morluto commented on GitHub (Nov 1, 2026):
SDK wire representation
The same injected-limit stdio control was repeated with the installed TypeScript MCP SDK 2.3.1. In both full and compact profiles the failed
trace_native_valuescall arrived asisError: true, onetextcontent block containing the JSON error, nostructuredContent, and the target-content provenance marker. Parsing the text exposed both recovery records and the link. The SDK source skips the success output-schema validator whenisErroris true; I separately validated the parsed error against REA's canonical error schema. This matches REA's deliberate text-only error transport and the strict-client concern recorded in closed #1261; it is not evidence that an autonomous agent selected the recovery path or that every MCP host consumes it correctly.@kaoru0822-kitauji commented on GitHub (Nov 1, 2026):
A production-default, real-application occurrence of the "nothing retained" outcome, observed twice. This is a JavaScript partial result, not a direct provider observation.
Setup: REA
aa48d494e(plus an unrelated record-selection branch; the bundle, delivery and JavaScript paths are unchanged), macOS arm64, Node 24.22.1, real stdiorea mcpwith default settings:REA_MCP_MAX_RESPONSE_BYTESunset (10 MiB) and default heap. The target is Obsidian 1.12.7's localobsidian.asar(24,060,763 bytes, not executed). The call wasanalyze_javascript_application {input_path, detail: "summary"}.Observed (both runs):
resource_constraintwithreported_limits.original_error_code: "provider_timeout"(the 300,000 ms per-source timeout). The error response was ≥ 10,503,395 bytes againstresult_budget_bytes: 10,484,736, about 19 KB over.constraintwasreceive-buffer.retention: "failed". Retaining the oversized original error failed withrecord_evidence→resource_constraint, "Insufficient live heap headroom to authenticate investigation records". It reportedprojected_value_bytes: 2,852,496,392,serialized_json_utf16_bytes: 921,302,156,authentication_bytes: 7,547,597,096andavailable_heap_bytes: 3,905,340,536.binary_sessionreportedinvestigation.evidence_records: 0,retained_representation_bytes: 0andmaximum_representation_bytes: 1,087,335,542. The completed partial analysis was neither delivered nor retained. The remediation suggested a larger response budget, but the original error was never retained to retry against./usr/bin/time -lon the server process).Source-derived, not verified: the partial observation here is not itself an
Evidencerecord. SotoPartialErrorToolResultfalls back to inline delivery, and the oversized-error path then tries to retain the whole original error (resultplusrawResult), which is far larger than the 10.5 MB wire projection.Not established: natural frequency, other hosts or heaps, and whether a smaller retained partial parent (as #8296 observed on its candidate branch) would avoid this. I have not tested #8444. Related: #8296.