[PR #2406] feat(wasm): decode WebAssembly components offline #5206

Open
opened 2026-10-31 01:04:48 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2406
Author: @all-black-493
Created: 10/12/2026
Status: 🔄 Open

Base: main ← Head: feat/wasm-component-inspection


📝 Commits (10+)

  • deb85e8 feat(wasm): decode WebAssembly components offline
  • 4a5f5b9 fix(wasm): bound component decoding and keep exact names
  • f645f46 fix(wasm): budget decoded entries and resolve aliased relationships
  • 70a0e8d docs(wasm): describe the decoded-entry budget
  • c103ec3 fix(wasm): retain component read cleanup ownership
  • 1fe0450 fix(wasm): budget traced output and keep known component sources
  • 3693dd0 chore: merge current main into PR #2406
  • ecccea1 fix(cli): remove duplicate WASM command import
  • b2523d7 Merge branch 'main' into feat/wasm-component-inspection
  • f10cbea Merge remote-tracking branch 'origin/main' into sweep/2406

📊 Changes

49 files changed (+5485 additions, -20 deletions)

View changed files

📝 .agents/skills/reverse-engineer-anything/SKILL.md (+5 -0)
📝 .agents/skills/reverse-engineer-anything/references/native-and-artifacts.md (+3 -1)
📝 docs/wasm-artifacts.md (+76 -5)
📝 scripts/lib/catalog-builders.mjs (+5 -0)
📝 scripts/lib/catalog-core.mjs (+2 -0)
📝 src/application/BinaryTargetResolver.ts (+13 -4)
📝 src/application/CapabilityInventory.ts (+2 -1)
➕ src/application/wasm/WasmComponentPort.ts (+21 -0)
➕ src/application/wasm/WasmComponentService.ts (+93 -0)
📝 src/cli/wasmCommands.ts (+30 -0)
📝 src/cliCommandNames.ts (+1 -0)
➕ src/composition/wasmComponent.ts (+6 -0)
📝 src/contracts/toolContracts.ts (+2 -0)
📝 src/contracts/toolEffects.test.ts (+2 -0)
📝 src/contracts/toolEffects.ts (+1 -0)
➕ src/contracts/wasm/wasmComponentToolContracts.ts (+28 -0)
📝 src/contracts/wasm/wasmToolContracts.ts (+1 -0)
📝 src/domain/analysisErrorPresentation.ts (+11 -0)
📝 src/domain/configurationErrors.ts (+1 -0)
➕ src/domain/wasm/wasmComponent.ts (+319 -0)

...and 29 more files

📄 Description

Summary

Adds inspect_wasm_component / rea inspect-wasm-component, an in-process decoder for WebAssembly component-model binaries. Refs #2350. The proposal and its open questions are in this comment.

Before this change, REA had no route for components. WABT 1.0.42 cannot parse them, and open_binary did not recognize their header.

Problem and expected behavior

A component (preamble 00 61 73 6D 0D 00 01 00) carries its own index spaces, typed imports and exports, embedded core modules and canonical ABI definitions. Treating it as a core module loses that structure.

Expected: given one local component file, REA returns its structure with byte ranges and provenance, and traces how component functions connect to core module exports and imports. It never validates, instantiates or executes anything.

Change and scope

  • Decoder. Written in src/wasm/ and pinned to component-model Binary.md at 06e3db0 (2026-09-23). It admits only version 0xd, layer 1. It reads the file through readStableArtifact and starts no subprocess, writes no temporary file, needs no WABT, and never instantiates or executes. Like the Go build-info reader (#1363), it has its own provider identity, wasm-component-binary v1.
  • Result.
    • The file SHA-256 and size, and section payload ranges.
    • Imports and exports with name attributes and extern types.
    • Type definitions. Component, instance and core module type declarations sit in a flat type_scopes list, so neither the JSON nor the advertised schema is recursive.
    • Embedded core modules by range, SHA-256, header version and import/export names.
    • Core and component instances, aliases, canonical definitions with options (including the async, error-context and thread built-ins), start and value sections, the component-name section, custom sections, and nested components linked by parent.
    • Every definition reports the index it defines in its sort.
  • Relationships. lifts trace each canonical lift through the core instance alias to the core export it wraps. lowers trace each lower to its component import and to the core imports it is bound to through inline-export core instances. declared_by_module checks the module's own import or export section, and is null when that interface was not decoded.
  • Coverage. validation is always not_performed. Malformed framing (LEB128, lengths, UTF-8, trailing bytes, truncation) fails with invalid_request and the file offset. A well-framed construct that isn't decoded (GC core types, unknown section ids or opcodes, nesting beyond 16 components or 32 type scopes) is listed in coverage.not_decoded with its range. Decoding continues with the next section, and indices that later definitions add to the affected sorts become null, because their positions are unknown. gated_features lists the feature gates of encodings actually present.
  • Routing.
    • open_binary returns the new constraint wasm_component_requires_static_inspection, with a remediation pointing to inspect_wasm_component.
    • inspect_wasm_artifact returns unsupported_target for a component before resolving WABT or running any command. An 8-byte probe routes early; the stable read still decides.
    • Both use a single preamble helper, src/domain/wasm/wasmPreamble.ts, which the core-module check now uses too.
  • Limits. 8 MiB input, 8 MiB inline output, at most 524,288 decoded entries (each charged before it is decoded), and at most 65,536 lower-to-core-import bindings. More bindings fail with the same resource-constraint error before the result is built. File-controlled counts such as start results cost constant memory, relationship tracing is linear, and cancellation is checked between sections. Names keep a leading U+FEFF, and a type that fails partway leaves no scope behind.

Not included: validation, the canonical ABI layout, value decoding, tracing through outer aliases or instantiated nested components, and summary delivery (asked about in #2350). The issue asks for spec/plan/tasks under docs/specs/. That directory doesn't exist, and AGENTS.md says not to commit local planning artifacts, so the design is in the issue comment and here, and the user docs are in docs/wasm-artifacts.md.

Follow the contribution scope. This is read-only static format inspection with no execution or mutation authority. #2350 asks whether a new in-process provider needs a separate maintainer decision; that is still pending.

Contract and boundary impact

  • Semantic owner and earliest changed stage: src/domain/wasm/wasmComponent.ts and wasmComponentTypes.ts (contract), src/wasm/WasmComponent*.ts (decoder), src/domain/wasm/wasmPreamble.ts (header identity).
  • Contribution scope fit and linked maintainer decision: format inspection; the provider question is pending in #2350.
  • CLI and MCP/tool-catalog contract: one new tool and CLI command; one new BinaryTargetError constraint. inspect_wasm_artifact and open_binary change only for component headers.
  • Provider, bridge, target-format, or platform compatibility: new in-process provider wasm-component-binary v1. No host tools are required.
  • Evidence, artifact, provenance, or reconstruction contract: Evidence subject format file; locations include the artifact path and any undecoded ranges.
  • Target selection, authority, upstream behavior, and cleanup details: one explicitly selected file. Following the read-ownership change on main (b955b825f), the stable read and the WABT component probe release their file handles through a provider-owned ArtifactResourceScope. A failed release returns cleanup_incomplete with the primary error, and the handle is retried on the next read or at CLI/MCP shutdown, where the server closes the same WasmComponentService it binds to the tool.
  • Generated metadata, package, or installation impact: the product catalog adds the tool under the artifact surface with its own provider identity. The skill gets one entry and a reference line, with no version bump, following recent feature PRs.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated:

    • src/wasm/WasmComponentDecoder.test.ts: index spaces across interleaved sections, lift/lower tracing, instance types with resources, names, gated encodings, nesting and its bound, partial coverage with null indices, an invalid name section, a non-core embedded module, malformed framing, unadmitted preambles and cancellation.
    • tests/acceptance/wasmComponentCli.test.ts and tests/boundary/mcp/wasmComponentMcp.test.ts: public CLI and MCP calls. They validate the advertised input and output JSON Schemas with Ajv 2020 after SDK conversion, and cover availability without an active target, session Evidence, typed errors and partial coverage.
    • Resource and fidelity regressions from review: a start section with 4,294,967,295 results, 20,000 lifts with 20,000 exports, 90,000 multiplicative lower bindings (typed failure), a name with a leading U+FEFF, and a type that fails after opening its scope.
    • tests/boundary/filesystem/targetDiagnostics.test.ts (open_binary routing) and src/wasm/WabtArtifactProvider.test.ts (WABT pre-check: no command runs and no workspace is created, with and without WABT configured).
    • Fixtures are original, encoded in memory by src/wasm/WasmComponentBinary.fixture.ts; no binary is committed.
  • Base reproduction: on main, open_binary does not recognize a component header, and inspect_wasm_artifact passes component bytes to WABT, which cannot decode them.

  • Real-producer cross-check (manual, not a CI lane): @bytecodealliance/jco 1.35.0, which bundles wasm-tools, run in an isolated directory.

    • jco print parses all three fixtures, with the same index numbering the decoder reports.
    • A component encoded by jco parse from WAT (records, variants, enums, flags, options, results, tuples, resource.new/drop/rep, a component-typed import, instantiation, inline-export instances, a module type and an outer alias) decodes to the same indices as jco print shows.
    • A real WASI 0.2 command component made by jco new --wasi-command (17,552 bytes) decodes completely. It has 8 imports, 4 core modules, 15 core instances, 13 lowers, 1 lift and 4 resource.drop, matching jco print. All 13 lowers trace to their WASI imports and adapter-module imports with declared_by_module: true. The lift traces to wasi:cli/run@0.2.12#run.
  • User-visible CLI/MCP output, from the WASI command component above (trimmed; ranges omitted, one entry per list shown):

    {
      "operation": "inspect_wasm_component",
      "normalized_result": {
        "validation": "not_performed",
        "coverage": { "status": "complete", "not_decoded": [] },
        "components": [{
          "imports": [
            { "name": "wasi:io/error@0.2.12", "attributes": [], "type": { "sort": "instance", "type": 0 }, "defines": { "sort": "instance", "index": 0 } },
            "… 7 more: wasi:io/streams, wasi:cli/stdin|stdout|stderr, wasi:clocks/wall-clock, wasi:filesystem/types|preopens"
          ],
          "exports": [
            { "name": "wasi:cli/run@0.2.12", "attributes": [], "target": { "sort": "instance", "index": 8 }, "type": null, "defines": { "sort": "instance", "index": 9 } }
          ],
          "lowers": [{
            "canon": 4, "func": 0, "core_func": 16,
            "component_source": { "kind": "instance-export", "instance": 4, "name": "get-stderr", "instance_import": "wasi:cli/stderr@0.2.12" },
            "satisfies": [{ "core_instance": 12, "core_module": 1, "import_module": "wasi:cli/stderr@0.2.12", "import_name": "get-stderr", "declared_by_module": true }]
          }],
          "lifts": [{
            "canon": 17, "func": 13, "core_func": 31, "type": 21,
            "core_source": { "core_instance": 12, "name": "wasi:cli/run@0.2.12#run", "core_module": 1, "declared_by_module": true },
            "exported_as": []
          }]
        }]
      }
    }
    
  • Remaining proof gaps:

    • The real-producer checks were run once by hand and are not an automated lane.
    • No component from a full language toolchain (Rust cargo component, componentize-py) was decoded.
    • Async, thread and map encodings are covered only by original fixtures and jco print parsing, not by producer output.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run check:
    • Typecheck, lint (0 errors), knip, metadata:check and architecture guards pass.
    • format:check flagged only untracked local build output outside this diff; oxfmt --check on the changed files passes.
    • The new modules add no lint warnings. In touched existing files, the new registration function's five parameters match registerGoTools.
  • npm run docs:check: passes.
  • New and affected source tests: 50 pass (decoder, WABT provider, effects, capability inventory, advertised examples). After both rounds of review fixes (head e1e9960db), the decoder and WABT provider suites pass (32 tests), as do the component CLI/MCP, WASM artifact MCP and target diagnostics suites (31 tests) and check:fast. Both real-producer components decode with identical output.
  • New and affected boundary/acceptance tests: 75 pass across 10 files (component CLI/MCP, WASM artifact MCP, target diagnostics, product catalog, CLI tool coverage, tool schema validity, local tool contracts, compact input schemas, setup skill).
  • After rebasing onto main at 11f8b7625 (head c103ec369):
    • check:fast, docs:check, knip and jscpd pass (2.99% duplicated lines, threshold 3.5%).
    • Source tests: 55 pass across the WASM suites and tool effects.
    • Boundary/acceptance: 42 pass across component CLI/MCP, WASM artifact MCP, target diagnostics, serverLifecycleMcp and artifactReadCleanupRetry. The last two are upstream's ownership tests, extended to the component provider and service. With the scope removed from the provider, the retry case fails with cancelled instead of cleanup_incomplete.
  • A wider run of 54 affected files before the rebase: 1 failure, tests/boundary/mcp/firmwareMcp.test.ts ("Unsupported tool version 26.6.4"). It fails the same way on the unmodified base on this host.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Core-module behavior is unchanged.
  • Real Hopper/Ghidra, browser, or OS coverage: Linux x64, Node 24.14.0. The decoder uses no host tools.
  • Package or release metadata impact: the product catalog gains one tool; no package or skill version changes.
  • Agent and analysis cost:
    • tools/list grows by 33,919 bytes (about 1.35% of 2,516,115). Of that, 32,440 bytes is the typed output schema, 3rd largest of 188 tools (median 8,445), in the range of inspect_web_page and analyze_javascript_application. Tokens were not measured; at about 4 bytes per token that is roughly 8.5k tokens, an estimate.
    • The WASI command component returns 52,179 bytes of CLI JSON.
    • Decoding takes about 10–13 ms. The CLI run takes 1.6–1.8 s elapsed, about 2.4 s CPU and about 317 MB peak RSS, which matches the CLI's own startup cost on a missing file (1.6–1.8 s, about 2.4 s, about 315 MB).
    • Summary delivery or schema compaction could follow if wanted.
  • Security, privacy, process, or containment review:
    • Read-only parsing of one selected file, with bounded input and output, LEB128 width checks, vector counts limited by the remaining bytes, and bounded nesting. Nothing is executed or fetched.
    • Component names and strings are treated as target content, which is the default.

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.

Refs #2350


🔄 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/2406 **Author:** [@all-black-493](https://github.com/all-black-493) **Created:** 10/12/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/wasm-component-inspection` --- ### 📝 Commits (10+) - [`deb85e8`](https://github.com/morluto/rea/commit/deb85e8004b87d8717040ea87dfb29f0c592741b) feat(wasm): decode WebAssembly components offline - [`4a5f5b9`](https://github.com/morluto/rea/commit/4a5f5b98e38bcc03c3f2372558777186c226db40) fix(wasm): bound component decoding and keep exact names - [`f645f46`](https://github.com/morluto/rea/commit/f645f46df78a86eaefee95d5e7f85a5e1c1f2e5c) fix(wasm): budget decoded entries and resolve aliased relationships - [`70a0e8d`](https://github.com/morluto/rea/commit/70a0e8d524a69427b2594b98d2d94d79523f7b16) docs(wasm): describe the decoded-entry budget - [`c103ec3`](https://github.com/morluto/rea/commit/c103ec369980c4f9fed04fc6df3d0cb3b892e960) fix(wasm): retain component read cleanup ownership - [`1fe0450`](https://github.com/morluto/rea/commit/1fe0450db1e28fc324e5205ad384821e4e2300aa) fix(wasm): budget traced output and keep known component sources - [`3693dd0`](https://github.com/morluto/rea/commit/3693dd009688ddee3084115d3428c29fc341776e) chore: merge current main into PR #2406 - [`ecccea1`](https://github.com/morluto/rea/commit/ecccea1fd05d73d71e45444c1045b7a8b5b29c31) fix(cli): remove duplicate WASM command import - [`b2523d7`](https://github.com/morluto/rea/commit/b2523d7336391e5203ffa82402970ddaa6db8c58) Merge branch 'main' into feat/wasm-component-inspection - [`f10cbea`](https://github.com/morluto/rea/commit/f10cbea54f8879f4a90566ea884e32da8faae7bd) Merge remote-tracking branch 'origin/main' into sweep/2406 ### 📊 Changes **49 files changed** (+5485 additions, -20 deletions) <details> <summary>View changed files</summary> 📝 `.agents/skills/reverse-engineer-anything/SKILL.md` (+5 -0) 📝 `.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md` (+3 -1) 📝 `docs/wasm-artifacts.md` (+76 -5) 📝 `scripts/lib/catalog-builders.mjs` (+5 -0) 📝 `scripts/lib/catalog-core.mjs` (+2 -0) 📝 `src/application/BinaryTargetResolver.ts` (+13 -4) 📝 `src/application/CapabilityInventory.ts` (+2 -1) ➕ `src/application/wasm/WasmComponentPort.ts` (+21 -0) ➕ `src/application/wasm/WasmComponentService.ts` (+93 -0) 📝 `src/cli/wasmCommands.ts` (+30 -0) 📝 `src/cliCommandNames.ts` (+1 -0) ➕ `src/composition/wasmComponent.ts` (+6 -0) 📝 `src/contracts/toolContracts.ts` (+2 -0) 📝 `src/contracts/toolEffects.test.ts` (+2 -0) 📝 `src/contracts/toolEffects.ts` (+1 -0) ➕ `src/contracts/wasm/wasmComponentToolContracts.ts` (+28 -0) 📝 `src/contracts/wasm/wasmToolContracts.ts` (+1 -0) 📝 `src/domain/analysisErrorPresentation.ts` (+11 -0) 📝 `src/domain/configurationErrors.ts` (+1 -0) ➕ `src/domain/wasm/wasmComponent.ts` (+319 -0) _...and 29 more files_ </details> ### 📄 Description ## Summary Adds `inspect_wasm_component` / `rea inspect-wasm-component`, an in-process decoder for WebAssembly component-model binaries. Refs #2350. The proposal and its open questions are in [this comment](https://github.com/morluto/rea/issues/2350#issuecomment-6132735562). Before this change, REA had no route for components. WABT 1.0.42 cannot parse them, and `open_binary` did not recognize their header. ## Problem and expected behavior A component (preamble `00 61 73 6D 0D 00 01 00`) carries its own index spaces, typed imports and exports, embedded core modules and canonical ABI definitions. Treating it as a core module loses that structure. Expected: given one local component file, REA returns its structure with byte ranges and provenance, and traces how component functions connect to core module exports and imports. It never validates, instantiates or executes anything. ## Change and scope - **Decoder.** Written in `src/wasm/` and pinned to component-model [`Binary.md` at `06e3db0`](https://github.com/WebAssembly/component-model/blob/06e3db039e38588e2643a9417bf5d03100feafde/design/mvp/Binary.md) (2026-09-23). It admits only version `0xd`, layer `1`. It reads the file through `readStableArtifact` and starts no subprocess, writes no temporary file, needs no WABT, and never instantiates or executes. Like the Go build-info reader (#1363), it has its own provider identity, `wasm-component-binary` v1. - **Result.** - The file SHA-256 and size, and section payload ranges. - Imports and exports with name attributes and extern types. - Type definitions. Component, instance and core module type declarations sit in a flat `type_scopes` list, so neither the JSON nor the advertised schema is recursive. - Embedded core modules by range, SHA-256, header version and import/export names. - Core and component instances, aliases, canonical definitions with options (including the async, error-context and thread built-ins), start and value sections, the `component-name` section, custom sections, and nested components linked by `parent`. - Every definition reports the index it defines in its sort. - **Relationships.** `lifts` trace each canonical lift through the core instance alias to the core export it wraps. `lowers` trace each lower to its component import and to the core imports it is bound to through inline-export core instances. `declared_by_module` checks the module's own import or export section, and is null when that interface was not decoded. - **Coverage.** `validation` is always `not_performed`. Malformed framing (LEB128, lengths, UTF-8, trailing bytes, truncation) fails with `invalid_request` and the file offset. A well-framed construct that isn't decoded (GC core types, unknown section ids or opcodes, nesting beyond 16 components or 32 type scopes) is listed in `coverage.not_decoded` with its range. Decoding continues with the next section, and indices that later definitions add to the affected sorts become null, because their positions are unknown. `gated_features` lists the feature gates of encodings actually present. - **Routing.** - `open_binary` returns the new constraint `wasm_component_requires_static_inspection`, with a remediation pointing to `inspect_wasm_component`. - `inspect_wasm_artifact` returns `unsupported_target` for a component before resolving WABT or running any command. An 8-byte probe routes early; the stable read still decides. - Both use a single preamble helper, `src/domain/wasm/wasmPreamble.ts`, which the core-module check now uses too. - **Limits.** 8 MiB input, 8 MiB inline output, at most 524,288 decoded entries (each charged before it is decoded), and at most 65,536 lower-to-core-import bindings. More bindings fail with the same resource-constraint error before the result is built. File-controlled counts such as start results cost constant memory, relationship tracing is linear, and cancellation is checked between sections. Names keep a leading U+FEFF, and a type that fails partway leaves no scope behind. Not included: validation, the canonical ABI layout, value decoding, tracing through outer aliases or instantiated nested components, and summary delivery (asked about in #2350). The issue asks for spec/plan/tasks under `docs/specs/`. That directory doesn't exist, and AGENTS.md says not to commit local planning artifacts, so the design is in the issue comment and here, and the user docs are in `docs/wasm-artifacts.md`. Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). This is read-only static format inspection with no execution or mutation authority. #2350 asks whether a new in-process provider needs a separate maintainer decision; that is still pending. ## Contract and boundary impact - Semantic owner and earliest changed stage: `src/domain/wasm/wasmComponent.ts` and `wasmComponentTypes.ts` (contract), `src/wasm/WasmComponent*.ts` (decoder), `src/domain/wasm/wasmPreamble.ts` (header identity). - Contribution scope fit and linked maintainer decision: format inspection; the provider question is pending in #2350. - CLI and MCP/tool-catalog contract: one new tool and CLI command; one new `BinaryTargetError` constraint. `inspect_wasm_artifact` and `open_binary` change only for component headers. - Provider, bridge, target-format, or platform compatibility: new in-process provider `wasm-component-binary` v1. No host tools are required. - Evidence, artifact, provenance, or reconstruction contract: Evidence subject format `file`; locations include the artifact path and any undecoded ranges. - Target selection, authority, upstream behavior, and cleanup details: one explicitly selected file. Following the read-ownership change on `main` (b955b825f), the stable read and the WABT component probe release their file handles through a provider-owned `ArtifactResourceScope`. A failed release returns `cleanup_incomplete` with the primary error, and the handle is retried on the next read or at CLI/MCP shutdown, where the server closes the same `WasmComponentService` it binds to the tool. - Generated metadata, package, or installation impact: the product catalog adds the tool under the `artifact` surface with its own provider identity. The skill gets one entry and a reference line, with no version bump, following recent feature PRs. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: - `src/wasm/WasmComponentDecoder.test.ts`: index spaces across interleaved sections, lift/lower tracing, instance types with resources, names, gated encodings, nesting and its bound, partial coverage with null indices, an invalid name section, a non-core embedded module, malformed framing, unadmitted preambles and cancellation. - `tests/acceptance/wasmComponentCli.test.ts` and `tests/boundary/mcp/wasmComponentMcp.test.ts`: public CLI and MCP calls. They validate the advertised input and output JSON Schemas with Ajv 2020 after SDK conversion, and cover availability without an active target, session Evidence, typed errors and partial coverage. - Resource and fidelity regressions from review: a start section with 4,294,967,295 results, 20,000 lifts with 20,000 exports, 90,000 multiplicative lower bindings (typed failure), a name with a leading U+FEFF, and a type that fails after opening its scope. - `tests/boundary/filesystem/targetDiagnostics.test.ts` (`open_binary` routing) and `src/wasm/WabtArtifactProvider.test.ts` (WABT pre-check: no command runs and no workspace is created, with and without WABT configured). - Fixtures are original, encoded in memory by `src/wasm/WasmComponentBinary.fixture.ts`; no binary is committed. - Base reproduction: on `main`, `open_binary` does not recognize a component header, and `inspect_wasm_artifact` passes component bytes to WABT, which cannot decode them. - Real-producer cross-check (manual, not a CI lane): `@bytecodealliance/jco` 1.35.0, which bundles `wasm-tools`, run in an isolated directory. - `jco print` parses all three fixtures, with the same index numbering the decoder reports. - A component encoded by `jco parse` from WAT (records, variants, enums, flags, options, results, tuples, `resource.new`/`drop`/`rep`, a component-typed import, instantiation, inline-export instances, a module type and an outer alias) decodes to the same indices as `jco print` shows. - A real WASI 0.2 command component made by `jco new --wasi-command` (17,552 bytes) decodes completely. It has 8 imports, 4 core modules, 15 core instances, 13 lowers, 1 lift and 4 `resource.drop`, matching `jco print`. All 13 lowers trace to their WASI imports and adapter-module imports with `declared_by_module: true`. The lift traces to `wasi:cli/run@0.2.12#run`. - User-visible CLI/MCP output, from the WASI command component above (trimmed; ranges omitted, one entry per list shown): ```json { "operation": "inspect_wasm_component", "normalized_result": { "validation": "not_performed", "coverage": { "status": "complete", "not_decoded": [] }, "components": [{ "imports": [ { "name": "wasi:io/error@0.2.12", "attributes": [], "type": { "sort": "instance", "type": 0 }, "defines": { "sort": "instance", "index": 0 } }, "… 7 more: wasi:io/streams, wasi:cli/stdin|stdout|stderr, wasi:clocks/wall-clock, wasi:filesystem/types|preopens" ], "exports": [ { "name": "wasi:cli/run@0.2.12", "attributes": [], "target": { "sort": "instance", "index": 8 }, "type": null, "defines": { "sort": "instance", "index": 9 } } ], "lowers": [{ "canon": 4, "func": 0, "core_func": 16, "component_source": { "kind": "instance-export", "instance": 4, "name": "get-stderr", "instance_import": "wasi:cli/stderr@0.2.12" }, "satisfies": [{ "core_instance": 12, "core_module": 1, "import_module": "wasi:cli/stderr@0.2.12", "import_name": "get-stderr", "declared_by_module": true }] }], "lifts": [{ "canon": 17, "func": 13, "core_func": 31, "type": 21, "core_source": { "core_instance": 12, "name": "wasi:cli/run@0.2.12#run", "core_module": 1, "declared_by_module": true }, "exported_as": [] }] }] } } ``` - Remaining proof gaps: - The real-producer checks were run once by hand and are not an automated lane. - No component from a full language toolchain (Rust `cargo component`, `componentize-py`) was decoded. - Async, thread and map encodings are covered only by original fixtures and `jco print` parsing, not by producer output. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run check`: - Typecheck, lint (0 errors), `knip`, `metadata:check` and architecture guards pass. - `format:check` flagged only untracked local build output outside this diff; `oxfmt --check` on the changed files passes. - The new modules add no lint warnings. In touched existing files, the new registration function's five parameters match `registerGoTools`. - `npm run docs:check`: passes. - New and affected source tests: 50 pass (decoder, WABT provider, effects, capability inventory, advertised examples). After both rounds of review fixes (head `e1e9960db`), the decoder and WABT provider suites pass (32 tests), as do the component CLI/MCP, WASM artifact MCP and target diagnostics suites (31 tests) and `check:fast`. Both real-producer components decode with identical output. - New and affected boundary/acceptance tests: 75 pass across 10 files (component CLI/MCP, WASM artifact MCP, target diagnostics, product catalog, CLI tool coverage, tool schema validity, local tool contracts, compact input schemas, setup skill). - After rebasing onto `main` at `11f8b7625` (head `c103ec369`): - `check:fast`, `docs:check`, `knip` and `jscpd` pass (2.99% duplicated lines, threshold 3.5%). - Source tests: 55 pass across the WASM suites and tool effects. - Boundary/acceptance: 42 pass across component CLI/MCP, WASM artifact MCP, target diagnostics, `serverLifecycleMcp` and `artifactReadCleanupRetry`. The last two are upstream's ownership tests, extended to the component provider and service. With the scope removed from the provider, the retry case fails with `cancelled` instead of `cleanup_incomplete`. - A wider run of 54 affected files before the rebase: 1 failure, `tests/boundary/mcp/firmwareMcp.test.ts` ("Unsupported tool version 26.6.4"). It fails the same way on the unmodified base on this host. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Core-module behavior is unchanged. - Real Hopper/Ghidra, browser, or OS coverage: Linux x64, Node 24.14.0. The decoder uses no host tools. - Package or release metadata impact: the product catalog gains one tool; no package or skill version changes. - Agent and analysis cost: - `tools/list` grows by 33,919 bytes (about 1.35% of 2,516,115). Of that, 32,440 bytes is the typed output schema, 3rd largest of 188 tools (median 8,445), in the range of `inspect_web_page` and `analyze_javascript_application`. Tokens were not measured; at about 4 bytes per token that is roughly 8.5k tokens, an estimate. - The WASI command component returns 52,179 bytes of CLI JSON. - Decoding takes about 10–13 ms. The CLI run takes 1.6–1.8 s elapsed, about 2.4 s CPU and about 317 MB peak RSS, which matches the CLI's own startup cost on a missing file (1.6–1.8 s, about 2.4 s, about 315 MB). - Summary delivery or schema compaction could follow if wanted. - Security, privacy, process, or containment review: - Read-only parsing of one selected file, with bounded input and output, LEB128 width checks, vector counts limited by the remaining bytes, and bounded nesting. Nothing is executed or fetched. - Component names and strings are treated as target content, which is the default. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [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. Refs #2350 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#5206
No description provided.