fix(firmware): retain nested dependency diagnostics

This commit is contained in:
morluto committed 2026-10-27 10:35:50 +08:00
1 parent 92213a9155
commit b7be0d90a9
2 files changed
+80 -47

No files matched your search

+72 -39
View File
@@ -706,46 +706,79 @@ describe("firmware chunk dependency failures", () => {
});
describe("Unblob multi-file extraction diagnostics", () => {
it("names a missing extractor dependency and stage while retaining the raw report", () => {
const dependencyFailure = {
__typename__: "ExtractorDependencyNotFoundReport",
severity: "ERROR",
dependencies: ["sasquatch"],
};
const record = root();
const normalized = normalizeUnblobReport(
[
it.each([
{ dependencies: ["sasquatch"], names: ["sasquatch", "nested-tool"] },
{ dependencies: ["sasquatch", ""], names: ["sasquatch", "nested-tool"] },
{ dependencies: [], names: ["nested-tool"] },
])(
"retains nested dependency diagnostics beneath $dependencies",
({ dependencies, names }) => {
const dependencyFailure = {
__typename__: "ExtractorDependencyNotFoundReport",
severity: "ERROR",
dependencies,
nested_reports: [
{
__typename__: "ExtractorDependencyNotFoundReport",
dependencies: ["nested-tool", "nested-tool"],
},
],
};
const record = root();
const normalized = normalizeUnblobReport(
[
{
...record,
reports: [
...record.reports.filter(
(item) => item.__typename__ !== "UnknownChunkReport",
),
{
__typename__: "ChunkReport",
id: "gzip-id",
start_offset: 0,
end_offset: 20,
size: 20,
handler_name: "gzip",
is_encrypted: false,
extraction_reports: [dependencyFailure],
},
],
},
],
context,
);
expect(normalized.coverage).toBe("partial");
expect(normalized.diagnostics).toEqual([
{
...record,
reports: [
...record.reports.filter(
(item) => item.__typename__ !== "UnknownChunkReport",
),
{
__typename__: "ChunkReport",
id: "gzip-id",
start_offset: 0,
end_offset: 20,
size: 20,
handler_name: "gzip",
is_encrypted: false,
extraction_reports: [dependencyFailure],
},
],
input_path: "$input",
stage: "gzip",
missing_dependencies: names,
report: dependencyFailure,
},
],
context,
);
expect(normalized.coverage).toBe("partial");
expect(normalized.diagnostics).toEqual([
{
input_path: "$input",
stage: "gzip",
missing_dependencies: ["sasquatch"],
report: dependencyFailure,
},
]);
});
]);
expect(normalized.chunk_missing_dependencies).toEqual([
...(dependencies.includes("sasquatch")
? [
{
input_path: "$input",
provider_id: "gzip-id",
dependencies: ["sasquatch"],
},
]
: []),
...(dependencies.length === 0 || dependencies.includes("")
? [
{
input_path: "$input",
provider_id: "gzip-id",
dependencies: [],
},
]
: []),
]);
},
);
});
describe("Unblob task derivation identities", () => {
@@ -1257,7 +1290,7 @@ it.each(["task", "chunk", "multi-file"] as const)(
{
__typename__: "ExtractorDependencyNotFoundReport",
severity: "ERROR",
dependencies: ["z-tool", "a-tool", "z-tool"],
dependencies: ["z-tool", "", "a-tool", "z-tool"],
producer_detail: "named source declaration",
},
{
+8 -8
View File
@@ -144,11 +144,6 @@ const known = new Set([
"MultiFileReport",
]);
const dependencyFailure = z.object({
__typename__: z.literal("ExtractorDependencyNotFoundReport"),
dependencies: z.array(z.string().min(1)).min(1),
});
/** Collect the named extractors from any dependency report nested in one value. */
const diagnosticDependencyNames = (value: unknown): string[] => {
// Producer-controlled name volume must not make deduplication quadratic;
@@ -160,11 +155,16 @@ const diagnosticDependencyNames = (value: unknown): string[] => {
return;
}
if (typeof node !== "object" || node === null) return;
const failure = dependencyFailure.safeParse(node);
const failure = missingDependency.safeParse(node);
if (failure.success) {
for (const dependency of failure.data.dependencies) found.add(dependency);
return;
// Empty names carry unknown identity, not evidence against the known
// names in the same declaration. Ownership facts retain that unknown;
// diagnostics project only names and keep the complete source report.
for (const dependency of failure.data.dependencies)
if (dependency !== "") found.add(dependency);
}
// A declaration may also carry nested producer diagnostics. Its own
// admission does not determine whether those independent reports exist.
for (const child of Object.values(node)) visit(child);
};
visit(value);