"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildMemoryRootCause = buildMemoryRootCause;
/**
 * Memory / LMK / DMABUF Root-Cause Graph builder (Spark Plan 14)
 *
 * Combines five orthogonal memory facets (process snapshots, LMK kills,
 * DMA/DMABUF allocations, external artifacts, baseline diff) into one
 * `MemoryRootCauseContract`.
 */
const sparkContracts_1 = require("../types/sparkContracts");
/** Sort and slice the largest deltas from a per-category map. */
function topContributors(perCategory, topK = 5) {
    if (!perCategory)
        return undefined;
    return Object.entries(perCategory)
        .map(([key, deltaBytes]) => ({ key, deltaBytes }))
        .sort((a, b) => Math.abs(b.deltaBytes) - Math.abs(a.deltaBytes))
        .slice(0, topK);
}
/** "Has data" guard that rejects both undefined and [] (Codex regression). */
function hasRows(rows) {
    return Array.isArray(rows) && rows.length > 0;
}
function buildMemoryRootCause(input) {
    const hasProcess = hasRows(input.processSnapshots);
    const hasLmk = hasRows(input.lmkEvents);
    const hasDma = hasRows(input.dmaAllocations);
    const hasExternal = hasRows(input.externalArtifacts);
    const baselineDiff = input.baseline
        ? {
            baselineId: input.baseline.baselineId,
            deltaBytes: input.baseline.deltaBytes,
            ...(input.baseline.perCategoryBytes
                ? { topContributors: topContributors(input.baseline.perCategoryBytes) }
                : {}),
        }
        : undefined;
    const allEmpty = !hasProcess
        && !hasLmk
        && !hasDma
        && !hasExternal
        && !baselineDiff;
    return {
        ...(0, sparkContracts_1.makeSparkProvenance)({
            source: 'memory-root-cause',
            ...(allEmpty ? { unsupportedReason: 'no memory facets supplied' } : {}),
        }),
        range: input.range,
        ...(hasProcess ? { processSnapshots: input.processSnapshots } : {}),
        ...(hasLmk ? { lmkEvents: input.lmkEvents } : {}),
        ...(hasDma ? { dmaAllocations: input.dmaAllocations } : {}),
        ...(hasExternal ? { externalArtifacts: input.externalArtifacts } : {}),
        ...(baselineDiff ? { baselineDiff } : {}),
        coverage: [
            { sparkId: 11, planId: '14', status: hasProcess ? 'implemented' : 'scaffolded' },
            { sparkId: 12, planId: '14', status: hasLmk ? 'implemented' : 'scaffolded' },
            { sparkId: 13, planId: '14', status: hasDma ? 'implemented' : 'scaffolded' },
            { sparkId: 34, planId: '14', status: baselineDiff ? 'implemented' : 'scaffolded' },
            { sparkId: 51, planId: '14', status: hasExternal && input.externalArtifacts.some(a => a.kind === 'leak_canary') ? 'implemented' : 'scaffolded' },
            { sparkId: 70, planId: '14', status: hasExternal && input.externalArtifacts.some(a => a.kind === 'leak_canary') ? 'implemented' : 'scaffolded' },
            { sparkId: 109, planId: '14', status: hasExternal && input.externalArtifacts.some(a => a.kind === 'leak_canary') ? 'implemented' : 'scaffolded' },
            { sparkId: 112, planId: '14', status: hasExternal && input.externalArtifacts.some(a => a.kind === 'koom') ? 'implemented' : 'scaffolded' },
        ],
    };
}
//# sourceMappingURL=memoryRootCause.js.map