/** * log10x_estimate_savings — forecast and verify per-pattern reduction policy. * * Two modes share one file because they share the same per-destination cost * model and PromQL plumbing. `runEstimateForecast` and `runEstimateVerify` * are exported as pure functions so `configure_engine` can fold a forecast * into its own envelope without re-querying. * * MODE: forecast * Input is either: * (a) `proposed_config`: explicit per-pattern (action, optional cap) * rows, e.g. produced by `configure_engine`'s greedy solver. * (b) `target_percent`: a % reduction goal. We run the same greedy * the solver uses (sorted by 30d bytes DESC), assigning the * destination's `action_defaults.standard` action until we hit * the target. * For each row we look up the 30d bytes + events, compute avg event * size, project low/expected/high savings via projectActionRange, and * aggregate totals + coverage. Caveats surface destination/no-op * mismatches and small-event degradation. * * MODE: verify * Input is `baseline_window` (pre-merge) + `post_window` (post-merge). * We query `all_events_summaryBytes_total` segmented by the engine's * `routeState` label (TenXSummary emits it on the * receive aggregator): * - baseline_bytes : sum over baseline (routeState!="drop" only) * - post_passed_bytes : sum over post (routeState!="drop" only) * - post_dropped_bytes : sum over post (routeState="drop") * `delivered_pct = 1 - (post_passed_bytes / scale(baseline_bytes,...))` * and we attribute the gap to four buckets: * - cap_fired : bytes the engine dropped for patterns that * existed in the baseline (i.e. the policy worked) * - drift : organic growth on patterns we DIDN'T cap * - new_patterns: bytes from patterns that weren't in the baseline * - leakage : bytes that passed for patterns we SHOULD have * capped (cap mis-set, no row, sample_n too loose) * * GRACEFUL-NOT-CONFIGURED NOTE * The spec calls for `NotConfiguredError` from `lib/not-configured.ts`. * That framework hasn't landed here; the equivalent existing primitive is * `CustomerMetricsNotConfiguredError` thrown from `resolveBackend()`. * We don't use that: our queries hit the env's own metrics backend * (Reporter / Receiver TenXSummary metrics live on `env.metricsBackend`, * not the cross-pillar customer backend), same as `savings.ts` and * `trend.ts`. Structured-error envelopes are emitted directly with * `phase` + `error` fields. When the graceful-not-configured framework * lands, swap the inline envelopes for `notConfiguredEnvelopeFromError`. */ import { z } from 'zod'; import type { EnvConfig } from '../lib/environments.js'; import { type Action, type ComputeSavingProjection } from '../lib/cost.js'; import type { SiemId } from '../lib/siem/pricing.js'; import { type VolumeLensResolution } from '../lib/volume-lens.js'; import { type StructuredOutput } from '../lib/output-types.js'; import { type ActionBytesBuckets } from '../lib/cap-csv-parser.js'; import { type Plan } from '../lib/plan-solver.js'; import { type PlanDependencySummary } from '../lib/plan-dependencies.js'; export declare const estimateSavingsSchema: { mode: z.ZodDefault>; proposed_config: z.ZodOptional; cap_bytes_per_window: z.ZodOptional; sample_n: z.ZodOptional; }, "strip", z.ZodTypeAny, { pattern_hash: string; action: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop"; cap_bytes_per_window?: number | undefined; sample_n?: number | undefined; }, { pattern_hash: string; action: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop"; cap_bytes_per_window?: number | undefined; sample_n?: number | undefined; }>, "many">>; target_percent: z.ZodOptional; budget_usd_monthly: z.ZodOptional; budget_gb_monthly: z.ZodOptional; default_action: z.ZodOptional>; retriever_installed: z.ZodDefault>; allow_lossy: z.ZodDefault>; deployment: z.ZodOptional>; exception_services: z.ZodOptional>; unprotect_patterns: z.ZodOptional>; check_dependencies: z.ZodDefault>; include_referenced: z.ZodDefault>; pattern_limit: z.ZodDefault; destination: z.ZodOptional>; siem_lens: z.ZodOptional>; monthly_volume_gb: z.ZodOptional; es_pruned: z.ZodOptional; tier_down_plan: z.ZodOptional; service: z.ZodOptional; retention_months: z.ZodDefault; observation_window: z.ZodOptional; timeRange: z.ZodOptional; baseline_window: z.ZodOptional; post_window: z.ZodOptional; commitment_id: z.ZodOptional; contract_type: z.ZodOptional>; effective_ingest_per_gb: z.ZodOptional; current_compute_units: z.ZodOptional; monthly_compute_spend_usd: z.ZodOptional; enforcement_mode: z.ZodOptional>; environment: z.ZodOptional; }; declare const schemaObj: z.ZodObject<{ mode: z.ZodDefault>; proposed_config: z.ZodOptional; cap_bytes_per_window: z.ZodOptional; sample_n: z.ZodOptional; }, "strip", z.ZodTypeAny, { pattern_hash: string; action: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop"; cap_bytes_per_window?: number | undefined; sample_n?: number | undefined; }, { pattern_hash: string; action: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop"; cap_bytes_per_window?: number | undefined; sample_n?: number | undefined; }>, "many">>; target_percent: z.ZodOptional; budget_usd_monthly: z.ZodOptional; budget_gb_monthly: z.ZodOptional; default_action: z.ZodOptional>; retriever_installed: z.ZodDefault>; allow_lossy: z.ZodDefault>; deployment: z.ZodOptional>; exception_services: z.ZodOptional>; unprotect_patterns: z.ZodOptional>; check_dependencies: z.ZodDefault>; include_referenced: z.ZodDefault>; pattern_limit: z.ZodDefault; destination: z.ZodOptional>; siem_lens: z.ZodOptional>; monthly_volume_gb: z.ZodOptional; es_pruned: z.ZodOptional; tier_down_plan: z.ZodOptional; service: z.ZodOptional; retention_months: z.ZodDefault; observation_window: z.ZodOptional; timeRange: z.ZodOptional; baseline_window: z.ZodOptional; post_window: z.ZodOptional; commitment_id: z.ZodOptional; contract_type: z.ZodOptional>; effective_ingest_per_gb: z.ZodOptional; current_compute_units: z.ZodOptional; monthly_compute_spend_usd: z.ZodOptional; enforcement_mode: z.ZodOptional>; environment: z.ZodOptional; }, "strip", z.ZodTypeAny, { mode: "verify" | "forecast"; retriever_installed: boolean; allow_lossy: boolean; check_dependencies: boolean; include_referenced: boolean; pattern_limit: number; retention_months: number; service?: string | undefined; destination?: "datadog" | "splunk" | "elasticsearch" | "clickhouse" | "cloudwatch" | "azure-monitor" | "gcp-logging" | "sumo" | "coralogix" | "elastic-serverless" | undefined; effective_ingest_per_gb?: number | undefined; siem_lens?: SiemId | undefined; timeRange?: string | undefined; environment?: string | undefined; monthly_volume_gb?: number | undefined; commitment_id?: string | undefined; baseline_window?: string | undefined; exception_services?: string[] | undefined; budget_usd_monthly?: number | undefined; budget_gb_monthly?: number | undefined; target_percent?: number | undefined; es_pruned?: boolean | undefined; contract_type?: "committed" | "on_demand" | undefined; proposed_config?: { pattern_hash: string; action: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop"; cap_bytes_per_window?: number | undefined; sample_n?: number | undefined; }[] | undefined; default_action?: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop" | undefined; deployment?: "self_managed" | "managed" | undefined; unprotect_patterns?: string[] | undefined; tier_down_plan?: string | undefined; observation_window?: string | undefined; post_window?: string | undefined; current_compute_units?: number | undefined; monthly_compute_spend_usd?: number | undefined; enforcement_mode?: "engine" | "manual_report" | undefined; }, { mode?: "verify" | "forecast" | undefined; service?: string | undefined; destination?: "datadog" | "splunk" | "elasticsearch" | "clickhouse" | "cloudwatch" | "azure-monitor" | "gcp-logging" | "sumo" | "coralogix" | "elastic-serverless" | undefined; effective_ingest_per_gb?: number | undefined; siem_lens?: SiemId | undefined; timeRange?: string | undefined; environment?: string | undefined; monthly_volume_gb?: number | undefined; commitment_id?: string | undefined; baseline_window?: string | undefined; exception_services?: string[] | undefined; budget_usd_monthly?: number | undefined; budget_gb_monthly?: number | undefined; target_percent?: number | undefined; es_pruned?: boolean | undefined; contract_type?: "committed" | "on_demand" | undefined; proposed_config?: { pattern_hash: string; action: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop"; cap_bytes_per_window?: number | undefined; sample_n?: number | undefined; }[] | undefined; default_action?: "pass" | "sample" | "compact" | "tier_down" | "offload" | "drop" | undefined; retriever_installed?: boolean | undefined; allow_lossy?: boolean | undefined; deployment?: "self_managed" | "managed" | undefined; unprotect_patterns?: string[] | undefined; check_dependencies?: boolean | undefined; include_referenced?: boolean | undefined; pattern_limit?: number | undefined; tier_down_plan?: string | undefined; retention_months?: number | undefined; observation_window?: string | undefined; post_window?: string | undefined; current_compute_units?: number | undefined; monthly_compute_spend_usd?: number | undefined; enforcement_mode?: "engine" | "manual_report" | undefined; }>; export type EstimateSavingsArgs = z.infer; export interface ForecastRow { pattern_hash: string; /** Dominant service for this pattern. User-facing renderers MUST use this * (and symbol_message) on user-visible cells, never the raw pattern_hash. */ service: string; /** Pattern descriptor (symbol_message). Empty string when the metric * backend didn't surface a label value for this hash. */ symbol_message: string; action: Action; bytes_in_monthly: number; bytes_in_monthly_display: string; bytes_saved_monthly: number; bytes_saved_monthly_display: string; avg_event_size_bytes: number; avg_event_size_bytes_display: string; dollars_saved_low: number; dollars_saved_expected: number; dollars_saved_high: number; /** * True when this row's dollars rest on a model rather than on the * destination's own meter. Set on every ClickHouse row: there the bill is * compute, priced from a measured rows-to-CPU curve and an ASSUMED unit * floor. A renderer that prints these figures must carry the word "modeled". */ modeled?: boolean; notes?: string[]; siem_lens?: string; } export interface ForecastResult { mode: 'forecast'; /** Volume projection lens result. `lensed:false` when the env's real volume was used. */ volume_lens: VolumeLensResolution; destination: SiemId; es_pruned?: boolean; service?: string; observation_window: string; target_percent?: number; budget_usd_monthly?: number; budget_gb_monthly?: number; plan_dependencies?: PlanDependencySummary; per_pattern: ForecastRow[]; /** * The ladder-solver plan (product-default path only: target_percent with no * forced default_action). Pattern-first, dollar-denominated, ladder-ordered, * with the keep-everything ceiling and the honest gap. The SAME object * poc_from_local emits, so the two paths render identically. */ plan?: Plan; /** True when per_pattern was sliced to pattern_limit (service-omitted mode). */ per_pattern_truncated: boolean; /** Total number of modeled patterns before the limit slice. */ per_pattern_total_count: number; /** * Per-service rollup. Populated when service is omitted; aggregated from * per_pattern AFTER the solver over the full (pre-slice) result set. */ per_service?: Array<{ service: string; pattern_count: number; bytes_saved_monthly: number; dollars_saved_expected: number; }>; totals: { bytes_in_monthly: number; /** * Env-wide observed monthly bytes — the denominator that * `coverage_of_env_pct` divides into `bytes_in_monthly` to compute * the coverage percent. When `args.service` is set, `bytes_in_monthly` * is the service-scope total and this field is the wider env-wide * total; when no service filter is set the two are equal. Exposed so * the headline coverage % is reconstructible from the envelope * without a hidden side query. */ env_bytes_in_monthly: number; bytes_saved_monthly: number; dollars_low_monthly: number; dollars_expected_monthly: number; dollars_high_monthly: number; annual_projection_expected: number; /** * True when these totals rest on a model rather than on the destination's * own meter. ClickHouse only, today. Renderers must carry the word * "modeled" wherever they print a dollar from a modeled total. */ modeled: boolean; /** Why the totals are modeled, in one line. Present only when modeled. */ modeled_note?: string; /** * The modeled compute saving for the WHOLE estate, on a compute-billed * destination. Rows kept is `1 - (bytes removed by offload/drop/sample) / * env bytes`, taken across every modeled pattern at once, because compute * is a property of the insert stream rather than of any one pattern. * Carries units before and after when the caller supplied * `current_compute_units` or `monthly_compute_spend_usd`, and a fraction * plus a note saying what to supply when it did not. */ compute_saving?: ComputeSavingProjection; /** * Disclose the extrapolation method for annual_projection_expected so * consumers understand it's a naive monthly × 12, NOT a * seasonality-adjusted forecast. Matches the projection_basis pattern * in savings.ts. */ projection_basis: { method: 'linear_extrapolation'; scale_factor: 12; basis_value: 'dollars_expected_monthly'; note: string; }; /** * Per-action breakdown of the forecast totals. Populated by the * executeEstimateSavings path so renderers can surface which * dollar/byte contribution came from which action. * * tier_down.bytes_saved is always 0 (byte volume is unchanged); savings * come from the lower per-GB rate at the cheaper destination tier, which * cuts both the ingest and storage rate. cost.ts computes the full * standard-vs-tier rate delta. */ action_mix?: ActionMix; }; /** * Fraction of TOTAL observed monthly env bytes that this forecast covers. * For a single-pattern proposed_config this is typically small (e.g. 0.01 * = 1% of env bytes). Use coverage_of_proposed_pct for "how complete is * this forecast relative to what was requested". */ coverage_of_env_pct: number; /** * The `_pct` suffix is misleading on * coverage_of_env_pct (the value 0.97 means "97%" but is stored as a * decimal ratio). Sibling `_percent` field stores the true-percent * value (97.27, not 0.9727) so consumers reading the `_pct` naming * convention used by sibling share_pct fields in this envelope (where * share_pct=16.09 means 16.09%) get the consistent reading. */ coverage_of_env_percent: number; /** * @deprecated use coverage_of_env_pct. Kept for backward compatibility. */ coverage_pct: number; /** * For the greedy/target_percent path: fraction of the total candidate bytes * (all observed patterns) that the solver actually modeled. For the * explicit proposed_config path this is always 1.0 (100%) because the * caller specified every row they care about. */ coverage_of_proposed_pct: number; /** Same value × 100. 97.27 means "97.27% of proposed bytes modeled". */ coverage_of_proposed_percent: number; /** * Source of the $/GB rate used to compute dollar projections. * - 'customer_supplied' — caller passed effective_ingest_per_gb * - 'list_price' — from COST_MODEL_BY_DESTINATION.ingest_per_gb */ rate_source: 'list_price' | 'customer_supplied'; /** * Human-readable disclosure of the rate used. Null when customer_supplied * (no caveat needed). Non-null for list_price. */ rate_disclosure: string | null; /** * Provenance of the bytes data — allows an agent to explain why two tools * show different numbers when called with different windows or cohorts. */ bytes_source: { metric: string; observation_window: string; cohort: 'kept'; scope_filter: string; }; /** * Pattern-universe count from the same scope as bytes_source. Null when the * distinctPatternCount query failed or returned no data. */ pattern_count_source: { query: 'distinctPatternCount'; count: number | null; window: string; }; caveats: string[]; } export interface VerifyAttribution { cap_fired_bytes: number; drift_bytes: number; new_patterns_bytes: number; leakage_bytes: number; } export interface VerifyResult { mode: 'verify'; destination: SiemId; commitment_id?: string; baseline_window: string; post_window: string; /** Echo of the honored baseline offset (pre-policy anchor); absent when none/invalid. */ baseline_offset?: string; baseline_bytes: number; post_passed_bytes: number; post_dropped_bytes: number; /** baseline scaled to the same window length as post_window for an apples-to-apples ratio. */ baseline_bytes_scaled: number; delivered_pct: number; delivered_dollars_now: number; delivered_dollars_annual_projection: number; delivered_dollars_at_renewal?: number; attribution: VerifyAttribution; attribution_pct: VerifyAttribution; causal_confidence: number; /** * Source of the $/GB rate used to compute the dollar projections. * - 'customer_supplied' — caller passed `effective_ingest_per_gb` * - 'list_price' — from `getDestinationCostModel().ingest_per_gb` * Propagated by the commitment-report adapter into per-week * `WeeklyVerifyResult.rate_source` (the verifier always has one). */ rate_source: 'list_price' | 'customer_supplied'; /** * Bytes saved by each engine action, joined from the cap-CSV. * Populated only when the caller passed `cap_csv_content`; absent * otherwise. * * Parts-≤-whole invariant: `totalAttributedBytes(per_action_breakdown)` * + `unattributed` ≤ `post_dropped_bytes` after the offload clamp; * see `clampOffloadToResidual` for the residual rule. */ per_action_breakdown?: ActionBytesBuckets; /** * Per-pattern attribution rows. One row per pattern_hash with * non-zero routeState="drop" bytes in the post window. Action is * sourced from the cap-CSV via `buildPatternActionLookup`; rows * with no cap-CSV match are emitted with `action: 'drop'` and * `action_source: 'unattributed'` so the offload clamp + caveat * surfacing can identify them. */ per_pattern_breakdown?: Array<{ pattern_hash: string; /** Human pattern name (TSDB pattern label); falls back to the hash. */ pattern: string; action: Action; delivered_bytes: number; /** * Expected bytes saved at this pattern's cap, scaled to the post * window. Null when the cap-CSV has no row for this hash. */ expected_bytes: number | null; /** * How the action was attributed: * - 'pat_row' — from a `pat:` row in the cap-CSV * - 'container' — from the container-default row * - 'unattributed' — no row matched; action defaulted to 'drop' */ action_source: 'pat_row' | 'container' | 'unattributed'; }>; caveats: string[]; } /** * Action-split + parts-≤-whole guard. Walks the per-hash dropped-bytes * series, attributes each hash's bytes to an action bucket, and clamps * the offload bucket to the residual so the sum never exceeds * `post_dropped_bytes`. Returns BOTH the bucket totals AND the per-pattern rows. * * Action resolution order (canonical as of action-intent migration): * 1. `actionIntentLookup` (from data/action-intent.json) — canonical * 2. Legacy cap-CSV `legacy_action_suffix` on the `pat:` row — backward compat * 3. Legacy cap-CSV `legacy_action_suffix` on the container-default row — backward compat * 4. Unattributed — no intent record and no legacy suffix */ export declare function computeActionSplit(args: { postDroppedByHash: Record; hashToPattern?: Map; capCsvContent?: string | null; actionIntentLookup?: Map; patternToContainer: Map; postDroppedBytes: number; }): { buckets: ActionBytesBuckets; rows: NonNullable; clamped: boolean; }; /** * What to reach for when compact turns out to be a no-op here. Read off the * destination's own lever list rather than hardcoded, because the answer is * not the same everywhere: on Datadog and CloudWatch it is tier_down, on * ClickHouse there is no cheaper in-platform tier modeled and offload is the * lever. Naming a lever the destination does not have sends the reader to a * tool call that refuses one step later. */ export declare function leversInsteadOfCompact(destination: string): Action[]; /** * Thrown by runEstimateForecast when default_action is a no-op on the * destination (e.g., action=compact on datadog where compact_mode=no-op). * executeEstimateSavings catches this and returns a structured refusal * envelope with a next-action suggestion instead of a generic failure. */ export declare class NoOpActionError extends Error { readonly action: string; readonly destination: string; constructor(action: string, destination: string); } export interface RunForecastArgs { destination: SiemId; es_pruned?: boolean; tier_down_plan?: string; service?: string; retention_months: number; proposed_config?: Array<{ pattern_hash: string; action: Action; sample_n?: number; }>; target_percent?: number; budget_usd_monthly?: number; budget_gb_monthly?: number; default_action?: Action; retriever_installed?: boolean; allow_lossy?: boolean; deployment?: 'self_managed' | 'managed'; exception_services?: string[]; unprotect_patterns?: string[]; check_dependencies?: boolean; include_referenced?: boolean; /** PromQL range expression for the observation window. Default 30d. */ observation_window?: string; /** Alias for `observation_window`. observation_window wins when both are set. */ timeRange?: string; /** * Compute-billed destinations only (ClickHouse). The service's CURRENT * compute unit count. Supply it, or `monthly_compute_spend_usd`, to turn the * modeled compute saving in `totals.compute_saving` from a fraction into * dollars. No tool schema exposes this yet; the plumbing lands with the * caller that collects it. */ current_compute_units?: number; /** * Compute-billed destinations only. The service's current monthly compute * spend in dollars, converted to units at the model's unit price when * `current_compute_units` is absent. */ monthly_compute_spend_usd?: number; /** * Maximum per_pattern rows to return. Default 50 when service is omitted; * unlimited when service is set. Totals computed over full result before slice. */ pattern_limit?: number; /** * Customer-supplied ingest $/GB override. When provided, dollar projections * use this rate instead of the destination list price (same as the verify path). * Surfaces as rate_source='customer_supplied' in the result. */ effective_ingest_per_gb?: number; /** * SIEM lens active: skip env-configured rates (they belong to the actual * destination). FED BY THE EXECUTOR from `lensRes.lensed` (executeEstimateSavings, * ~line 1818 -> 2013), NOT from the public estimate_savings arg. It is read * ONLY at the forecast resolveRate site (~1026). A future refactor that * inlines runEstimateForecast must keep this assignment, or the rate stops * following the SIEM lens. This is the SIEM lens; the VOLUME lens lives in a * separate object (result.volume_lens.lensed) — do not conflate. */ lensed?: boolean; /** * Volume projection lens: model the env at this monthly volume (decimal * GB/month) instead of its measured volume. Scales the byte basis by a * uniform factor (per-pattern shares + coverage unchanged). Omit for the * real measured volume. configure-engine never sets it. */ monthly_volume_gb?: number; } /** * Pure-function entry: callers (configure-engine) can run a forecast * inline against the same env they already resolved. Throws on missing * required args; lets the caller wrap into an envelope. */ export declare function runEstimateForecast(args: RunForecastArgs, env: EnvConfig): Promise; export interface RunVerifyArgs { destination: SiemId; es_pruned?: boolean; service?: string; baseline_window: string; post_window: string; commitment_id?: string; contract_type?: 'committed' | 'on_demand'; effective_ingest_per_gb?: number; /** * Optional cap-CSV content (verbatim string from the customer gitops * repo at `lookup_path`). When present alongside `action_intent_content`, * the verify run can also supply per-pattern byte-cap context for the * attribution rows. For action routing on the action-intent path, see * `action_intent_content`. * * Legacy rows that still contain a `:` suffix are silently * stripped; the suffix is stored in `legacy_action_suffix` on each row * but NOT used for action routing. If `action_intent_content` is also * absent but `cap_csv_content` is present with legacy suffixes, the * split will fall back to those legacy values (backward compat). */ cap_csv_content?: string | null; /** * Optional action-intent.json content (verbatim JSON from the customer * gitops repo at `data/action-intent.json`). When present, this is the * canonical source for per-pattern action attribution. Takes precedence * over any legacy `:action` suffix that may still be in the cap CSV. * When absent, the verify run falls back to cap-CSV legacy suffixes (if * present) or marks all dropped bytes as `unattributed`. */ action_intent_content?: string | null; /** * Label name carrying the container value on the engine's metrics. * Defaults to `k8s_container` (matches configure-engine.ts's PromQL * shape). Exposed so a customer with a relabeled aggregator can pass * the right label without us hard-coding the default in two places. */ container_label?: string; /** * SIEM lens active: skip env-configured rates (they belong to the actual * destination). FED BY THE EXECUTOR from `lensRes.lensed` (executeEstimateSavings, * ~line 1818 -> 2198), NOT from the public estimate_savings arg. It is read * ONLY at the verify resolveRate site (~1638). A future refactor that inlines * runEstimateVerify must keep this assignment, or the rate stops following the * SIEM lens. This is the SIEM lens; the VOLUME lens is a separate object — do * not conflate. */ lensed?: boolean; /** * PromQL duration (e.g. "30d") shifting the BASELINE queries back in time * via the `offset` modifier, so the baseline measures a window that ENDS * `baseline_offset` ago instead of trailing to "now". * * Why it exists: without it, both baseline and post `increase(...[w])` * vectors trail from "now" over an overlapping range, so the baseline is * the policy's own post-deploy output. delivered_pct then collapses to 0 * algebraically (the degenerate-windowing caveat fires). Anchoring the * baseline before the policy went live (`commitment.started_at`) is exactly * the fix the caveat prescribes; the commitment runner sets this to the * age of the commitment so the baseline window lands in pre-policy data. * * Must be a bare PromQL range duration (`^\d+(ms|s|m|h|d|w|y)$`); any other * value is ignored (no offset applied) and a caveat is pushed. The $ view * is unaffected either way; it reads post-window dropped bytes directly. */ baseline_offset?: string; } /** * Pure-function entry for verify. Queries the engine's routeState label * (TenXSummary) to attribute the delta. */ export declare function runEstimateVerify(args: RunVerifyArgs, env: EnvConfig): Promise; export declare function executeEstimateSavings(args: EstimateSavingsArgs, env: EnvConfig): Promise; export interface ActionMixBucket { dollars: number; bytes_saved: number; pattern_count: number; } export interface ActionMix { pass: ActionMixBucket; sample: ActionMixBucket; compact: ActionMixBucket; tier_down: ActionMixBucket; offload: ActionMixBucket; drop: ActionMixBucket; } export declare function buildActionMix(rows: ForecastRow[]): ActionMix; export {};