fix(managed): explain single-type member capacity exhaustion (#9065)

* test(process): align symlink fixture with filesystem checkpoints

* fix(managed): explain single-type member capacity exhaustion

* test(frida): assert the CLI spawn Evidence contract

* test(mcp): use an unsupported analysis-view parent

* test(browser): separate source-location line bounds from parity

* fix(managed): count selected types in capacity guidance
This commit is contained in:
ShuaixinHuang authored and GitHub committed 2026-11-06 14:37:16 +08:00
1 parent a74ce4512c
commit 6993e4ac73
2 files changed
+48 -1

No files matched your search

+3 -1
View File
@@ -51,7 +51,9 @@ export const prepareManagedMemberRecovery = (
limitations: [
...inventory.limitations,
"Member decoding exceeded capacity after the type inventory was admitted; fields, methods, member references, call edges, field accesses, exported types and user strings are not examined to completion. Empty member collections do not establish absence.",
"Use the returned TypeDef full_name values with type_names (CLI --type) to inspect a smaller selection; a single selected type can still exceed capacity.",
inventory.selection !== null && inventory.types.length === 1
? "This single-type selection already reached the member-decoding capacity. Member references and exported types are assembly-wide and still count toward the shared budget."
: "Use the returned TypeDef full_name values with type_names (CLI --type) to inspect a smaller selection; a single selected type can still exceed capacity.",
"Metadata tokens are build-local coordinates and require the reported artifact SHA-256 and MVID. Type names and list ranges retain their original metadata and nesting uncertainty.",
],
};
@@ -1,8 +1,11 @@
import { ManagedDecodeBudget } from "./ManagedDecodeBudget.js";
import { prepareManagedMemberRecovery } from "./ManagedMemberRecovery.js";
import { expect, it } from "vitest";
import { inspectManagedMembersBytes } from "./ManagedMemberInspector.js";
import {
buildManagedPeFixture,
buildManagedNestedTypeFixture,
managedPeFixtureTarget,
} from "./ManagedPe.fixture.js";
import { buildManagedMemberCapacityFixture } from "../../tests/fixtures/managedMemberCapacity.js";
@@ -97,6 +100,25 @@ it("preserves explicit type selection when its selected body exhausts capacity",
});
});
it("explains capacity exhaustion after a single-type selection", () => {
const bytes = buildManagedMemberCapacityFixture();
const result = inspectManagedMembersBytes(
bytes,
managedPeFixtureTarget(bytes),
{
typeNames: ["Fixture.Program"],
},
);
expect(result.coverage.state).toBe("partial");
expect(result.coverage.issues).toContainEqual(
expect.objectContaining({ code: "resource-limit" }),
);
const guidance = result.limitations.join(" ");
expect(guidance).toMatch(/single.type selection/i);
expect(guidance).toMatch(/assembly.wide/i);
expect(guidance).not.toContain("inspect a smaller selection");
});
it("retains types when a field signature exceeds the decoding bound", () => {
const bytes = buildManagedPeFixture({
fieldSignature: Buffer.alloc(270_001, 0x06),
@@ -376,3 +398,26 @@ it("reads inventory names on demand without admitting TypeDef member lists or Ex
]),
);
});
it("keeps narrowing advice when one bare name selects multiple nested types", () => {
const bytes = buildManagedNestedTypeFixture();
const inventory = inspectManagedMembersBytes(
bytes,
managedPeFixtureTarget(bytes),
{
typeNames: ["Inner"],
},
);
expect(inventory.types).toHaveLength(2);
const recovery = prepareManagedMemberRecovery(
inventory,
[],
new ManagedDecodeBudget(),
)(0);
expect(recovery.limitations.join(" ")).toContain(
"inspect a smaller selection",
);
expect(recovery.limitations.join(" ")).not.toContain(
"This single-type selection",
);
});