'use client'; import { Nudge } from "../sql/nudges.cjs"; import { IndexRecommendation } from "../query.cjs"; import { ActionPlanQuery } from "./aggregate-index-recommendations.cjs"; //#region src/action-plan/build-action-plan.d.ts /** * Bundling key for a step. v0.9/v1 = the affected table (`schema.table`); * #3100 widens this to a table-cluster. */ type DomainLabel = string; type IndexActionColumns = IndexRecommendation["columns"]; /** * One index change inside a step. A step is a unit of work applied in one go, * so it carries 1..N of these. Only `create` ships in #3098; the `drop` variant * exists for the type and lands with full-DB unused detection (#3120). */ type IndexAction = { op: "create"; definition: string; columns: IndexActionColumns; /** Prefix indexes this one absorbs (covering `(a,b,c)` absorbs `(a,b)`). */ coveredDefinitions: string[]; /** Union of query hashes this create helps, including absorbed prefixes. */ affectedQueryHashes: string[]; } | { op: "drop"; definition: string; reason: "unused" | "redundant"; }; /** Before/after planner cost for one query the step affects. */ interface AffectedQueryCost { hash: string; cost: number; optimizedCost: number; } interface CostReduction { average: number; best: number; total: number; } /** * A query whose cost rose past the configured regression threshold. The caller * (which owns the threshold config and the shared cost-delta rounding contract) * detects the breach; this module only shapes and ranks it. */ interface RegressionBreach { queryHash: string; /** Current planner cost. */ cost: number; /** Baseline cost the breach is measured against. */ baselineCost: number; /** Increase over baseline, in percent. Pre-rounded by the caller. */ increasePercentage: number; } /** A single anti-pattern finding shown inside a nudge step. */ type NudgeFinding = Pick; /** * One analyzed query plus its anti-pattern nudges, scoped current-state by the * caller. The two synthetic optimizer nudges (`*_IMPROVEMENT_FOUND`) are not * anti-patterns — they restate the index win — and are dropped here, not by the * caller. */ interface ActionPlanNudgeQuery { hash: string; nudges: readonly Nudge[]; } /** * A prioritized recommendation in the database-health action plan, a * discriminated union over action kinds: `index` (#3098), `regression` (#3099) * and `nudge` (#3102). * * Tiering across kinds is positional, not by `value` — the kinds' `value` * scores carry different units and are never compared across tiers. The order * is regression → CRITICAL nudge → index → WARNING nudge → INFO nudge: a * "something got worse" signal and a critical anti-pattern outrank a "do this * to improve" suggestion, while lower-severity advice falls below it. See * {@link buildActionPlan}. */ type ActionableStep = { kind: "index"; /** * Stable, content-derived identity: hash(domain + sorted index ops). Used * as the React key, the client freeze-diff key, and future triage identity. */ key: string; domain: DomainLabel; /** 1..N index actions bundled for this domain. */ indexes: IndexAction[]; /** UNION of affected query hashes across the bundle — never a sum. */ affectedQueryCount: number; /** Per-affected-query before/after cost, for display. */ affectedQueries: AffectedQueryCost[]; costReduction: CostReduction; /** Ranking score = total absolute reduction. Hidden from the user. */ value: number; } | { kind: "regression"; /** Stable, content-derived identity: hash("regression" + queryHash). */ key: string; queryHash: string; cost: number; baselineCost: number; increasePercentage: number; /** Within-tier ranking score = increasePercentage. Hidden from the user. */ value: number; } | { kind: "nudge"; /** Stable, content-derived identity: hash("nudge" + queryHash). */ key: string; queryHash: string; /** The query's anti-pattern findings, highest severity first. */ nudges: NudgeFinding[]; /** Highest severity across the findings — sets the card's tier. */ severity: Nudge["severity"]; /** Within-tier ranking score = summed severity weight. Hidden. */ value: number; }; /** * Consolidate analyzed queries and detected regressions into one prioritized * action plan. * * - Tiering is positional across kinds: regression → CRITICAL nudge → index → * WARNING nudge → INFO nudge. A regression or critical anti-pattern (both * "something is wrong") outranks an index suggestion ("do this to improve"); * lower-severity advice falls below it. Cross-kind `value`s carry different * units and are never compared. Within regressions, sort by * `increasePercentage` descending; within indexes, by summed absolute cost * reduction; within a nudge tier, by summed severity weight. * - Index bundling: one step per domain (table). Non-overlapping indexes on the * same table share a step; a covering `(a,b,c)` absorbs `(a,b)`. * - Index ranking: summed absolute cost reduction (`cost - optimizedCost`) over * the UNION of affected query hashes, each query counted once. * - Nudge bundling: one step per query, carrying all its anti-pattern findings; * the step's tier is the query's highest severity. * * Callers are expected to pass current-state, latest-per-hash queries; this * module does not gate on age or recency. */ declare function buildActionPlan(queries: readonly ActionPlanQuery[], regressions?: readonly RegressionBreach[], nudgeQueries?: readonly ActionPlanNudgeQuery[]): ActionableStep[]; //#endregion export { ActionPlanNudgeQuery, ActionableStep, AffectedQueryCost, CostReduction, DomainLabel, IndexAction, NudgeFinding, RegressionBreach, buildActionPlan }; //# sourceMappingURL=build-action-plan.d.cts.map