/** * ApiSpineEngineProvider — one grounded-search engine's `AiVisibilityProvider` * (in-house-ai-visibility, Sprint 2, wired in Sprint 4; * arch-20260717-in-house-oss-ai-visibility-architecture.md:44,84-97,278). * * Mirrors `DamcrawlerSerpProvider`'s injected-deps + `readonly name`/ * `readonly estCost...` shape (`./damcrawler-serp-provider.ts:69-101`), but * the injected transport is a Sprint-1 `GroundedSearchClient` (not * damcrawler). There is still no egress gate here — the transport's own * network call is ungated (that remains the ADAPTER's/factory's job) — but * as of Sprint 4 this class DOES own two boundary responsibilities per * ADR-11: (1) sanitize every piece of grounded free-text (`answerText` + * each candidate citation url) via the injected `ContentSanitizer` BEFORE * the row is built, and (2) verify each sanitized candidate url via the * injected `CitationVerifier` (gated by the `site-crawl` axis inside the * verifier itself) and retain ONLY `live === true` urls in `row.sourceUrls` * — an unverifiable citation NEVER reaches a row (sc-4-2). * * `probe()` runs `samplesPerPrompt` (N) independent grounded-search samples * per prompt and emits ONE raw `AiVisibilityRow` per real observation — * never a pre-aggregate ("Every arm emits raw per-(prompt,provider,sample) * AiVisibilityRows ... so API and scrape signal are structurally * unmixable", architecture:44). Each row is stamped with `this.name` * (`= client.engine`), so a future multiplexer can tell which engine * produced which observation without any additional bookkeeping. * * Cost accounting (ADR-3, `arch-20260717-in-house-oss-ai-visibility-adr-3.md`): * the LOCKED `AiVisibilityAdapter` books `estCostUsdPerPrompt * prompts.length` * (`ai-visibility-adapter.ts:114`) — it has no notion of N. So N MUST be * baked into `estCostUsdPerPrompt` here: `estCostUsdPerPrompt = perCallUsd * * samplesPerPrompt`. Getting this wrong under-books the USD ceiling. * * Sample-failure contract (sc-2-4, architecture:278 "Sample throws => * dropped (wider CI); all fail => abstain, nothing booked"): a single * rejecting sample is caught and `continue`d — it never throws out of the * loop, is never mislabeled, and never fabricates a citation. If EVERY * attempted sample across every prompt rejects, `probe()` throws instead of * returning `[]` — the (not-yet-wired) adapter converts any probe throw * into `abstain` + books nothing (`ai-visibility-adapter.ts:141-143`), which * is exactly the "all fail => abstain, nothing booked" outcome. Calling * `probe()` with zero prompts or `samplesPerPrompt <= 0` attempts nothing * and returns `[]` without throwing (there is no failure to report). This * contract is unaffected by the Sprint-4 sanitize/verify additions: verifier * errors stay INSIDE `probe` (fail-closed, `live:false`) and never throw * out of the sample loop — so cost accounting in the adapter (which books * only after a successful `probe()`) is unaffected by a verification * failure. */ import type { AiVisibilityProvider } from "./ai-visibility-adapter.js"; import type { AiVisibilityRow } from "../data-source.js"; import type { GroundedEngine, GroundedSearchClient } from "../../providers/grounded-search.js"; import type { MentionCitationExtractor } from "./mention-citation-extractor.js"; import type { CitationVerifier } from "./citation-verifier.js"; import type { ContentSanitizer } from "../content-sanitizer.js"; export declare class ApiSpineEngineProvider implements AiVisibilityProvider { private readonly client; private readonly extractor; private readonly samplesPerPrompt; private readonly verifier; private readonly sanitizer; readonly name: GroundedEngine; readonly estCostUsdPerPrompt: number; constructor(client: GroundedSearchClient, extractor: MentionCitationExtractor, samplesPerPrompt: number, perCallUsd: number, verifier: CitationVerifier, sanitizer: ContentSanitizer); probe(target: string, prompts: string[], locale?: string): Promise; } //# sourceMappingURL=api-spine-provider.d.ts.map