fix(json): consolidate dictionary admission across analysis and verification

This commit is contained in:
morluto committed 2026-10-26 18:14:50 +08:00
1 parent c06dc2d356
commit e7f986c994
18 files changed
+369 -99

No files matched your search

@@ -49,3 +49,50 @@ it("retains provider coverage caveats in a composed MCP overview without repeate
});
expect(calls.length).toBe(new Set(calls).size);
});
it("counts all own inventory dictionary entries in the composed overview", async () => {
const procedures = JSON.parse(
'{"__proto__":"observed procedure","0x1000":"ordinary procedure"}',
);
const strings = JSON.parse('{"__proto__":"observed string"}');
const before = [JSON.stringify(procedures), JSON.stringify(strings)];
const client = await connect({
execute: async (operation) => {
if (operation === "read_binary_inventory_summary")
return err(
new AnalysisCapabilityUnavailableError(
"fixture",
operation,
"No native overview",
),
);
const value =
operation === "current_document"
? "fixture"
: operation === "list_procedures"
? { procedures }
: operation === "list_strings"
? strings
: [];
return ok(
createAnalysisExecution(value, {
id: "fixture",
name: "Fixture",
version: "1",
}),
);
},
});
const response = await client.callTool({
name: "binary_overview",
arguments: {},
});
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.normalized_result).toMatchObject({
document: "fixture",
procedure_count: Object.keys(procedures).length,
string_count: Object.keys(strings).length,
});
expect([JSON.stringify(procedures), JSON.stringify(strings)]).toEqual(before);
});
+34
View File
@@ -150,6 +150,40 @@ const connect = async (analysis: AnalysisOperationPort) => {
};
describe("official tool input contracts", () => {
it("preserves every batch naming destination and rejects malformed own values before dispatch", async () => {
const invocations: Invocation[] = [];
const client = await connect({
execute: (name, arguments_) => {
invocations.push({ name, arguments_ });
return Promise.resolve(ok(null));
},
});
const names = JSON.parse('{"0x1000":"entry","__proto__":"other"}');
await client.callTool({
name: "set_addresses_names",
arguments: { names },
});
expect(invocations).toEqual([
{ name: "set_addresses_names", arguments_: { names } },
]);
expect(JSON.stringify(invocations[0]!.arguments_)).toContain(
'"__proto__":"other"',
);
for (const value of [42, null, {}]) {
const result = await client.callTool({
name: "set_addresses_names",
arguments: {
names: Object.fromEntries([
["0x1000", "entry"],
["__proto__", value],
]),
},
});
expect(result.isError).toBe(true);
}
expect(invocations).toHaveLength(1);
});
it("rejects misspelled top-level inputs before dispatch and keeps record keys open", async () => {
const invocations: Invocation[] = [];
const client = await connect({
@@ -114,3 +114,30 @@ it("parses explicit per-path expectations without borrowing the production phase
}).success,
).toBe(false);
});
it("retains prototype-named source paths in independent expectations", () => {
const input = Object.fromEntries([
["__proto__", expected],
["constructor", expected],
]);
const parsed = structuredScopeExpectationsSchema.parse(input);
expect(Object.keys(parsed)).toEqual(["__proto__", "constructor"]);
expect(Object.hasOwn(parsed, "__proto__")).toBe(true);
expect(parsed["__proto__"]).toEqual(expected);
});
it("validates prototype-named expectations and retains the nonempty path policy", () => {
for (const entry of [
null,
{ ...expected, operation: "wrong" },
{ ...expected, analysis_status: "wrong" },
])
expect(
structuredScopeExpectationsSchema.safeParse(
Object.fromEntries([["__proto__", entry]]),
).success,
).toBe(false);
expect(
structuredScopeExpectationsSchema.safeParse({ "": expected }).success,
).toBe(false);
});