"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.DEFAULT_DOMAIN_MANIFEST = void 0;
exports.getSceneReconstructionRoutes = getSceneReconstructionRoutes;
exports.getSceneDeepDiveRoutes = getSceneDeepDiveRoutes;
exports.getSceneDeepDiveRoute = getSceneDeepDiveRoute;
exports.matchesSceneReconstructionRoute = matchesSceneReconstructionRoute;
exports.resolveSceneReconstructionRoute = resolveSceneReconstructionRoute;
exports.getStrategyExecutionPolicy = getStrategyExecutionPolicy;
exports.shouldPreferHypothesisLoop = shouldPreferHypothesisLoop;
exports.getAspectEvidenceChecklist = getAspectEvidenceChecklist;
exports.getModeSpecificEvidenceChecklist = getModeSpecificEvidenceChecklist;
exports.DEFAULT_DOMAIN_MANIFEST = {
    strategyExecutionPolicies: {
        // Deterministic deep-dive paths with stable contracts should keep strategy mode.
        scrolling: 'prefer_strategy',
        startup: 'prefer_strategy',
        scene_reconstruction: 'prefer_strategy',
        scene_reconstruction_quick: 'prefer_strategy',
    },
    aspectEvidenceMap: {
        scrolling: ['滑动会话与区间级 FPS/掉帧率'],
        jank: ['卡顿帧列表、jank 类型分布与严重度'],
        frame: ['App/SF 帧时序、帧预算与超时类型'],
        cpu: ['主线程与关键线程 CPU 调度、频率与等待'],
        memory: ['内存分配热点、GC 暂停与内存压力'],
        binder: ['Binder 调用耗时、阻塞链与锁竞争'],
        startup: ['启动阶段拆解与关键阶段耗时'],
        interaction: ['输入到渲染链路延迟与交互响应'],
        anr: ['阻塞线程、等待对象与 ANR 证据链'],
        system: ['系统负载、热限频、I/O 抖动与后台干扰'],
        gpu: ['GPU 渲染耗时、Fence 等待与合成延迟'],
        render: ['RenderThread/绘制阶段耗时与瓶颈'],
        timeline: ['关键事件时间线与关联区间'],
    },
    modeEvidenceMap: {
        compare: ['对比对象统一口径指标（同窗口/同刷新率）'],
        clarify: ['已确认发现与证据链摘要'],
        drill_down: ['目标实体区间内的逐层证据（frame/cpu/binder/memory）'],
        extend: ['未覆盖实体的同类证据补齐与模式一致性'],
    },
    sceneReconstructionRoutes: [
        {
            id: 'startup_scene',
            routeProfile: 'legacy',
            sceneTypeGroups: ['startup'],
            agentId: 'startup_agent',
            domain: 'startup',
            directSkillId: 'startup_detail',
            descriptionTemplate: '分析启动场景: {{scopeLabel}}',
            paramMapping: {
                startup_id: 'startupId',
                start_ts: 'startTs',
                end_ts: 'endTs',
                dur_ms: 'durationMs',
                package: 'processName',
                startup_type: 'startupType',
                ttid_ms: 'ttidMs',
                ttfd_ms: 'ttfdMs',
            },
        },
        {
            id: 'non_startup_scene',
            routeProfile: 'legacy',
            // Whitelist gesture-like scene types only. Earlier this rule used
            // sceneTypeGroups: ['all'] with excludeSceneTypes for the three startup
            // types, which would also catch idle / screen_on/off/sleep / app_switch
            // / scroll_start and route them through scrolling_analysis — none of
            // those scenes have a meaningful Stage 2 analysis path.
            sceneTypeGroups: ['scroll', 'interaction'],
            agentId: 'frame_agent',
            domain: 'scroll',
            directSkillId: 'scrolling_analysis',
            descriptionTemplate: '分析帧性能: {{scopeLabel}}',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
            },
            skillParams: {
                enable_frame_details: false,
            },
        },
        {
            id: 'smart_startup_scene',
            routeProfile: 'smart',
            sceneTypeGroups: ['startup'],
            agentId: 'startup_agent',
            domain: 'startup',
            directSkillId: 'startup_detail',
            descriptionTemplate: '智能分析启动场景: {{scopeLabel}}',
            paramMapping: {
                startup_id: 'startupId',
                start_ts: 'startTs',
                end_ts: 'endTs',
                dur_ms: 'durationMs',
                package: 'processName',
                startup_type: 'startupType',
                ttid_ms: 'ttidMs',
                ttfd_ms: 'ttfdMs',
            },
        },
        {
            id: 'smart_scroll_scene',
            routeProfile: 'smart',
            // `scroll_start` is a zero-duration marker, useful in the reconstructed
            // timeline but not a valid frame-analysis interval.
            sceneTypes: ['scroll', 'inertial_scroll'],
            agentId: 'frame_agent',
            domain: 'scroll',
            directSkillId: 'scrolling_analysis',
            descriptionTemplate: '智能分析滑动场景: {{scopeLabel}}',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
            },
            skillParams: {
                enable_frame_details: false,
            },
        },
        {
            id: 'smart_click_scene',
            routeProfile: 'smart',
            sceneTypes: ['tap', 'long_press', 'screen_unlock'],
            agentId: 'interaction_agent',
            domain: 'interaction',
            directSkillId: 'click_response_analysis',
            descriptionTemplate: '智能分析点击响应场景: {{scopeLabel}}',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
            },
            skillParams: {
                enable_per_event_detail: false,
            },
        },
        {
            id: 'smart_navigation_scene',
            routeProfile: 'smart',
            sceneTypes: ['navigation', 'back_key', 'home_key', 'recents_key', 'window_transition'],
            agentId: 'interaction_agent',
            domain: 'navigation',
            directSkillId: 'navigation_analysis',
            descriptionTemplate: '智能分析导航/返回场景: {{scopeLabel}}',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
            },
        },
        {
            id: 'smart_anr_scene',
            routeProfile: 'smart',
            sceneTypes: ['anr', 'jank_region'],
            agentId: 'anr_agent',
            domain: 'anr',
            directSkillId: 'anr_analysis',
            descriptionTemplate: '智能分析 ANR/严重卡顿场景: {{scopeLabel}}',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                process_name: 'processName',
                package: 'processName',
            },
        },
        {
            id: 'smart_device_state_scene',
            routeProfile: 'smart',
            sceneTypeGroups: ['device_state'],
            agentId: 'system_agent',
            domain: 'system',
            directSkillId: 'device_state_snapshot',
            descriptionTemplate: '智能分析设备状态场景: {{scopeLabel}}',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
            },
        },
    ],
    sceneDeepDiveRoutes: [
        {
            id: 'startup_deep_dive',
            eventTypes: ['cold_start', 'warm_start', 'hot_start'],
            skillId: 'startup_analysis',
            description: '启动性能分析',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
                startup_id: 'metadata.startupId',
                startup_type: 'metadata.startupType',
                ttid_ms: 'metadata.ttidMs',
                ttfd_ms: 'metadata.ttfdMs',
            },
        },
        {
            id: 'scroll_deep_dive',
            eventTypes: ['scroll', 'inertial_scroll'],
            skillId: 'scrolling_analysis',
            description: '滑动流畅性分析',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
            },
        },
        {
            id: 'tap_deep_dive',
            eventTypes: ['tap', 'long_press', 'screen_unlock'],
            skillId: 'click_response_analysis',
            description: '点击响应分析',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
                package: 'processName',
            },
        },
        {
            id: 'idle_deep_dive',
            eventTypes: ['idle'],
            skillId: 'device_state_snapshot',
            description: '设备状态快照',
            paramMapping: {
                start_ts: 'startTs',
                end_ts: 'endTs',
            },
        },
    ],
    baselineEvidence: '关键指标基线（时间窗、进程、刷新率口径一致）',
    fallbackEvidence: [
        '帧时序与掉帧统计',
        '线程调度与关键耗时切片',
        'IPC/锁竞争与系统侧干扰指标',
    ],
};
const SCENE_TYPE_GROUPS = {
    startup: ['cold_start', 'warm_start', 'hot_start'],
    scroll: ['scroll', 'inertial_scroll'],
    interaction: ['tap', 'long_press', 'ime_show', 'ime_hide'],
    navigation: ['navigation', 'back_key', 'home_key', 'recents_key', 'window_transition'],
    app_switch: ['app_switch', 'home_screen', 'app_foreground'],
    idle: ['idle'],
    device_state: ['screen_on', 'screen_off', 'screen_sleep', 'idle'],
    jank_region: ['jank_region'],
    anr: ['anr'],
};
function normalizeToken(value) {
    return String(value || '').trim().toLowerCase();
}
function normalizeStringArray(values) {
    const out = [];
    const seen = new Set();
    for (const value of values || []) {
        const normalized = normalizeToken(value);
        if (!normalized || seen.has(normalized))
            continue;
        seen.add(normalized);
        out.push(normalized);
    }
    return out;
}
function collectRouteSceneTypes(route) {
    const out = new Set();
    for (const sceneType of normalizeStringArray(route.sceneTypes || [])) {
        out.add(sceneType);
    }
    for (const group of route.sceneTypeGroups || []) {
        if (group === 'all')
            continue;
        for (const sceneType of SCENE_TYPE_GROUPS[group] || []) {
            const normalized = normalizeToken(sceneType);
            if (normalized)
                out.add(normalized);
        }
    }
    return out;
}
function getSceneReconstructionRoutes(profileOrManifest = 'legacy', maybeManifest) {
    const routeProfile = typeof profileOrManifest === 'string'
        ? normalizeRouteProfile(profileOrManifest)
        : 'legacy';
    const manifest = typeof profileOrManifest === 'string'
        ? (maybeManifest ?? exports.DEFAULT_DOMAIN_MANIFEST)
        : profileOrManifest;
    const routes = Array.isArray(manifest.sceneReconstructionRoutes)
        ? manifest.sceneReconstructionRoutes
        : [];
    const effectiveRoutes = routes.length > 0 ? routes : exports.DEFAULT_DOMAIN_MANIFEST.sceneReconstructionRoutes;
    return effectiveRoutes.filter((route) => {
        const routeProfileForRule = normalizeRouteProfile(route.routeProfile);
        return routeProfileForRule === routeProfile;
    });
}
/**
 * Get all scene deep-dive routes from manifest, with fallback to defaults.
 */
