/** * analyzeToolCatalog — the tool-catalog confusability lint * (RFC-002 block C1, the adoption front door). * * Pattern: policy layer over `pairwiseSimilarity` (influence-core) — the * geometry is computed there; thresholds, verdicts, hints and * the structural rule pack live here. Everything is consumer- * injectable with our defaults (the plug-and-play meta-pattern). * Role: `src/lib/tool-lint/`. ZERO stack buy-in — plain * `{ name, description?, inputSchema? }[]` in, report out. * `catalogFromTools` adapts the library's own `Tool[]`; * `coerceCatalog` (cli.ts) normalizes OpenAI/Anthropic/MCP * shapes. * * ## What is embedded (and why) * * `confusabilityText(tool)` = tokenized name + ': ' + description. The * model differentiates tools by name AND description together, so two * tools with near-identical names and overlapping descriptions ARE the * confusability case (`get_fcns_database` vs `influx_get_fcns_database`) * — embedding only the prose would miss the name signal. * * ## Calibration (RFC-002 §3 — read this before trusting verdicts) * * Absolute cosine ranges are PER-EMBEDDER. The default threshold (0.85) * is a starting point for real sentence embedders. The test/demo * `mockEmbedder` (character-frequency) compresses unrelated prose into * ~0.85–0.97 — with it, use `MOCK_EMBEDDER_CALIBRATION` and trust only * the RELATIVE ordering in `report.similarity.ranked` (the acceptance * fixtures assert ordering, never absolute scores). */ import type { Tool } from '../../core/tools.js'; import type { AnalyzeToolCatalogOptions, CatalogTool, ToolCatalogReport } from './types.js'; /** Default `confusabilityThreshold` — a starting point for REAL sentence * embedders (unrelated tool descriptions typically land 0.3–0.7). * Calibrate per embedder; meaningless for the mock (see below). */ export declare const DEFAULT_CONFUSABILITY_THRESHOLD = 0.85; /** Default `watchBand` below the threshold. */ export declare const DEFAULT_WATCH_BAND = 0.05; /** * Threshold/band calibrated for the char-frequency `mockEmbedder` on * realistic tool prose (seed corpus: the Neo SAN catalog). The mock * compresses unrelated descriptions into ~0.85–0.97 cosine, so expect * false positives even at 0.94 — with the mock, the RELATIVE ordering * of `report.similarity.ranked` is the trustworthy signal; absolute * verdicts are only honest with a real embedder + per-embedder * calibration. */ export declare const MOCK_EMBEDDER_CALIBRATION: Readonly<{ confusabilityThreshold: 0.94; watchBand: 0.02; }>; /** * Adapt the library's `Tool[]` (from `defineTool` / `Agent.tool`) to the * lint's plain catalog shape. Trivial on purpose: `Tool.schema` already * IS `{ name, description, inputSchema }`. */ export declare function catalogFromTools(tools: readonly Tool[]): readonly CatalogTool[]; /** * The text the confusability analysis embeds for one tool: the name with * `_`/`-`/camelCase boundaries opened into words, then the description. * Exported so consumers can reproduce or replace the construction. */ export declare function confusabilityText(tool: CatalogTool): string; /** * Lint a tool catalog: pairwise confusability over what the model reads * (when an embedder is supplied) + the structural rule pack. Returns a * report whose `ok` is the CI gate. * * Duplicate tool names are themselves reported as structural errors * (rule `duplicate-name`, built-in precondition — a catalog where two * tools share a name is broken before any similarity question); the * duplicates are dropped from the similarity analysis (first one wins). */ export declare function analyzeToolCatalog(tools: readonly CatalogTool[], options?: AnalyzeToolCatalogOptions): Promise; /** * Suggest the DIFFERENTIATING AXIS for a flagged pair. Heuristic: when * the names are near-twins (≤2 distinct tokens), the qualifier IS the * axis — the descriptions must say when to choose each variant. When the * names differ, surface the few description terms each tool does NOT * share, as the place to anchor an explicit choice condition. */ export declare function differentiationHint(a: CatalogTool, b: CatalogTool): string; //# sourceMappingURL=analyze.d.ts.map