import path from "node:path";
import { loadCanonicalConfig } from "./config.js";
import { PRODUCT_METADATA } from "./product.js";
import { compileRepoContext } from "./context.js";
import { packSelectionArtifactFragment, resolveEffectiveMcpPackState } from "./mcp-pack-selection.js";
import { syncExecutionPlan } from "./execution-plan.js";
import { loadExecutionState } from "./execution-state.js";
import { getRuntimeIdentity, listRuntimeExecutionEvents, openRuntimeTarget, persistRuntimeDerivedOutput } from "../runtime/client.js";
import { getMemoryPaths, loadOpenRisks } from "./memory.js";
import { inspectBootstrapTarget } from "./project-detect.js";
import { loadProjectOverlay, resolveExecutionMode, resolveProfileSelection } from "./profiles.js";
import { deriveRepoReadiness } from "./repo-readiness.js";
import { loadLatestReconcileReport } from "./reconcile.js";
import { listSpecialists, normalizeSpecialistId, recommendNextSpecialist } from "./specialists.js";
import { loadActiveRoleHints, loadContinuitySnapshot, loadLatestTaskPacketSet } from "./state.js";
import { validateControlPlane, validateTargetRepo } from "./validator.js";
import { pathExists, readJson, readText, renderDisplayPath } from "../utils/fs.js";
import { buildEcosystemCatalog } from "../integrations/ecosystem-catalog.js";
import { buildMachineGuidanceContext, filterMachineGuidance, loadMachineAdvisory } from "../integrations/machine-advisory.js";
import { buildMachineParityState, summarizeMachineParity } from "../integrations/machine-parity.js";
import { nextActionEngine } from "./next-action.js";
import { buildFeedbackSummary } from "./context-feedback.js";
import { buildExecutionSummary } from "./execution-log.js";
import { loadPreparedScope } from "./prepared-scope.js";
import { loadRepoIntelligenceSummary } from "./repo-intelligence.js";
import { runtimeDecisionFromSnapshot } from "./runtime-decision.js";
import { buildReadyRepoSubstrate } from "./ready-substrate.js";
import { classifyFileArea, deriveTaskArea } from "./task-intent.js";
import { loadWorkflowState } from "./workflow-engine.js";
const REPO_CONTROL_SNAPSHOT_VERSION = 1;
const DEFAULT_WARM_SNAPSHOT_MAX_AGE_MS = 120_000;
const DEFAULT_STALE_SNAPSHOT_MAX_AGE_MS = 10 * 60_000;
const AUTHORITATIVE_DERIVED_OUTPUTS = new Set([
    "execution-state",
    "execution-events"
]);
function repoControlSnapshotPath(targetRoot) {
    return path.join(targetRoot, ".agent", "state", "repo-control-snapshot.json");
}
function buildFreshLoadState(generatedAt = new Date().toISOString()) {
    return {
        source: "fresh",
        freshness: "fresh",
        generatedAt,
        snapshotSavedAt: null,
        snapshotAgeMs: null,
        detail: "Repo-local state is current."
    };
}
function withFreshLoadState(state, generatedAt = new Date().toISOString()) {
    return {
        ...state,
        loadState: buildFreshLoadState(generatedAt)
    };
}
function emptyMachineParitySummary() {
    return {
        available: true,
        updatedAt: new Date().toISOString(),
        overallStatus: "needs-work",
        boundaryNote: "Repo-local Kiwi capability is built into the product. Machine-global parity measures optional external setup that Kiwi can benefit from, but does not treat as canonical repo truth.",
        repoLocalCovered: 0,
        repoLocalTotal: 0,
        machineGlobal: {
            covered: 0,
            partial: 0,
            missing: 0,
            optional: 0,
            total: 0
        },
        topMissing: [],
        topPartial: []
    };
}
export async function loadWarmRepoControlSnapshot(targetRoot, options = {}) {
    const snapshotFilePath = repoControlSnapshotPath(targetRoot);
    if (!(await pathExists(snapshotFilePath))) {
        return null;
    }
    const warmMaxAgeMs = options.warmMaxAgeMs ?? DEFAULT_WARM_SNAPSHOT_MAX_AGE_MS;
    const staleMaxAgeMs = Math.max(options.staleMaxAgeMs ?? DEFAULT_STALE_SNAPSHOT_MAX_AGE_MS, warmMaxAgeMs);
    try {
        const artifact = await readJson(snapshotFilePath);
        if (artifact.artifactType !== "kiwi-control/repo-control-snapshot" || artifact.version !== REPO_CONTROL_SNAPSHOT_VERSION) {
            return null;
        }
        const ageMs = Date.now() - new Date(artifact.savedAt).getTime();
        if (!Number.isFinite(ageMs) || ageMs < 0 || ageMs > staleMaxAgeMs) {
            return null;
        }
        if (ageMs > warmMaxAgeMs) {
            return {
                ...artifact.state,
                runtimeIdentity: artifact.state.runtimeIdentity ?? null,
                derivedFreshness: artifact.state.derivedFreshness ?? [],
                machineParity: artifact.state.machineParity ?? emptyMachineParitySummary(),
                loadState: {
                    source: "stale-snapshot",
                    freshness: "stale",
                    generatedAt: artifact.state.loadState?.generatedAt ?? artifact.savedAt,
                    snapshotSavedAt: artifact.savedAt,
                    snapshotAgeMs: ageMs,
                    detail: `Loaded an older repo snapshot from ${Math.round(ageMs / 1000)}s ago while fresh state refreshes in the background.`
                }
            };
        }
        return {
            ...artifact.state,
            runtimeIdentity: artifact.state.runtimeIdentity ?? null,
            derivedFreshness: artifact.state.derivedFreshness ?? [],
            machineParity: artifact.state.machineParity ?? emptyMachineParitySummary(),
            loadState: {
                source: "warm-snapshot",
                freshness: "warm",
                generatedAt: artifact.state.loadState?.generatedAt ?? artifact.savedAt,
                snapshotSavedAt: artifact.savedAt,
                snapshotAgeMs: ageMs,
                detail: `Loaded a warm repo snapshot from ${Math.round(ageMs / 1000)}s ago while fresh state refreshes in the background.`
            }
        };
    }
    catch {
        return null;
    }
}
export async function persistRepoControlSnapshot(targetRoot, state) {
    if (!(await pathExists(path.join(targetRoot, ".agent")))) {
        return repoControlSnapshotPath(targetRoot);
    }
    const snapshotFilePath = repoControlSnapshotPath(targetRoot);
    const savedAt = new Date().toISOString();
    const artifact = buildRepoControlSnapshotArtifact(state, savedAt);
    await persistRuntimeDerivedOutput({
        targetRoot,
        outputName: "repo-control-snapshot",
        payload: artifact,
        sourceRevision: state.executionState.revision
    });
    return snapshotFilePath;
}
export function buildRepoControlSnapshotArtifact(state, savedAt = new Date().toISOString()) {
    return {
        artifactType: "kiwi-control/repo-control-snapshot",
        version: REPO_CONTROL_SNAPSHOT_VERSION,
        savedAt,
        state: withFreshLoadState(state, state.loadState?.generatedAt ?? savedAt)
    };
}
export async function buildRepoControlState(options) {
    if (options.preferSnapshot) {
        const snapshot = await loadWarmRepoControlSnapshot(options.targetRoot);
        if (snapshot) {
            return snapshot;
        }
    }
    const config = await loadCanonicalConfig(options.repoRoot);
    const state = await buildRepoControlStateFromConfig({
        config,
        repoRoot: options.repoRoot,
        targetRoot: options.targetRoot,
        ...(options.machineAdvisoryOptions ? { machineAdvisoryOptions: options.machineAdvisoryOptions } : {}),
        ...(options.profileName ? { profileName: options.profileName } : {}),
        ...(options.readOnly ? { readOnly: true } : {})
    });
    if (!options.readOnly) {
        await persistRepoControlSnapshot(options.targetRoot, state).catch(() => null);
    }
    return state;
}
export async function buildRepoControlStateFromConfig(options) {
    const generatedAt = new Date().toISOString();
    const [inspection, overlay, selection, continuity, activeRoleHints] = await Promise.all([
        inspectBootstrapTarget(options.targetRoot, options.config),
        loadProjectOverlay(options.targetRoot),
        resolveProfileSelection(options.targetRoot, options.config, options.profileName),
        loadContinuitySnapshot(options.targetRoot),
        loadActiveRoleHints(options.targetRoot)
    ]);
    const executionMode = resolveExecutionMode(options.config, selection, overlay, continuity.latestPhase?.mode);
    const compiledContext = await compileRepoContext({
        targetRoot: options.targetRoot,
        config: options.config,
        profileName: selection.profileName,
        profile: selection.profile,
        overlay,
        executionMode,
        taskType: continuity.latestPhase?.routingSummary.taskType ?? options.config.global.defaults.default_task_type,
        fileArea: continuity.latestPhase?.routingSummary.fileArea ?? "application",
        changeSize: continuity.latestPhase?.routingSummary.changeSize ?? options.config.global.defaults.default_change_size,
        riskLevel: continuity.latestPhase?.routingSummary.riskLevel ?? "medium"
    });
    const recommendedSpecialist = normalizeSpecialistId(options.config, activeRoleHints?.nextRecommendedSpecialist) ??
        normalizeSpecialistId(options.config, continuity.currentFocus?.nextRecommendedSpecialist) ??
        recommendNextSpecialist({
            config: options.config,
            profileName: selection.profileName,
            taskType: compiledContext.taskType,
            fileArea: compiledContext.fileArea,
            projectType: inspection.projectType,
            ...(activeRoleHints?.activeRole ? { activeSpecialistId: activeRoleHints.activeRole } : {})
        }).specialistId;
    const [controlPlaneIssues, targetRepoIssues, openRisks, latestTaskPacketSet, latestReconcile, machineAdvisory, runtimeSnapshot, runtimeIdentity] = await Promise.all([
        validateControlPlane(options.repoRoot, options.config),
        validateTargetRepo(options.targetRoot, options.config, selection),
        loadOpenRisks(options.targetRoot),
        loadLatestTaskPacketSet(options.targetRoot),
        loadLatestReconcileReport(options.targetRoot),
        loadMachineAdvisory(options.machineAdvisoryOptions).catch(() => ({
            artifactType: "kiwi-control/machine-advisory",
            version: 3,
            generatedBy: "kiwi-control machine-advisory",
            windowDays: 7,
            updatedAt: new Date().toISOString(),
            stale: true,
            sections: {
                inventory: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." },
                mcpInventory: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." },
                optimizationLayers: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." },
                setupPhases: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." },
                configHealth: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." },
                usage: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." },
                guidance: { status: "partial", updatedAt: new Date().toISOString(), reason: "Machine advisory unavailable." }
            },
            inventory: [],
            mcpInventory: {
                claudeTotal: 0,
                codexTotal: 0,
                copilotTotal: 0,
                tokenServers: []
            },
            optimizationLayers: [],
            setupPhases: [],
            configHealth: [],
            skillsCount: 0,
            copilotPlugins: [],
            usage: {
                days: 7,
                claude: {
                    available: false,
                    days: [],
                    totals: {
                        inputTokens: 0,
                        outputTokens: 0,
                        cacheCreationTokens: 0,
                        cacheReadTokens: 0,
                        totalTokens: 0,
                        totalCost: null,
                        cacheHitRatio: null
                    },
                    note: "Machine advisory unavailable."
                },
                codex: {
                    available: false,
                    days: [],
                    totals: {
                        inputTokens: 0,
                        outputTokens: 0,
                        cachedInputTokens: 0,
                        reasoningOutputTokens: 0,
                        sessions: 0,
                        totalTokens: 0,
                        cacheHitRatio: null
                    },
                    note: "Machine advisory unavailable."
                },
                copilot: {
                    available: false,
                    note: "Machine advisory unavailable."
                }
            },
            optimizationScore: {
                planning: { label: "planning", score: 0, earnedPoints: 0, maxPoints: 100, activeSignals: [], missingSignals: [] },
                execution: { label: "execution", score: 0, earnedPoints: 0, maxPoints: 100, activeSignals: [], missingSignals: [] },
                assistant: { label: "assistant", score: 0, earnedPoints: 0, maxPoints: 100, activeSignals: [], missingSignals: [] }
            },
            setupSummary: {
                installedTools: { readyCount: 0, totalCount: 0 },
                healthyConfigs: { readyCount: 0, totalCount: 0 },
                activeTokenLayers: [],
                readyRuntimes: {
                    planning: false,
                    execution: false,
                    assistant: false
                }
            },
            systemHealth: {
                criticalCount: 0,
                warningCount: 0,
                okCount: 0
            },
            guidance: [],
            note: "Machine-local advisory is unavailable."
        })),
        openRuntimeTarget({
            targetRoot: options.targetRoot,
            projectType: inspection.projectType,
            profileName: selection.profileName
        }).catch(async () => {
            const executionState = await loadExecutionState(options.targetRoot);
            return runtimeFallbackSnapshot(options.targetRoot, executionState);
        }),
        getRuntimeIdentity().catch(() => null)
    ]);
    const validationIssues = [
        ...controlPlaneIssues,
        ...targetRepoIssues
    ];
    const memoryPaths = getMemoryPaths(options.targetRoot);
    const memoryEntries = [
        ["Repo Facts", memoryPaths.repoFacts],
        ["Current Focus", memoryPaths.currentFocus],
        ["Open Risks", memoryPaths.openRisks],
        ["Context Tree", path.join(options.targetRoot, ".agent", "context", "context-tree.json")]
    ];
    const memoryBank = await Promise.all(memoryEntries.map(async ([label, filePath]) => ({
        label,
        path: renderDisplayPath(options.targetRoot, filePath),
        present: await pathExists(filePath)
    })));
    const continuityItems = [
        {
            label: "Latest checkpoint",
            value: continuity.latestCheckpoint ? `${continuity.latestCheckpoint.phase} [${continuity.latestCheckpoint.createdAt}]` : "none recorded"
        },
        {
            label: "Latest handoff",
            value: continuity.latestHandoff ? `${continuity.latestHandoff.summary} -> ${continuity.latestHandoff.toRole}` : "none recorded"
        },
        {
            label: "Latest reconcile",
            value: latestReconcile ? `${latestReconcile.dispatchId} [${latestReconcile.status}]` : "none recorded"
        },
        {
            label: "Current focus",
            value: continuity.currentFocus?.currentFocus ?? "none recorded"
        },
        {
            label: "Open risks",
            value: openRisks?.risks.join("; ") || "none recorded",
            ...(openRisks?.risks.length ? { tone: "warn" } : {})
        }
    ];
    const availableSpecialists = listSpecialists({
        config: options.config,
        profileName: selection.profileName
    });
    const validation = {
        ok: validationIssues.every((issue) => issue.level !== "error"),
        errors: validationIssues.filter((issue) => issue.level === "error").length,
        warnings: validationIssues.filter((issue) => issue.level === "warn").length,
        issues: validationIssues
    };
    const repoState = summarizeRepoState({
        targetRoot: options.targetRoot,
        inspection,
        validation
    });
    const canonicalExecutionState = runtimeSnapshotToExecutionStateRecord(runtimeSnapshot);
    const executionState = runtimeSnapshotToExecutionState(runtimeSnapshot);
    const readiness = deriveRepoReadiness({
        repoState,
        validation,
        executionState: canonicalExecutionState
    });
    const runtimeDecision = runtimeDecisionFromSnapshot(runtimeSnapshot);
    const fallbackNextCommand = buildFallbackNextCommand(repoState.mode, options.targetRoot);
    const fallbackNextFile = buildFallbackNextFile(inspection.existingAuthorityFiles);
    const defaultRecommendedSpecialist = repoState.mode === "repo-not-initialized"
        ? inspection.projectType === "node"
            ? "fullstack-specialist"
            : inspection.projectType === "python"
                ? "python-specialist"
                : "architecture-specialist"
        : repoState.mode === "initialized-invalid"
            ? "review-specialist"
            : recommendedSpecialist;
    const activeSpecialistId = normalizeSpecialistId(options.config, activeRoleHints?.activeRole, defaultRecommendedSpecialist) ??
        defaultRecommendedSpecialist;
    const activeSpecialistProfile = availableSpecialists.find((entry) => entry.specialistId === activeSpecialistId) ?? null;
    const recommendedSpecialistProfile = availableSpecialists.find((entry) => entry.specialistId === defaultRecommendedSpecialist) ?? null;
    const packSelection = await resolveEffectiveMcpPackState({
        targetRoot: options.targetRoot,
        config: options.config,
        profileName: selection.profileName,
        projectType: inspection.projectType,
        taskType: compiledContext.taskType,
        fileArea: compiledContext.fileArea,
        authorityFiles: compiledContext.authorityOrder,
        starterMcpHints: compiledContext.eligibleMcpServers,
        activeSpecialistId
    });
    const repoOverview = summarizeRepoOverview();
    const ecosystem = buildEcosystemCatalog();
    const kiwiControl = await loadKiwiControlState(options.targetRoot, validationIssues, {
        readOnly: true,
        runtimeSnapshot,
        packSelection: packSelectionArtifactFragment({
            selectedPack: packSelection.selectedPackId,
            selectedPackSource: packSelection.selectedPackSource,
            explicitSelection: packSelection.explicitSelection,
            heuristicPackId: packSelection.heuristicPackId,
            executable: packSelection.executable,
            unavailablePackReason: packSelection.unavailablePackReason,
            effectiveCapabilityIds: packSelection.effectiveCapabilityIds,
            preferredCapabilityIds: packSelection.preferredCapabilityIds,
            unavailableCapabilityIds: packSelection.unavailableCapabilityIds,
            availablePacks: packSelection.availablePacks.map((entry) => ({
                id: entry.id,
                executable: entry.executable,
                unavailablePackReason: entry.unavailablePackReason
            }))
        })
    });
    const machineGuidanceContext = buildMachineGuidanceContext({
        taskType: deriveMachineTaskType(kiwiControl),
        workflowStep: kiwiControl.workflow.currentStepId,
        validationFailed: validation.errors > 0,
        evalPrecisionLow: kiwiControl.feedback.totalRuns > 0 && kiwiControl.feedback.successRate < 50,
        executionRetriesTriggered: kiwiControl.workflow.steps.some((step) => step.retryCount > 0)
    });
    machineAdvisory.guidance = filterMachineGuidance(machineAdvisory.guidance, machineGuidanceContext);
    const machineParity = summarizeMachineParity(buildMachineParityState(machineAdvisory));
    return {
        targetRoot: options.targetRoot,
        loadState: buildFreshLoadState(generatedAt),
        profileName: selection.profileName,
        executionMode,
        projectType: inspection.projectType,
        repoState,
        executionState,
        readiness: {
            label: runtimeDecision.readinessLabel,
            tone: runtimeDecision.readinessTone,
            detail: runtimeDecision.readinessDetail,
            nextCommand: runtimeDecision.nextCommand
        },
        runtimeIdentity,
        derivedFreshness: runtimeSnapshot.derivedFreshness.filter((entry) => AUTHORITATIVE_DERIVED_OUTPUTS.has(entry.outputName)),
        runtimeDecision,
        repoOverview,
        continuity: continuityItems,
        memoryBank,
        specialists: {
            activeSpecialist: activeSpecialistId,
            recommendedSpecialist: defaultRecommendedSpecialist,
            available: availableSpecialists,
            activeProfile: activeSpecialistProfile,
            recommendedProfile: recommendedSpecialistProfile,
            handoffTargets: availableSpecialists.map((specialist) => specialist.specialistId).slice(0, 8),
            safeParallelHint: buildSafeParallelHint(repoState.mode, latestTaskPacketSet?.files.length ?? 0)
        },
        mcpPacks: {
            selectedPack: packSelection.selectedPack,
            selectedPackSource: packSelection.selectedPackSource,
            explicitSelection: packSelection.explicitSelection,
            suggestedPack: packSelection.suggestedPack,
            available: packSelection.availablePacks,
            compatibleCapabilities: packSelection.effectiveCapabilities,
            effectiveCapabilityIds: packSelection.effectiveCapabilityIds,
            preferredCapabilityIds: packSelection.preferredCapabilityIds,
            executable: packSelection.executable,
            unavailablePackReason: packSelection.unavailablePackReason,
            capabilityStatus: !packSelection.executable
                ? "blocked"
                : packSelection.effectiveCapabilities.length > 0
                    ? "compatible"
                    : "limited",
            note: packSelection.note
        },
        validation,
        ecosystem,
        machineAdvisory,
        machineParity,
        kiwiControl
    };
    function summarizeRepoOverview() {
        return [
            { label: "Project type", value: `${inspection.projectType} (${inspection.projectTypeSource})` },
            {
                label: "Active role",
                value: normalizeSpecialistId(options.config, activeRoleHints?.activeRole, activeRoleHints?.activeRole) ??
                    "none recorded"
            },
            {
                label: "Next file",
                value: activeRoleHints?.nextFileToRead ?? continuity.currentFocus?.nextFileToRead ?? fallbackNextFile
            },
            {
                label: "Next command",
                value: activeRoleHints?.nextSuggestedCommand ?? continuity.currentFocus?.nextSuggestedCommand ?? fallbackNextCommand
            },
            {
                label: "Execution lifecycle",
                value: executionState.lifecycle
            },
            { label: "Validation state", value: summarizeValidation(validationIssues) },
            {
                label: "Current phase",
                value: continuity.latestPhase ? `${continuity.latestPhase.label} [${continuity.latestPhase.status}]` : "none recorded"
            }
        ];
    }
}
function deriveMachineTaskType(state) {
    const task = state.contextView.task?.toLowerCase() ?? "";
    if (!task) {
        return null;
    }
    if (/\b(read|inspect|review|summarize)\b/.test(task)) {
        return "read";
    }
    if (/\bdocs?|document|readme\b/.test(task)) {
        return "docs";
    }
    return "implementation";
}
function runtimeSnapshotToExecutionState(snapshot) {
    return {
        revision: snapshot.revision,
        operationId: snapshot.operationId,
        task: snapshot.task,
        sourceCommand: snapshot.sourceCommand,
        lifecycle: fromRuntimeLifecycle(snapshot.lifecycle),
        reason: snapshot.reason,
        nextCommand: snapshot.nextCommand,
        blockedBy: snapshot.blockedBy,
        lastUpdatedAt: snapshot.lastUpdatedAt,
        artifacts: snapshot.artifacts,
        lastEvent: snapshot.lastEvent
            ? {
                revision: snapshot.lastEvent.revision,
                operationId: snapshot.lastEvent.operationId,
                type: snapshot.lastEvent.eventType,
                lifecycle: fromRuntimeLifecycle(snapshot.lastEvent.lifecycle),
                task: snapshot.lastEvent.task,
                sourceCommand: snapshot.lastEvent.sourceCommand,
                reason: snapshot.lastEvent.reason,
                nextCommand: snapshot.lastEvent.nextCommand,
                blockedBy: snapshot.lastEvent.blockedBy,
                artifacts: snapshot.lastEvent.artifacts,
                recordedAt: snapshot.lastEvent.recordedAt
            }
            : null
    };
}
function runtimeSnapshotToExecutionStateRecord(snapshot) {
    return {
        artifactType: "kiwi-control/execution-state",
        version: 1,
        revision: snapshot.revision,
        operationId: snapshot.operationId,
        task: snapshot.task,
        sourceCommand: snapshot.sourceCommand,
        lifecycle: fromRuntimeLifecycle(snapshot.lifecycle),
        reason: snapshot.reason,
        nextCommand: snapshot.nextCommand,
        blockedBy: snapshot.blockedBy,
        lastUpdatedAt: snapshot.lastUpdatedAt,
        artifacts: snapshot.artifacts,
        lastEvent: snapshot.lastEvent
            ? {
                revision: snapshot.lastEvent.revision,
                operationId: snapshot.lastEvent.operationId,
                type: snapshot.lastEvent.eventType,
                lifecycle: fromRuntimeLifecycle(snapshot.lastEvent.lifecycle),
                task: snapshot.lastEvent.task,
                sourceCommand: snapshot.lastEvent.sourceCommand,
                reason: snapshot.lastEvent.reason,
                nextCommand: snapshot.lastEvent.nextCommand,
                blockedBy: snapshot.lastEvent.blockedBy,
                artifacts: snapshot.lastEvent.artifacts,
                recordedAt: snapshot.lastEvent.recordedAt
            }
            : null
    };
}
function runtimeFallbackSnapshot(targetRoot, executionState) {
    const readiness = deriveRepoReadiness({
        repoState: {
            mode: "healthy",
            title: "Repo state is healthy",
            detail: "Repo-local state is readable."
        },
        validation: {
            errors: 0,
            warnings: 0
        },
        executionState
    });
    const runtimeDecision = {
        currentStepId: executionState.lifecycle === "packet-created"
            ? "generate_packets"
            : executionState.lifecycle === "queued"
                ? "execute_packet"
                : executionState.lifecycle === "completed"
                    ? "checkpoint"
                    : executionState.lifecycle === "idle"
                        ? "idle"
                        : "validate",
        currentStepLabel: executionState.lifecycle === "packet-created"
            ? "Generate run packets"
            : executionState.lifecycle === "queued"
                ? "Execute packet"
                : executionState.lifecycle === "completed"
                    ? "Checkpoint progress"
                    : executionState.lifecycle === "idle"
                        ? "Idle"
                        : "Validate outcome",
        currentStepStatus: executionState.lifecycle === "running"
            ? "running"
            : executionState.lifecycle === "blocked" || executionState.lifecycle === "failed"
                ? "failed"
                : executionState.lifecycle === "completed"
                    ? "success"
                    : "pending",
        nextCommand: executionState.nextCommand,
        readinessLabel: readiness.label,
        readinessTone: readiness.tone,
        readinessDetail: readiness.detail,
        nextAction: executionState.nextCommand
            ? {
                action: executionState.lifecycle === "packet-created"
                    ? "Generate run packets"
                    : executionState.lifecycle === "queued"
                        ? "Open latest task packet and execute it"
                        : executionState.lifecycle === "blocked" || executionState.lifecycle === "failed"
                            ? "Fix the blocking execution issue"
                            : "Continue",
                command: executionState.lifecycle === "queued" ? null : executionState.nextCommand,
                reason: executionState.reason ?? readiness.detail,
                priority: executionState.lifecycle === "blocked" || executionState.lifecycle === "failed" ? "critical" : "high"
            }
            : null,
        recovery: executionState.lifecycle === "blocked" || executionState.lifecycle === "failed"
            ? {
                kind: executionState.lifecycle === "failed" ? "failed" : "blocked",
                reason: executionState.reason ?? readiness.detail,
                fixCommand: executionState.nextCommand,
                retryCommand: executionState.sourceCommand
            }
            : null,
        decisionSource: "compatibility-fallback",
        updatedAt: executionState.lastUpdatedAt ?? new Date().toISOString()
    };
    return {
        targetRoot,
        revision: executionState.revision,
        operationId: executionState.operationId,
        task: executionState.task,
        sourceCommand: executionState.sourceCommand,
        lifecycle: toRuntimeLifecycle(executionState.lifecycle),
        reason: executionState.reason,
        nextCommand: executionState.nextCommand,
        blockedBy: executionState.blockedBy,
        artifacts: executionState.artifacts,
        lastUpdatedAt: executionState.lastUpdatedAt,
        lastEvent: executionState.lastEvent
            ? {
                eventId: null,
                revision: executionState.lastEvent.revision,
                operationId: executionState.lastEvent.operationId,
                eventType: executionState.lastEvent.type,
                lifecycle: toRuntimeLifecycle(executionState.lastEvent.lifecycle),
                task: executionState.lastEvent.task,
                sourceCommand: executionState.lastEvent.sourceCommand,
                reason: executionState.lastEvent.reason,
                nextCommand: executionState.lastEvent.nextCommand,
                blockedBy: executionState.lastEvent.blockedBy,
                artifacts: executionState.lastEvent.artifacts,
                actor: "compatibility-fallback",
                recordedAt: executionState.lastEvent.recordedAt
            }
            : null,
        readiness: {
            label: readiness.label,
            tone: readiness.tone,
            detail: readiness.detail,
            nextCommand: readiness.nextCommand
        },
        decision: runtimeDecision,
        derivedFreshness: []
    };
}
function toRuntimeLifecycle(lifecycle) {
    switch (lifecycle) {
        case "packet-created":
            return "packet_created";
        default:
            return lifecycle;
    }
}
function fromRuntimeLifecycle(lifecycle) {
    switch (lifecycle) {
        case "packet_created":
            return "packet-created";
        default:
            return lifecycle;
    }
}
function summarizeValidation(issues) {
    const errors = issues.filter((issue) => issue.level === "error").length;
    const warnings = issues.filter((issue) => issue.level === "warn").length;
    if (errors === 0 && warnings === 0) {
        return "passing";
    }
    if (errors === 0) {
        return `${warnings} warning${warnings === 1 ? "" : "s"}`;
    }
    return `${errors} error${errors === 1 ? "" : "s"}, ${warnings} warning${warnings === 1 ? "" : "s"}`;
}
function summarizeRepoState(options) {
    const sourceOfTruthNote = "Repo-local artifacts under .agent/ and promoted repo instruction files remain the source of truth. The desktop app only reads and reports that state.";
    if (!options.inspection.alreadyInitialized) {
        return {
            mode: "repo-not-initialized",
            title: "Repo not initialized yet",
            detail: `Run ${PRODUCT_METADATA.cli.primaryCommand} init in this folder to seed the repo-local control surfaces before using specialists, checkpoints, or handoffs.`,
            sourceOfTruthNote
        };
    }
    if (options.validation.errors > 0) {
        return {
            mode: "initialized-invalid",
            title: "Repo contract needs repair",
            detail: `${options.validation.errors} validation error${options.validation.errors === 1 ? "" : "s"} are blocking a healthy repo-local state. Use ${PRODUCT_METADATA.cli.primaryCommand} check in this folder to inspect the contract drift.`,
            sourceOfTruthNote
        };
    }
    if (options.validation.warnings > 0) {
        return {
            mode: "initialized-with-warnings",
            title: "Repo is usable with warnings",
            detail: `${options.validation.warnings} warning${options.validation.warnings === 1 ? "" : "s"} remain, but the repo-local control surfaces are present and readable.`,
            sourceOfTruthNote
        };
    }
    return {
        mode: "healthy",
        title: "Repo state is healthy",
        detail: "The repo-local control surfaces are present, validation is clean, and the desktop app can safely mirror the CLI view of repo state.",
        sourceOfTruthNote
    };
}
function buildFallbackNextCommand(mode, _targetRoot) {
    switch (mode) {
        case "repo-not-initialized":
            return `${PRODUCT_METADATA.cli.primaryCommand} init`;
        case "initialized-invalid":
            return `${PRODUCT_METADATA.cli.primaryCommand} check --json`;
        case "initialized-with-warnings":
            return `${PRODUCT_METADATA.cli.primaryCommand} status`;
        default:
            return "none recorded";
    }
}
function buildFallbackNextFile(authorityFiles) {
    return authorityFiles[0] ?? "none recorded";
}
function buildSafeParallelHint(mode, taskFileCount) {
    if (mode === "repo-not-initialized") {
        return "Initialize the repo before handing work to specialists. Generic repos should stay quiet until repo-local surfaces exist.";
    }
    if (mode === "initialized-invalid") {
        return "Repair the repo-local contract first. Parallel work is premature while checkpoints, memory, or handoff state are invalid.";
    }
    if (taskFileCount > 1) {
        return "Parallel work is safest when each specialist owns disjoint files and reconcile is already planned.";
    }
    return "Keep generic repos quiet. Fan out only when file ownership and reconcile responsibilities are explicit.";
}
async function readJsonIfPresent(filePath) {
    if (!(await pathExists(filePath))) {
        return null;
    }
    return readJson(filePath);
}
function normalizeRuntimeExecutionEvent(raw) {
    if (!raw || typeof raw !== "object") {
        return null;
    }
    const event = raw;
    if (typeof event.revision !== "number" || typeof event.eventType !== "string" || typeof event.recordedAt !== "string") {
        return null;
    }
    return {
        eventId: typeof event.eventId === "number" ? event.eventId : null,
        revision: event.revision,
        operationId: typeof event.operationId === "string" ? event.operationId : null,
        eventType: event.eventType,
        lifecycle: typeof event.lifecycle === "string" ? event.lifecycle : "idle",
        task: typeof event.task === "string" ? event.task : null,
        sourceCommand: typeof event.sourceCommand === "string" ? event.sourceCommand : null,
        reason: typeof event.reason === "string" ? event.reason : null,
        nextCommand: typeof event.nextCommand === "string" ? event.nextCommand : null,
        blockedBy: Array.isArray(event.blockedBy) ? event.blockedBy.filter((value) => typeof value === "string") : [],
        artifacts: event.artifacts && typeof event.artifacts === "object"
            ? Object.fromEntries(Object.entries(event.artifacts).map(([key, value]) => [
                key,
                Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : []
            ]))
            : {},
        actor: typeof event.actor === "string" ? event.actor : "compatibility-fallback",
        recordedAt: event.recordedAt
    };
}
async function loadExecutionEventFeed(targetRoot, runtimeSnapshot) {
    if (runtimeSnapshot) {
        try {
            const runtimeEvents = await listRuntimeExecutionEvents(targetRoot);
            return {
                source: "runtime",
                latestRevision: runtimeEvents.latestRevision,
                recentEvents: runtimeEvents.events.slice(0, 12)
            };
        }
        catch {
            // Fall through to the repo-local compatibility export below.
        }
    }
    const compatibilityPath = path.join(targetRoot, ".agent", "state", "execution-events.ndjson");
    if (!(await pathExists(compatibilityPath))) {
        return {
            source: "unavailable",
            latestRevision: runtimeSnapshot?.revision ?? null,
            recentEvents: []
        };
    }
    try {
        const raw = await readText(compatibilityPath);
        const recentEvents = raw
            .split(/\r?\n/)
            .map((line) => line.trim())
            .filter((line) => line.length > 0)
            .slice(-12)
            .map((line) => {
            try {
                return normalizeRuntimeExecutionEvent(JSON.parse(line));
            }
            catch {
                return null;
            }
        })
            .filter((event) => event !== null)
            .reverse();
        return {
            source: "compatibility",
            latestRevision: recentEvents[0]?.revision ?? runtimeSnapshot?.revision ?? null,
            recentEvents
        };
    }
    catch {
        return {
            source: "unavailable",
            latestRevision: runtimeSnapshot?.revision ?? null,
            recentEvents: []
        };
    }
}
async function loadKiwiControlState(targetRoot, validationIssues, options = {}) {
    const contextSelectionPath = path.join(targetRoot, ".agent", "state", "context-selection.json");
    const contextTracePath = path.join(targetRoot, ".agent", "state", "context-trace.json");
    const runtimeLifecyclePath = path.join(targetRoot, ".agent", "state", "runtime-lifecycle.json");
    const indexingPath = path.join(targetRoot, ".agent", "state", "indexing.json");
    const skillsRegistryPath = path.join(targetRoot, ".agent", "state", "skills-registry.json");
    const tokenUsagePath = path.join(targetRoot, ".agent", "state", "token-usage.json");
    const tokenBreakdownPath = path.join(targetRoot, ".agent", "state", "token-breakdown.json");
    const measuredUsagePath = path.join(targetRoot, ".agent", "state", "measured-usage.json");
    const workflowPath = path.join(targetRoot, ".agent", "state", "workflow.json");
    const instructionsPath = path.join(targetRoot, ".agent", "context", "generated-instructions.md");
    const [selection, persistedIndexing, trace, tokenUsage, persistedTokenBreakdown, persistedRuntimeLifecycle, persistedMeasuredUsage, persistedSkills, workflowFilePresent, hasInstructions, preparedScope, repoIntelligence, readySubstrate, executionEvents] = await Promise.all([
        readJsonIfPresent(contextSelectionPath),
        readJsonIfPresent(indexingPath),
        readJsonIfPresent(contextTracePath),
        readJsonIfPresent(tokenUsagePath),
        readJsonIfPresent(tokenBreakdownPath),
        readJsonIfPresent(runtimeLifecyclePath),
        readJsonIfPresent(measuredUsagePath),
        readJsonIfPresent(skillsRegistryPath),
        pathExists(workflowPath),
        pathExists(instructionsPath),
        loadPreparedScope(targetRoot).catch(() => null),
        loadRepoIntelligenceSummary(targetRoot).catch(() => ({
            available: false,
            generatedAt: null,
            summary: null,
            agentPackAvailable: false,
            agentPackPath: null,
            agentPackSummary: null,
            taskPackAvailable: false,
            taskPackPath: null,
            taskPackTask: null,
            taskPackSummary: null,
            taskPackFiles: 0,
            repoMapPath: null,
            symbolIndexPath: null,
            dependencyGraphPath: null,
            impactMapPath: null,
            entryPoints: [],
            keyModules: [],
            topReverseDependencyHubs: [],
            changedFiles: [],
            impactedFiles: [],
            decisionGraphPath: null,
            historyGraphPath: null,
            reviewGraphPath: null,
            importantDecisions: 0,
            hotspotFiles: 0,
            reviewRiskTargets: 0,
            compactContextPackAvailable: false,
            compactContextPackPath: null,
            compactContextPackMode: null,
            compactContextPackTask: null,
            compactContextPackSummary: null,
            compactContextPackFiles: 0,
            reviewContextPackAvailable: false,
            reviewContextPackPath: null,
            reviewContextPackTask: null,
            reviewContextPackSummary: null,
            reviewPackAvailable: false,
            reviewPackPath: null,
            reviewPackSummary: null
        })),
        buildReadyRepoSubstrate(targetRoot, options.runtimeSnapshot, options.packSelection),
        loadExecutionEventFeed(targetRoot, options.runtimeSnapshot)
    ]);
    let contextView = {
        task: null,
        selectedFiles: [],
        excludedPatterns: [],
        reason: null,
        confidence: null,
        confidenceDetail: null,
        keywordMatches: [],
        tree: emptyContextTree(),
        timestamp: null
    };
    let indexing = {
        totalFiles: 0,
        observedFiles: 0,
        selectedFiles: 0,
        candidateFiles: 0,
        excludedFiles: 0,
        discoveredFiles: 0,
        analyzedFiles: 0,
        skippedFiles: 0,
        skippedDirectories: 0,
        visitedDirectories: 0,
        maxDepthExplored: 0,
        fileBudgetReached: false,
        directoryBudgetReached: false,
        partialScan: false,
        ignoreRulesApplied: [],
        skipped: [],
        indexedFiles: 0,
        indexUpdatedFiles: 0,
        indexReusedFiles: 0,
        impactFiles: 0,
        changedSignals: 0,
        keywordSignals: 0,
        importSignals: 0,
        repoContextSignals: 0,
        scopeArea: null,
        coverageNote: "Run kiwi-control prepare to record indexing coverage and selection reasoning.",
        selectionReason: null
    };
    let fileAnalysis = {
        totalFiles: 0,
        scannedFiles: 0,
        skippedFiles: 0,
        selectedFiles: 0,
        excludedFiles: 0,
        selected: [],
        excluded: [],
        skipped: []
    };
    let contextTrace = {
        initialSignals: {
            changedFiles: [],
            recentFiles: [],
            importNeighbors: [],
            proximityFiles: [],
            keywordMatches: [],
            repoContextFiles: []
        },
        expansionSteps: [],
        honesty: {
            heuristic: true,
            lowConfidence: false,
            partialScan: false
        }
    };
    if (selection) {
        const tree = buildContextTree(selection);
        const observedFiles = collectObservedTreeFiles(selection).length;
        const discovery = selection.signals.discovery;
        contextView = {
            task: selection.task,
            selectedFiles: selection.include,
            excludedPatterns: selection.exclude,
            reason: selection.reason,
            confidence: selection.confidence ?? null,
            confidenceDetail: describeContextConfidence(selection),
            keywordMatches: selection.signals?.keywordMatches ?? [],
            tree,
            timestamp: selection.timestamp
        };
        indexing = {
            totalFiles: discovery?.totalFiles ?? observedFiles,
            observedFiles,
            selectedFiles: tree.selectedCount,
            candidateFiles: tree.candidateCount,
            excludedFiles: tree.excludedCount,
            discoveredFiles: discovery?.discoveredFiles ?? observedFiles,
            analyzedFiles: discovery?.analyzedFiles ?? observedFiles,
            skippedFiles: discovery?.skippedFiles ?? 0,
            skippedDirectories: discovery?.skippedDirectories ?? 0,
            visitedDirectories: discovery?.visitedDirectories ?? 0,
            maxDepthExplored: discovery?.maxDepthExplored ?? 0,
            fileBudgetReached: Boolean(discovery?.fileBudgetReached),
            directoryBudgetReached: Boolean(discovery?.directoryBudgetReached),
            partialScan: Boolean(discovery?.partialScan),
            ignoreRulesApplied: discovery?.ignoreRulesApplied ?? [],
            skipped: discovery?.skipped ?? [],
            indexedFiles: discovery?.indexedFiles ?? 0,
            indexUpdatedFiles: discovery?.indexUpdatedFiles ?? 0,
            indexReusedFiles: discovery?.indexReusedFiles ?? 0,
            impactFiles: discovery?.impactFiles ?? 0,
            changedSignals: (selection.signals.changedFiles ?? []).length,
            keywordSignals: (selection.signals.keywordMatches ?? []).length,
            importSignals: (selection.signals.importNeighbors ?? []).length,
            repoContextSignals: (selection.signals.repoContextFiles ?? []).length,
            scopeArea: deriveTaskArea(selection.task),
            coverageNote: describeIndexingCoverage(selection, observedFiles),
            selectionReason: selection.reason
        };
    }
    if (persistedIndexing) {
        indexing = {
            ...indexing,
            totalFiles: persistedIndexing.totalFiles,
            discoveredFiles: persistedIndexing.discoveredFiles,
            analyzedFiles: persistedIndexing.analyzedFiles,
            skippedFiles: persistedIndexing.skippedFiles,
            skippedDirectories: persistedIndexing.skippedDirectories,
            visitedDirectories: persistedIndexing.visitedDirectories,
            maxDepthExplored: persistedIndexing.maxDepthExplored,
            fileBudgetReached: persistedIndexing.fileBudgetReached,
            directoryBudgetReached: persistedIndexing.directoryBudgetReached,
            partialScan: persistedIndexing.partialScan,
            ignoreRulesApplied: persistedIndexing.ignoreRulesApplied,
            skipped: persistedIndexing.skipped,
            indexedFiles: persistedIndexing.indexedFiles ?? indexing.indexedFiles,
            indexUpdatedFiles: persistedIndexing.indexUpdatedFiles ?? indexing.indexUpdatedFiles,
            indexReusedFiles: persistedIndexing.indexReusedFiles ?? indexing.indexReusedFiles,
            impactFiles: persistedIndexing.impactFiles ?? indexing.impactFiles
        };
    }
    if (trace) {
        fileAnalysis = {
            totalFiles: trace.fileAnalysis.totalFiles,
            scannedFiles: trace.fileAnalysis.scannedFiles,
            skippedFiles: trace.fileAnalysis.skippedFiles,
            selectedFiles: trace.fileAnalysis.selectedFiles,
            excludedFiles: trace.fileAnalysis.excludedFiles,
            selected: trace.fileAnalysis.selected,
            excluded: trace.fileAnalysis.excluded,
            skipped: trace.fileAnalysis.skipped
        };
        contextTrace = {
            initialSignals: trace.initialSignals,
            expansionSteps: trace.expansionSteps,
            honesty: trace.honesty
        };
    }
    let tokenAnalytics = {
        selectedTokens: 0,
        fullRepoTokens: 0,
        savingsPercent: 0,
        fileCountSelected: 0,
        fileCountTotal: 0,
        estimationMethod: null,
        estimateNote: null,
        topDirectories: [],
        task: null,
        timestamp: null
    };
    let wastedFiles = {
        files: [],
        totalWastedTokens: 0,
        removalSavingsPercent: 0
    };
    let heavyDirectories = {
        directories: []
    };
    let tokenBreakdown = {
        partialScan: false,
        categories: []
    };
    let runtimeLifecycle = {
        currentTask: null,
        currentStage: "idle",
        validationStatus: null,
        nextSuggestedCommand: null,
        nextRecommendedAction: null,
        recentEvents: []
    };
    let measuredUsage = {
        available: false,
        source: "none",
        totalTokens: 0,
        totalRuns: 0,
        runs: [],
        workflows: [],
        files: [],
        note: "No measured token usage is available yet."
    };
    let skills = {
        activeSkills: [],
        suggestedSkills: [],
        totalSkills: 0
    };
    let workflowState = {
        artifactType: "kiwi-control/workflow",
        version: 3,
        timestamp: new Date().toISOString(),
        task: null,
        status: "pending",
        currentStepId: null,
        steps: []
    };
    if (tokenUsage) {
        const usage = tokenUsage;
        tokenAnalytics = {
            selectedTokens: usage.selected_tokens,
            fullRepoTokens: usage.full_repo_tokens,
            savingsPercent: usage.savings_percent,
            fileCountSelected: usage.file_count_selected,
            fileCountTotal: usage.file_count_total,
            estimationMethod: usage.estimation_method ?? null,
            estimateNote: usage.estimate_note ?? null,
            topDirectories: usage.top_directories ?? [],
            task: usage.task,
            timestamp: usage.timestamp
        };
        wastedFiles = {
            files: usage.wasted_files ?? [],
            totalWastedTokens: usage.wasted_tokens_total ?? 0,
            removalSavingsPercent: usage.wasted_removal_savings_percent ?? 0
        };
        heavyDirectories = {
            directories: usage.heavy_directories ?? []
        };
        measuredUsage = {
            available: usage.measured_usage?.available ?? false,
            source: usage.measured_usage?.source ?? "none",
            totalTokens: usage.measured_usage?.total_tokens ?? 0,
            totalRuns: usage.measured_usage?.total_runs ?? 0,
            runs: [],
            workflows: [],
            files: [],
            note: usage.measured_usage?.note ?? measuredUsage.note
        };
    }
    if (persistedTokenBreakdown) {
        tokenBreakdown = {
            partialScan: persistedTokenBreakdown.partial_scan,
            categories: persistedTokenBreakdown.categories
        };
    }
    if (persistedRuntimeLifecycle) {
        runtimeLifecycle = {
            currentTask: persistedRuntimeLifecycle.currentTask,
            currentStage: persistedRuntimeLifecycle.currentStage,
            validationStatus: persistedRuntimeLifecycle.validationStatus,
            nextSuggestedCommand: persistedRuntimeLifecycle.nextSuggestedCommand,
            nextRecommendedAction: persistedRuntimeLifecycle.nextRecommendedAction,
            recentEvents: persistedRuntimeLifecycle.recentEvents
        };
    }
    if (persistedMeasuredUsage) {
        measuredUsage = {
            available: persistedMeasuredUsage.available,
            source: persistedMeasuredUsage.source,
            totalTokens: persistedMeasuredUsage.totalTokens,
            totalRuns: persistedMeasuredUsage.totalRuns,
            runs: persistedMeasuredUsage.runs,
            workflows: persistedMeasuredUsage.workflows,
            files: persistedMeasuredUsage.files,
            note: persistedMeasuredUsage.note
        };
    }
    if (persistedSkills) {
        skills = {
            activeSkills: persistedSkills.activeSkills,
            suggestedSkills: persistedSkills.suggestedSkills,
            totalSkills: persistedSkills.skills.length
        };
    }
    if (workflowFilePresent) {
        workflowState = await loadWorkflowState(targetRoot);
    }
    const efficiency = {
        instructionsGenerated: hasInstructions,
        instructionsPath: hasInstructions ? instructionsPath : null
    };
    // Load decision engine, feedback, and execution data in parallel
    const [decisionOutput, feedbackSummary, executionSummary] = await Promise.all([
        nextActionEngine(targetRoot, validationIssues, {
            persist: false
        }).catch(() => ({
            nextActions: [],
            summary: "Decision engine unavailable",
            decisionLogic: {
                artifactType: "kiwi-control/decision-logic",
                version: 1,
                timestamp: new Date().toISOString(),
                summary: "Decision engine unavailable",
                decisionPriority: "low",
                inputSignals: [],
                reasoningChain: [],
                ignoredSignals: []
            }
        })),
        buildFeedbackSummary(targetRoot, contextView.task ?? undefined).catch(() => ({
            totalRuns: 0, successRate: 0, adaptationLevel: "limited", note: "Adaptive feedback is unavailable.", basedOnPastRuns: false, reusedPattern: null, similarTasks: [], recentEntries: [],
            topBoostedFiles: [], topPenalizedFiles: []
        })),
        buildExecutionSummary(targetRoot).catch(() => ({
            totalExecutions: 0, totalTokensUsed: 0, averageTokensPerRun: 0,
            successRate: 0, recentExecutions: [], tokenTrend: "insufficient-data"
        }))
    ]);
    const nextActions = {
        actions: decisionOutput.nextActions,
        summary: decisionOutput.summary
    };
    const decisionLogic = {
        summary: decisionOutput.decisionLogic?.summary ?? decisionOutput.summary,
        decisionPriority: decisionOutput.decisionLogic?.decisionPriority ?? "low",
        inputSignals: decisionOutput.decisionLogic?.inputSignals ?? [],
        reasoningChain: decisionOutput.decisionLogic?.reasoningChain ?? [],
        ignoredSignals: decisionOutput.decisionLogic?.ignoredSignals ?? []
    };
    const feedback = {
        totalRuns: feedbackSummary.totalRuns,
        successRate: feedbackSummary.successRate,
        adaptationLevel: feedbackSummary.adaptationLevel,
        note: feedbackSummary.note,
        basedOnPastRuns: feedbackSummary.basedOnPastRuns,
        reusedPattern: feedbackSummary.reusedPattern,
        similarTasks: feedbackSummary.similarTasks,
        recentEntries: feedbackSummary.recentEntries,
        topBoostedFiles: feedbackSummary.topBoostedFiles,
        topPenalizedFiles: feedbackSummary.topPenalizedFiles
    };
    const execution = {
        totalExecutions: executionSummary.totalExecutions,
        totalTokensUsed: executionSummary.totalTokensUsed,
        averageTokensPerRun: executionSummary.averageTokensPerRun,
        successRate: executionSummary.successRate,
        recentExecutions: executionSummary.recentExecutions,
        tokenTrend: executionSummary.tokenTrend
    };
    const executionTrace = {
        steps: workflowState.steps.map((step) => ({
            stepId: step.stepId,
            action: step.action,
            status: step.status,
            expectedOutput: step.expectedOutput,
            files: step.files,
            skillsApplied: step.skillsApplied,
            attemptCount: step.attemptCount,
            retryCount: step.retryCount,
            tokenUsage: {
                source: step.tokenUsage.source,
                measuredTokens: step.tokenUsage.measuredTokens,
                estimatedTokens: step.tokenUsage.estimatedTokens,
                note: step.tokenUsage.note
            },
            result: step.result,
            output: step.output,
            validation: step.validation,
            failureReason: step.failureReason,
            updatedAt: step.updatedAt
        })),
        whyThisHappened: decisionLogic.summary
    };
    const executionPlan = await syncExecutionPlan(targetRoot, {
        task: contextView.task ?? workflowState.task,
        validationIssues,
        persist: false
    }).catch(() => ({
        artifactType: "kiwi-control/execution-plan",
        version: 2,
        task: contextView.task ?? workflowState.task,
        intent: null,
        hierarchy: {
            goal: contextView.task ?? workflowState.task,
            subtasks: []
        },
        state: "idle",
        currentStepIndex: 0,
        confidence: null,
        risk: "low",
        blocked: false,
        summary: "No execution plan is recorded yet.",
        steps: [],
        nextCommands: [],
        lastError: null,
        contextSnapshot: {
            selectedFiles: [],
            selectedModuleGroups: [],
            confidence: null,
            contextTreePath: null,
            dependencyChains: {},
            forwardDependencies: [],
            reverseDependencies: []
        },
        impactPreview: {
            likelyFiles: [],
            moduleGroups: []
        },
        verificationLayers: [],
        partialResults: [],
        evalSummary: null,
        updatedAt: new Date().toISOString()
    }));
    return {
        contextView, tokenAnalytics, efficiency,
        nextActions, feedback, execution, wastedFiles, heavyDirectories, indexing,
        fileAnalysis, contextTrace, tokenBreakdown, decisionLogic, runtimeLifecycle, executionEvents,
        measuredUsage, skills,
        workflow: {
            task: workflowState.task,
            status: workflowState.status,
            currentStepId: workflowState.currentStepId,
            steps: workflowState.steps
        },
        executionTrace,
        executionPlan: {
            summary: executionPlan.summary,
            intent: executionPlan.intent,
            hierarchy: executionPlan.hierarchy,
            state: executionPlan.state,
            currentStepIndex: executionPlan.currentStepIndex,
            confidence: executionPlan.confidence,
            risk: executionPlan.risk,
            blocked: executionPlan.blocked,
            steps: executionPlan.steps,
            nextCommands: executionPlan.nextCommands,
            lastError: executionPlan.lastError,
            impactPreview: executionPlan.impactPreview,
            verificationLayers: executionPlan.verificationLayers,
            partialResults: executionPlan.partialResults
        },
        repoIntelligence,
        readySubstrate
    };
}
function describeIndexingCoverage(selection, observedFiles) {
    const discovery = selection.signals.discovery;
    if (!discovery) {
        return `Showing ${observedFiles} observed files from live selector signals.`;
    }
    const indexNote = typeof discovery.indexReusedFiles === "number" || typeof discovery.indexUpdatedFiles === "number"
        ? ` The incremental import index reused ${discovery.indexReusedFiles ?? 0} files and refreshed ${discovery.indexUpdatedFiles ?? 0}.`
        : "";
    if (discovery.fileBudgetReached || discovery.directoryBudgetReached) {
        return `Discovery hit a budget limit, so coverage is intentionally partial and bounded.${indexNote}`;
    }
    if (discovery.maxDepthExplored >= 4) {
        return `Discovery reached depth ${discovery.maxDepthExplored} and stayed within budget.${indexNote}`;
    }
    return `Discovery stayed shallow at depth ${discovery.maxDepthExplored}, which usually means strong early signals narrowed the scope quickly.${indexNote}`;
}
function describeContextConfidence(selection) {
    const confidence = selection.confidence ?? null;
    if (!confidence) {
        return null;
    }
    const maxDepthExplored = selection.signals.discovery?.maxDepthExplored ?? 0;
    const budgetLimited = Boolean(selection.signals.discovery?.fileBudgetReached || selection.signals.discovery?.directoryBudgetReached);
    if (confidence === "high") {
        return "Multiple repo-local signals agree and current coverage looks healthy.";
    }
    if (confidence === "medium") {
        if (budgetLimited) {
            return "Useful evidence was found, but discovery hit a budget limit.";
        }
        if (maxDepthExplored >= 4) {
            return "Useful evidence was found across the repo, but coverage is still partial.";
        }
        return "Useful evidence was found, but the file set should still be treated as partial.";
    }
    if (budgetLimited) {
        return "Evidence is narrow and discovery hit a budget limit.";
    }
    if (maxDepthExplored < 4) {
        return "Evidence is narrow and repo coverage is still limited.";
    }
    return "Evidence is narrow or partial, so verify file relevance before editing.";
}
function emptyContextTree() {
    return {
        nodes: [],
        selectedCount: 0,
        candidateCount: 0,
        excludedCount: 0
    };
}
function buildContextTree(selection) {
    const selectedFiles = selection.include.filter(isVisibleContextTreePath);
    const observedFiles = collectObservedTreeFiles(selection);
    if (observedFiles.length === 0) {
        return emptyContextTree();
    }
    const taskArea = deriveTaskArea(selection.task);
    const selectedSet = new Set(selectedFiles);
    const directSignals = new Set([
        ...selection.signals.changedFiles,
        ...selection.signals.importNeighbors,
        ...selection.signals.keywordMatches
    ].filter(isVisibleContextTreePath));
    const scopedPrefixes = deriveContextTreeScopedPrefixes([...directSignals].filter((file) => classifyFileArea(file) === taskArea), taskArea);
    const statusByFile = new Map();
    for (const file of observedFiles) {
        if (selectedSet.has(file)) {
            statusByFile.set(file, "selected");
            continue;
        }
        statusByFile.set(file, isExcludedContextTreeFile(file, taskArea, scopedPrefixes) ? "excluded" : "candidate");
    }
    const root = new Map();
    for (const file of sortContextTreePaths([...statusByFile.keys()])) {
        insertContextTreePath(root, file, statusByFile.get(file) ?? "candidate");
    }
    const counts = [...statusByFile.values()].reduce((summary, status) => {
        if (status === "selected")
            summary.selectedCount += 1;
        if (status === "candidate")
            summary.candidateCount += 1;
        if (status === "excluded")
            summary.excludedCount += 1;
        return summary;
    }, { selectedCount: 0, candidateCount: 0, excludedCount: 0 });
    return {
        nodes: [...root.values()].map((node) => finalizeContextTreeNode(node, taskArea, scopedPrefixes)),
        ...counts
    };
}
function collectObservedTreeFiles(selection) {
    const seen = new Set();
    const orderedSignals = [
        selection.include,
        selection.signals.changedFiles,
        selection.signals.keywordMatches,
        selection.signals.importNeighbors,
        selection.signals.proximityFiles.slice(0, 10),
        selection.signals.recentFiles.slice(0, 12)
    ];
    for (const files of orderedSignals) {
        for (const file of files) {
            if (!isVisibleContextTreePath(file)) {
                continue;
            }
            seen.add(file);
        }
    }
    return [...seen];
}
function isVisibleContextTreePath(filePath) {
    return !filePath.startsWith(".agent/");
}
function insertContextTreePath(root, filePath, status) {
    const parts = filePath.split("/").filter(Boolean);
    let currentLevel = root;
    let currentPath = "";
    for (const [index, part] of parts.entries()) {
        currentPath = currentPath ? `${currentPath}/${part}` : part;
        const isFile = index === parts.length - 1;
        let node = currentLevel.get(part);
        if (!node) {
            node = {
                name: part,
                path: currentPath,
                kind: isFile ? "file" : "directory",
                status: isFile ? status : "excluded",
                children: new Map()
            };
            currentLevel.set(part, node);
        }
        if (isFile) {
            node.status = status;
            return;
        }
        currentLevel = node.children;
    }
}
function finalizeContextTreeNode(node, taskArea, scopedPrefixes) {
    const children = [...node.children.values()]
        .map((child) => finalizeContextTreeNode(child, taskArea, scopedPrefixes))
        .sort(compareContextTreeNodes);
    if (node.kind === "file") {
        return {
            name: node.name,
            path: node.path,
            kind: node.kind,
            status: node.status,
            expanded: false,
            children: []
        };
    }
    const status = children.some((child) => child.status === "selected")
        ? "selected"
        : children.some((child) => child.status === "candidate")
            ? "candidate"
            : "excluded";
    return {
        name: node.name,
        path: node.path,
        kind: "directory",
        status,
        expanded: shouldExpandContextTreeDirectory(node.path, taskArea, scopedPrefixes, children),
        children
    };
}
function compareContextTreeNodes(left, right) {
    if (left.kind !== right.kind) {
        return left.kind === "directory" ? -1 : 1;
    }
    const rank = { selected: 0, candidate: 1, excluded: 2 };
    const rankDelta = rank[left.status] - rank[right.status];
    if (rankDelta !== 0) {
        return rankDelta;
    }
    return left.name.localeCompare(right.name);
}
function sortContextTreePaths(files) {
    return [...files].sort((left, right) => {
        const leftParts = left.split("/").length;
        const rightParts = right.split("/").length;
        if (leftParts !== rightParts) {
            return leftParts - rightParts;
        }
        return left.localeCompare(right);
    });
}
function deriveContextTreeScopedPrefixes(files, taskArea) {
    if (taskArea !== "application" && taskArea !== "docs") {
        return [];
    }
    const prefixes = new Set();
    for (const file of files) {
        const directory = path.dirname(file).replace(/\\/g, "/");
        if (!directory || directory === ".") {
            continue;
        }
        prefixes.add(directory);
    }
    return [...prefixes];
}
function isExcludedContextTreeFile(filePath, taskArea, scopedPrefixes) {
    if (isAuthorityInstructionTreeFile(filePath)) {
        return true;
    }
    if (classifyFileArea(filePath) !== taskArea) {
        return true;
    }
    if (scopedPrefixes.length > 0 && !matchesContextTreePrefixes(filePath, scopedPrefixes)) {
        return true;
    }
    return false;
}
function matchesContextTreePrefixes(filePath, prefixes) {
    if (prefixes.length === 0) {
        return true;
    }
    const normalized = filePath.replace(/\\/g, "/");
    return prefixes.some((prefix) => normalized === prefix || normalized.startsWith(`${prefix}/`));
}
function isAuthorityInstructionTreeFile(filePath) {
    const normalized = filePath.replace(/\\/g, "/").toLowerCase();
    const basename = path.basename(normalized);
    return basename === "agents.md"
        || basename === "claude.md"
        || basename === "copilot-instructions.md"
        || normalized.startsWith(".github/instructions/")
        || normalized.startsWith(".github/agents/");
}
function shouldExpandContextTreeDirectory(directoryPath, taskArea, scopedPrefixes, children) {
    if (taskArea === "docs" && (directoryPath === "docs" || directoryPath.startsWith("docs/"))) {
        return true;
    }
    if (taskArea === "application" && scopedPrefixes.some((prefix) => prefix === directoryPath || prefix.startsWith(`${directoryPath}/`))) {
        return true;
    }
    if (children.some((child) => child.status === "selected") && classifyFileArea(directoryPath) === taskArea) {
        return true;
    }
    return false;
}