function getSceneDeepDiveRoutes(manifest = exports.DEFAULT_DOMAIN_MANIFEST) {
    const routes = Array.isArray(manifest.sceneDeepDiveRoutes)
        ? manifest.sceneDeepDiveRoutes
        : [];
    return routes.length > 0 ? routes : exports.DEFAULT_DOMAIN_MANIFEST.sceneDeepDiveRoutes;
}
/**
 * Look up a deep-dive route by scene/event type.
 * Returns the first route whose eventTypes includes the given type,
 * or the first fallback route if no match, or null.
 */
function getSceneDeepDiveRoute(eventType, manifest = exports.DEFAULT_DOMAIN_MANIFEST) {
    const normalized = String(eventType || '').trim().toLowerCase();
    if (!normalized)
        return null;
    const routes = getSceneDeepDiveRoutes(manifest);
    for (const route of routes) {
        if (route.eventTypes.some((t) => String(t).toLowerCase() === normalized)) {
            return route;
        }
    }
    const fallback = routes.find((r) => r.fallback);
    return fallback ?? null;
}
function matchesSceneReconstructionRoute(sceneType, route) {
    const normalizedSceneType = normalizeToken(sceneType);
    if (!normalizedSceneType)
        return false;
    const excluded = new Set(normalizeStringArray(route.excludeSceneTypes || []));
    if (excluded.has(normalizedSceneType))
        return false;
    const hasAllGroup = (route.sceneTypeGroups || []).some(group => group === 'all');
    if (hasAllGroup)
        return true;
    const included = collectRouteSceneTypes(route);
    if (included.size === 0)
        return false;
    return included.has(normalizedSceneType);
}
function resolveSceneReconstructionRoute(sceneType, manifest = exports.DEFAULT_DOMAIN_MANIFEST, routeProfile = 'legacy') {
    for (const route of getSceneReconstructionRoutes(routeProfile, manifest)) {
        if (matchesSceneReconstructionRoute(sceneType, route)) {
            return route;
        }
    }
    return null;
}
function normalizeRouteProfile(value) {
    if (value === 'legacy' || value === 'smart')
        return value;
    throw new Error(`Invalid scene reconstruction routeProfile: ${String(value)}`);
}
function getStrategyExecutionPolicy(strategyId, manifest = exports.DEFAULT_DOMAIN_MANIFEST) {
    const id = normalizeToken(strategyId);
    if (!id)
        return 'prefer_hypothesis';
    return manifest.strategyExecutionPolicies[id] || 'prefer_hypothesis';
}
function shouldPreferHypothesisLoop(input, manifest = exports.DEFAULT_DOMAIN_MANIFEST) {
    if (input.forceStrategy)
        return false;
    if (normalizeToken(input.preferredLoopMode || '') !== 'hypothesis_experiment')
        return false;
    const policy = getStrategyExecutionPolicy(input.strategyId, manifest);
    return policy !== 'prefer_strategy';
}
function getAspectEvidenceChecklist(aspects, manifest = exports.DEFAULT_DOMAIN_MANIFEST) {
    const rows = [];
    for (const raw of aspects || []) {
        const key = normalizeToken(raw);
        if (!key)
            continue;
        const mapped = manifest.aspectEvidenceMap[key];
        if (!mapped)
            continue;
        rows.push(...mapped);
    }
    return rows;
}
function getModeSpecificEvidenceChecklist(mode, manifest = exports.DEFAULT_DOMAIN_MANIFEST) {
    return [...(manifest.modeEvidenceMap[mode] || [])];
}
//# sourceMappingURL=domainManifest.js.map