[PR #3787] [MERGED] feat(artifacts): inspect and extract .NET single-file bundles #5899

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3787
Author: @Zhong-fan
Created: 10/15/2026
Status: ✅ Merged
Merged: 10/29/2026
Merged by: @gensokyo-dev

Base: main ← Head: feat/2352-dotnet-single-file


📝 Commits (10+)

  • 34ad3f6 feat(artifacts): inventory and extract .NET single-file bundles
  • dfdb7a8 fix(artifacts): retain bundle source I/O failure reasons
  • 7bef0a2 docs(artifacts): record Linux bundle regression verification
  • 00de2c9 fix(artifacts): preserve bundle source failures and cancellation
  • d2439db Merge commit 'ca1b2f8608' into feat/2352-dotnet-single-file
  • a53f791 Merge commit '59f528f0e5' into feat/2352-dotnet-single-file
  • 5653cda docs(artifacts): record synchronized bundle verification
  • fb46280 fix(artifacts): bind bundle extraction to inventoried host
  • 9f1391e docs(artifacts): record bundle verification outcome
  • d4ac1c7 fix(artifacts): bound bundle paths and suggest extraction

📊 Changes

27 files changed (+2213 additions, -41 deletions)

View changed files

➕ docs/dotnet-bundles.md (+110 -0)
📝 docs/managed-code-analysis.md (+6 -2)
➕ scripts/fixtures/dotnet-bundle/BundleFixture.csproj (+13 -0)
➕ scripts/fixtures/dotnet-bundle/NuGet.Config (+2 -0)
➕ scripts/fixtures/dotnet-bundle/Program.cs (+92 -0)
📝 src/artifacts/ArtifactEmbeddedFormatProbes.test.ts (+74 -1)
📝 src/artifacts/ArtifactEmbeddedFormatProbes.ts (+19 -0)
📝 src/artifacts/ArtifactPaths.ts (+30 -2)
📝 src/artifacts/ArtifactReader.ts (+18 -0)
➕ src/artifacts/ArtifactReaderAdmission.ts (+16 -0)
➕ src/artifacts/DotnetBundleArtifactReader.ts (+242 -0)
📝 src/artifacts/createArtifactReader.ts (+13 -10)
➕ src/artifacts/dotnet/DotnetBundle.fixture.ts (+107 -0)
➕ src/artifacts/dotnet/DotnetBundle.ts (+292 -0)
➕ src/artifacts/dotnet/DotnetBundleAdmission.ts (+8 -0)
📝 src/artifacts/extraction/ArtifactExtraction.ts (+2 -1)
📝 src/artifacts/inventory/ArtifactGraphConstruction.ts (+5 -1)
📝 src/artifacts/inventory/classify.ts (+12 -15)
📝 src/artifacts/inventory/reader.ts (+2 -9)
📝 src/domain/artifactFormatMetadata.ts (+9 -0)

...and 7 more files

📄 Description

Problem and outcome

Closes #2352. Ordinary .NET single-file apphosts previously appeared as native files without accessible bundled members. Existing inspect-artifact/extract-artifact and MCP equivalents now inventory and materialize PE, ELF and thin Mach-O bundles with v1.0, v2.0 or v6.0 headers, including v6 raw-DEFLATE members. No target execution, assembly loading, new provider or protection recovery is added.

The host retains its whole-file digest; members retain expanded-byte identities, original stored extents and declared version/type metadata. Declarations do not establish assembly validity. Existing summary delivery and filtered/paged inventory views work with the new format, retain provenance and preserve full Evidence. Unsupported versions/flags, malformed paths/ranges/compression and resource limits fail explicitly. Universal Mach-O contents remain unexpanded.

Implementation

A bounded manifest reader and streamed member decoder use the shared artifact factory, file-source ownership, resource scopes and safe output tree. Completed marker observations follow source identity through preflight, inventory and extraction: one scan instead of three. A recognized CArchive bounds the marker search, so an embedded apphost cannot replace the outer container. Closing joins late descriptor admission and retains failed cleanup for retry. Obsolete duplicate reader dispatch/type unions and the downstream native-format repair were removed; current main formats remain supported.

Fixed input failures name the effective ceiling and its units, declare that no runtime override exists, and explain why worker memory, summary delivery and paging do not raise it. The producing artifact error owner supplies the guidance and the explicit capacity boundary to both adapters.

Executed validation

  • 91 distinct focused tests across 9 files passed (three public journeys rerun after review edits): actual CLI and SDK stdio MCP, summary plus exact member/content views, parser/resource boundaries, single-scan extraction, late admission/close and generic inventory projections. Typecheck/lint, docs checks, formatting and discovery of all 2,839 test files passed.
  • Current-head upstream source suite: 21,893 passed / 16 skipped in 1,178 files. Build, static checks, documentation, Linux native package, Windows native controls, APK signatures, EVM, browser, web network, binary layout and four Node-version SQLite lanes passed. All eight built test shards also passed. Current-head CI is green; Greptile reports 5/5 and all five review threads are resolved. No bypass was used.
  • Microsoft SDK 8.0.427 / HostModel 8.0.33 produced 12 PE/ELF/thin-Mach-O hosts spanning v1/v2/plain-v6/compressed-v6. Independent C# BinaryReader/DeflateStream observations verified stored extents, types and source-member digests. Public CLI and MCP inspection/extraction matched all 48 members. A genuine SDK-published Linux application contributed another three matching members. Hosts stayed byte-identical; owned extraction output was verified and removed. Linux performs byte parsing of PE/Mach-O here; Windows/macOS execution and protected/arbitrary-bundle compatibility are unverified.
  • The original reader, ported only to borrow the current tagged source admission, fails the new cleanup and scan-count regressions: it reports closure while a descriptor is open and scans three times. The final reader passes both.

Measured costs

Paired fresh MCP processes performed initialization, named schema validation, tools discovery, open, full inspection, extraction/byte verification and close of the same compressed producer host. Two runs per reader with reversed order; warm filesystem caches, true cold-cache costs unmeasured. Tokenx estimates cover all JSON-RPC frames, including catalog, instructions, text and structured replies; these are not billed-token measurements.

Schema profile Original reader: elapsed / CPU / peak family RSS Final reader: elapsed / CPU / peak family RSS Whole-task estimated tokens, both
Full output (default) 3.02–3.10 s / 4.03–4.27 s / 492–496 MB 3.35–3.43 s / 4.45–4.49 s / 489–491 MB 232,407
Existing compact output 2.20–2.22 s / 3.05–3.07 s / 444–446 MB 2.11–2.18 s / 2.93–3.05 s / 439–440 MB 44,134

Both use compact input and artifact/session families. Compact output is an existing caller option, not a new default or a reader speedup. Catalog startup dominates this small-host workflow; stronger selected-path validation adds checks and no overall speedup is claimed. All eight tasks completed below the 1.5 GiB process-family guard, with no surviving children. Native files without a marker incur one additional streaming pass, and extraction additionally hashes the whole host to bind inventory identity. A separate public CLI capacity task with 1,000 distinct deep paths refused the path-tree budget in 1.94 s / 2.50 CPU s / 341 MB peak family RSS, returned a typed truncated/limit error (322 estimated command/reply tokens), and left no child processes. Metadata, member expansion and path-tree budgets are documented in docs/dotnet-bundles.md.

Author readiness

Human owner: @Zhong-fan

  • 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.
  • Current-head upstream CI has passed.

🔄 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/3787 **Author:** [@Zhong-fan](https://github.com/Zhong-fan) **Created:** 10/15/2026 **Status:** ✅ Merged **Merged:** 10/29/2026 **Merged by:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Base:** `main` ← **Head:** `feat/2352-dotnet-single-file` --- ### 📝 Commits (10+) - [`34ad3f6`](https://github.com/morluto/rea/commit/34ad3f627c4f8cb6b4f04e90567fe3a44d7416a4) feat(artifacts): inventory and extract .NET single-file bundles - [`dfdb7a8`](https://github.com/morluto/rea/commit/dfdb7a8c8eb1517292666b8018fd9de819ed9e96) fix(artifacts): retain bundle source I/O failure reasons - [`7bef0a2`](https://github.com/morluto/rea/commit/7bef0a27c15a957bd74fb1e0f6664e193b8adc09) docs(artifacts): record Linux bundle regression verification - [`00de2c9`](https://github.com/morluto/rea/commit/00de2c91af6813c845a23cbeec982635552d770e) fix(artifacts): preserve bundle source failures and cancellation - [`d2439db`](https://github.com/morluto/rea/commit/d2439dbaa8f5c7852ff17277eca93f5ec65e264a) Merge commit 'ca1b2f8608c52ed721d3576ba5eeb1d66717b08c' into feat/2352-dotnet-single-file - [`a53f791`](https://github.com/morluto/rea/commit/a53f791d3cf8397c48a5bb7db73fdf69319f2e06) Merge commit '59f528f0e5bfd780e314e929db9ebf1ad65c1303' into feat/2352-dotnet-single-file - [`5653cda`](https://github.com/morluto/rea/commit/5653cdac4fdbc9a02c46f095b521cff06c14af0e) docs(artifacts): record synchronized bundle verification - [`fb46280`](https://github.com/morluto/rea/commit/fb46280aaa3997cc67e078ad0efac8699fe8b31b) fix(artifacts): bind bundle extraction to inventoried host - [`9f1391e`](https://github.com/morluto/rea/commit/9f1391e5b94cb85426901594c550362ceb5cec8c) docs(artifacts): record bundle verification outcome - [`d4ac1c7`](https://github.com/morluto/rea/commit/d4ac1c750670e006333336b20e77cc97938c697b) fix(artifacts): bound bundle paths and suggest extraction ### 📊 Changes **27 files changed** (+2213 additions, -41 deletions) <details> <summary>View changed files</summary> ➕ `docs/dotnet-bundles.md` (+110 -0) 📝 `docs/managed-code-analysis.md` (+6 -2) ➕ `scripts/fixtures/dotnet-bundle/BundleFixture.csproj` (+13 -0) ➕ `scripts/fixtures/dotnet-bundle/NuGet.Config` (+2 -0) ➕ `scripts/fixtures/dotnet-bundle/Program.cs` (+92 -0) 📝 `src/artifacts/ArtifactEmbeddedFormatProbes.test.ts` (+74 -1) 📝 `src/artifacts/ArtifactEmbeddedFormatProbes.ts` (+19 -0) 📝 `src/artifacts/ArtifactPaths.ts` (+30 -2) 📝 `src/artifacts/ArtifactReader.ts` (+18 -0) ➕ `src/artifacts/ArtifactReaderAdmission.ts` (+16 -0) ➕ `src/artifacts/DotnetBundleArtifactReader.ts` (+242 -0) 📝 `src/artifacts/createArtifactReader.ts` (+13 -10) ➕ `src/artifacts/dotnet/DotnetBundle.fixture.ts` (+107 -0) ➕ `src/artifacts/dotnet/DotnetBundle.ts` (+292 -0) ➕ `src/artifacts/dotnet/DotnetBundleAdmission.ts` (+8 -0) 📝 `src/artifacts/extraction/ArtifactExtraction.ts` (+2 -1) 📝 `src/artifacts/inventory/ArtifactGraphConstruction.ts` (+5 -1) 📝 `src/artifacts/inventory/classify.ts` (+12 -15) 📝 `src/artifacts/inventory/reader.ts` (+2 -9) 📝 `src/domain/artifactFormatMetadata.ts` (+9 -0) _...and 7 more files_ </details> ### 📄 Description ## Problem and outcome Closes #2352. Ordinary .NET single-file apphosts previously appeared as native files without accessible bundled members. Existing `inspect-artifact`/`extract-artifact` and MCP equivalents now inventory and materialize PE, ELF and thin Mach-O bundles with v1.0, v2.0 or v6.0 headers, including v6 raw-DEFLATE members. No target execution, assembly loading, new provider or protection recovery is added. The host retains its whole-file digest; members retain expanded-byte identities, original stored extents and declared version/type metadata. Declarations do not establish assembly validity. Existing summary delivery and filtered/paged inventory views work with the new format, retain provenance and preserve full Evidence. Unsupported versions/flags, malformed paths/ranges/compression and resource limits fail explicitly. Universal Mach-O contents remain unexpanded. ## Implementation A bounded manifest reader and streamed member decoder use the shared artifact factory, file-source ownership, resource scopes and safe output tree. Completed marker observations follow source identity through preflight, inventory and extraction: one scan instead of three. A recognized CArchive bounds the marker search, so an embedded apphost cannot replace the outer container. Closing joins late descriptor admission and retains failed cleanup for retry. Obsolete duplicate reader dispatch/type unions and the downstream native-format repair were removed; current main formats remain supported. Fixed input failures name the effective ceiling and its units, declare that no runtime override exists, and explain why worker memory, summary delivery and paging do not raise it. The producing artifact error owner supplies the guidance and the explicit capacity boundary to both adapters. ## Executed validation - 91 distinct focused tests across 9 files passed (three public journeys rerun after review edits): actual CLI and SDK stdio MCP, summary plus exact member/content views, parser/resource boundaries, single-scan extraction, late admission/close and generic inventory projections. Typecheck/lint, docs checks, formatting and discovery of all 2,839 test files passed. - Current-head upstream source suite: 21,893 passed / 16 skipped in 1,178 files. Build, static checks, documentation, Linux native package, Windows native controls, APK signatures, EVM, browser, web network, binary layout and four Node-version SQLite lanes passed. All eight built test shards also passed. [Current-head CI](https://github.com/morluto/rea/actions/runs/40868327990) is green; Greptile reports 5/5 and all five review threads are resolved. No bypass was used. - Microsoft SDK 8.0.427 / HostModel 8.0.33 produced 12 PE/ELF/thin-Mach-O hosts spanning v1/v2/plain-v6/compressed-v6. Independent C# BinaryReader/DeflateStream observations verified stored extents, types and source-member digests. Public CLI and MCP inspection/extraction matched all 48 members. A genuine SDK-published Linux application contributed another three matching members. Hosts stayed byte-identical; owned extraction output was verified and removed. Linux performs byte parsing of PE/Mach-O here; Windows/macOS execution and protected/arbitrary-bundle compatibility are unverified. - The original reader, ported only to borrow the current tagged source admission, fails the new cleanup and scan-count regressions: it reports closure while a descriptor is open and scans three times. The final reader passes both. ## Measured costs Paired fresh MCP processes performed initialization, named schema validation, tools discovery, open, full inspection, extraction/byte verification and close of the same compressed producer host. Two runs per reader with reversed order; warm filesystem caches, true cold-cache costs unmeasured. Tokenx estimates cover all JSON-RPC frames, including catalog, instructions, text and structured replies; these are not billed-token measurements. | Schema profile | Original reader: elapsed / CPU / peak family RSS | Final reader: elapsed / CPU / peak family RSS | Whole-task estimated tokens, both | | --- | --- | --- | --- | | Full output (default) | 3.02–3.10 s / 4.03–4.27 s / 492–496 MB | 3.35–3.43 s / 4.45–4.49 s / 489–491 MB | 232,407 | | Existing compact output | 2.20–2.22 s / 3.05–3.07 s / 444–446 MB | 2.11–2.18 s / 2.93–3.05 s / 439–440 MB | 44,134 | Both use compact input and artifact/session families. Compact output is an existing caller option, not a new default or a reader speedup. Catalog startup dominates this small-host workflow; stronger selected-path validation adds checks and no overall speedup is claimed. All eight tasks completed below the 1.5 GiB process-family guard, with no surviving children. Native files without a marker incur one additional streaming pass, and extraction additionally hashes the whole host to bind inventory identity. A separate public CLI capacity task with 1,000 distinct deep paths refused the path-tree budget in 1.94 s / 2.50 CPU s / 341 MB peak family RSS, returned a typed `truncated/limit` error (322 estimated command/reply tokens), and left no child processes. Metadata, member expansion and path-tree budgets are documented in `docs/dotnet-bundles.md`. ## Author readiness Human owner: @Zhong-fan - [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. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. - [x] Current-head upstream CI has passed. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:10:16 +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#5899
No description provided.