{
  "schema_version": 1,
  "generated_at": "2026-08-06T08:25:46.798Z",
  "capabilities": [
    {
      "id": "managed/clover",
      "name": "clover",
      "title": "Clover",
      "description": "All of Clover in one subscription: 62 semantic SQL operators — 35 calibrated ML specialists, 22 LLM operators, structured document parsing, forecasting with business drivers, and CPU-side time-series anomaly/imputation/similarity, plus safe web extraction and cited research. ML and extraction operators are unmetered on every tier; lanes buy LLM generation speed.",
      "tags": [
        "managed",
        "clover",
        "bundle",
        "specialists",
        "llm",
        "web",
        "documents",
        "lanes",
        "verified"
      ],
      "kind": "managed",
      "catalog_visibility": "public",
      "device": "api",
      "operators": [
        "clover_means",
        "clover_relevance",
        "clover_similar",
        "clover_embed",
        "clover_entails",
        "clover_contradicts",
        "clover_sentiment",
        "clover_sentiment_score",
        "clover_classify",
        "clover_classify_scores",
        "clover_nli",
        "clover_toxic",
        "clover_moderate",
        "clover_language",
        "clover_language_info",
        "clover_extract",
        "clover_pii",
        "clover_ocr",
        "clover_document_parse",
        "clover_transcribe",
        "clover_forecast",
        "clover_forecast_drivers",
        "clover_series_anomalies",
        "clover_series_impute",
        "clover_series_embed",
        "clover_series_similarity",
        "clover_image_similar",
        "clover_image_embed",
        "clover_cluster",
        "clover_fit",
        "clover_predict",
        "clover_explain",
        "clover_anomaly_fit",
        "clover_anomaly_score",
        "clover_relations",
        "clover_llm_ask",
        "clover_llm_apply",
        "clover_llm_extract",
        "clover_llm_translate",
        "clover_llm_anonymize",
        "clover_llm_canonical",
        "clover_llm_fix",
        "clover_llm_date",
        "clover_llm_means",
        "clover_llm_implies",
        "clover_llm_contradicts",
        "clover_llm_score",
        "clover_llm_supports",
        "clover_llm_valid",
        "clover_llm_steelman",
        "clover_llm_fallacies",
        "clover_llm_same_entity",
        "clover_llm_merge_records",
        "clover_llm_timeline",
        "clover_llm_consensus",
        "clover_llm_make_operator",
        "clover_triples",
        "clover_web_scrape",
        "clover_web_markdown",
        "clover_web_research",
        "clover_web_research_deep",
        "clover_web_watch"
      ],
      "backend_name": "embed",
      "capability_manifest": {
        "api_version": "rvbbit.capability/v1",
        "kind": "managed",
        "name": "clover",
        "title": "Clover",
        "description": "All of Clover in one subscription: 62 semantic SQL operators — 35 calibrated ML specialists (text, structured documents, audio, images, tabular AutoML, anomaly detection, imputation, forecasting with business drivers, time-series similarity, clustering, and SHAP explanations), 22 LLM operators for fuzzy judgment and structured extraction, safe web extraction, plus cited research with tenant-scoped evidence memory, deep gap closure, and change watches. ML and extraction operators are unmetered on every tier; lanes buy LLM generation speed.",
        "tags": [
          "managed",
          "clover",
          "bundle",
          "specialists",
          "llm",
          "web",
          "documents",
          "lanes",
          "verified"
        ],
        "operators": [
          {
            "name": "clover_means",
            "description": "TRUE if text semantically matches a criterion (cross-encoder)"
          },
          {
            "name": "clover_relevance",
            "description": "Relevance score 0..1 of text to criterion"
          },
          {
            "name": "clover_similar",
            "description": "Embedding cosine similarity of two texts"
          },
          {
            "name": "clover_embed",
            "description": "Reusable Arctic text embedding vector for KNN, similarity and clustering"
          },
          {
            "name": "clover_entails",
            "description": "TRUE if premise entails hypothesis (NLI)"
          },
          {
            "name": "clover_contradicts",
            "description": "TRUE if two statements contradict (NLI 3-class)"
          },
          {
            "name": "clover_sentiment",
            "description": "Sentiment label + score for a text"
          },
          {
            "name": "clover_sentiment_score",
            "description": "Continuous sentiment in [-1, 1]"
          },
          {
            "name": "clover_classify",
            "description": "Zero-shot classification over your labels"
          },
          {
            "name": "clover_classify_scores",
            "description": "Zero-shot classification with the winning label and every candidate score"
          },
          {
            "name": "clover_nli",
            "description": "Full 3-way entailment, neutral, and contradiction scores"
          },
          {
            "name": "clover_toxic",
            "description": "TRUE if text is toxic"
          },
          {
            "name": "clover_moderate",
            "description": "Full moderation category scores"
          },
          {
            "name": "clover_language",
            "description": "ISO language code of text"
          },
          {
            "name": "clover_language_info",
            "description": "Language code plus confidence for thresholded routing"
          },
          {
            "name": "clover_extract",
            "description": "Entity extraction (GLiNER) over your types"
          },
          {
            "name": "clover_pii",
            "description": "PII detection preset (person, email, phone, ssn, ...)"
          },
          {
            "name": "clover_ocr",
            "description": "OCR a document to plain text through the structured Granite-Docling parser"
          },
          {
            "description": "Parse a document into Markdown, typed blocks, tables, cells, hierarchy and source geometry",
            "name": "clover_document_parse"
          },
          {
            "name": "clover_transcribe",
            "description": "Transcribe audio to text (Whisper large-v3-turbo)"
          },
          {
            "name": "clover_forecast",
            "description": "Forecast a numeric series N steps ahead — median + quantile bands"
          },
          {
            "description": "Forecast named related series with historical and known-future business drivers",
            "name": "clover_forecast_drivers"
          },
          {
            "description": "Score a long time series for anomalies with CPU-side TSPulse",
            "name": "clover_series_anomalies"
          },
          {
            "description": "Fill missing points in a time series with TSPulse reconstruction",
            "name": "clover_series_impute"
          },
          {
            "description": "Create a semantic TSPulse embedding for the most recent 512 points",
            "name": "clover_series_embed"
          },
          {
            "description": "Compare two time-series shapes with TSPulse semantic similarity",
            "name": "clover_series_similarity"
          },
          {
            "name": "clover_image_similar",
            "description": "Similarity of two images, or an image and a text description"
          },
          {
            "name": "clover_image_embed",
            "description": "Reusable SigLIP2 embedding for an image or text description"
          },
          {
            "name": "clover_cluster",
            "description": "Cluster a JSON array of texts into assignments and representative groups"
          },
          {
            "name": "clover_fit",
            "description": "Fit a TabPFN model on tabular rows — the fitted model is returned to you"
          },
          {
            "name": "clover_predict",
            "description": "Predict with a clover_fit model — classifications or regressions"
          },
          {
            "name": "clover_explain",
            "description": "SHAP feature attributions for a fitted TabPFN or anomaly model"
          },
          {
            "name": "clover_anomaly_fit",
            "description": "Fit an anomaly detector on numeric rows (client-held model)"
          },
          {
            "name": "clover_anomaly_score",
            "description": "Score rows for anomalousness against a fitted detector"
          },
          {
            "name": "clover_relations",
            "description": "Extract (subject, predicate, object) relation triples from text"
          },
          {
            "name": "clover_llm_ask",
            "description": "One-shot ask against the hosted generalist"
          },
          {
            "name": "clover_llm_apply",
            "description": "Apply an instruction/question to a text — answers only from the text"
          },
          {
            "name": "clover_llm_extract",
            "description": "Freeform text to a JSON object per a schema you describe"
          },
          {
            "name": "clover_llm_translate",
            "description": "Translate to any language — returns only the translation"
          },
          {
            "name": "clover_llm_anonymize",
            "description": "Rewrite text with all PII redacted ([NAME], [EMAIL], ...)"
          },
          {
            "name": "clover_llm_canonical",
            "description": "Canonical form of a value (NYC -> New York City)"
          },
          {
            "name": "clover_llm_fix",
            "description": "Repair malformed values given a type hint (gmial.com -> gmail.com)"
          },
          {
            "name": "clover_llm_date",
            "description": "Messy text to ISO 8601 date, or NULL"
          },
          {
            "name": "clover_llm_means",
            "description": "TRUE if text semantically matches a criterion — LLM-judged for inputs that need thought"
          },
          {
            "name": "clover_llm_implies",
            "description": "TRUE if premise implies conclusion — incl. the quantifier logic fast NLI misses"
          },
          {
            "name": "clover_llm_contradicts",
            "description": "TRUE if two texts oppose each other on the same subject"
          },
          {
            "name": "clover_llm_score",
            "description": "Judge text against any English-phrased criterion, 0-1"
          },
          {
            "name": "clover_llm_supports",
            "description": "How strongly evidence supports a claim, 0-1"
          },
          {
            "name": "clover_llm_valid",
            "description": "TRUE if a value satisfies an English-phrased rule"
          },
          {
            "name": "clover_llm_steelman",
            "description": "Rewrite an argument in its strongest, most defensible form"
          },
          {
            "name": "clover_llm_fallacies",
            "description": "Detect logical fallacies — JSON array of {fallacy, explanation}"
          },
          {
            "name": "clover_llm_same_entity",
            "description": "TRUE if two values identify the same real-world entity"
          },
          {
            "name": "clover_llm_merge_records",
            "description": "Merge duplicate JSON records into one canonical golden record"
          },
          {
            "name": "clover_llm_timeline",
            "description": "Extract a normalized chronological event timeline from text"
          },
          {
            "name": "clover_llm_consensus",
            "description": "Synthesize the shared consensus across a JSON array of findings"
          },
          {
            "name": "clover_llm_make_operator",
            "description": "The operator operator: describe an operator in plain English → drafts it, creates it under a temp name, runs generated tests, self-corrects, then promotes it with its tests attached"
          },
          {
            "name": "clover_triples",
            "description": "Extract knowledge-graph triples from text as strict JSON — same contract as the built-in rvbbit.triples, so every KG surface (data_crawl, Document Brain, Scry) can run on it"
          },
          {
            "name": "clover_web_scrape",
            "description": "Fetch a public HTTP(S) page or document and return Markdown, metadata, provenance, and extraction diagnostics"
          },
          {
            "name": "clover_web_markdown",
            "description": "Fetch a public HTTP(S) page or document and return its cleaned Markdown"
          },
          {
            "description": "Research the public web with cited claims, typed knowledge, tenant-scoped snapshots, and exact evidence lineage",
            "name": "clover_web_research"
          },
          {
            "description": "Research with one bounded follow-the-evidence pass to close material gaps",
            "name": "clover_web_research_deep"
          },
          {
            "description": "Refresh stable public URLs, reuse unchanged evidence without another synthesis, and report source and claim changes",
            "name": "clover_web_watch"
          }
        ],
        "managed": {
          "vendor": "rvbbit.ai",
          "status": "available",
          "entitlement": "clover",
          "key_env": "RVBBIT_CLOVER_KEY",
          "pricing": {
            "monthly_usd": 299,
            "from": true,
            "note": "a lane = one LLM generation in flight — ML operators are unmetered on every tier",
            "tiers": [
              {
                "name": "Free",
                "lanes": 1,
                "monthly_usd": 0,
                "checkout_url": "https://rvbbit.ai/buy/clover-free"
              },
              {
                "name": "Pro",
                "lanes": 5,
                "monthly_usd": 299,
                "checkout_url": "https://rvbbit.ai/buy/clover-pro"
              },
              {
                "name": "Scale",
                "lanes": 25,
                "monthly_usd": 999,
                "checkout_url": "https://rvbbit.ai/buy/clover-scale"
              },
              {
                "name": "Custom",
                "lanes": null,
                "monthly_usd": null,
                "contact_email": "ryan@rvbbit.ai",
                "note": "Need more lanes, a dedicated box, or a private model set? Email us."
              }
            ]
          },
          "endpoint": {
            "base_url": "http://clover.rvbb.it:8090"
          },
          "verified": {
            "tests": 107,
            "passed": 106,
            "regime": "clover-v1.2 @ pg_rvbbit 4.0.5",
            "battery_date": "2026-07-16",
            "note": "50-operator catalog: 49 registry operators carry embedded cases; clover_llm_make_operator is a guarded PL/pgSQL workflow. One known-red NLI entailment case remains tracked openly."
          },
          "models": [
            {
              "slot": "embed",
              "model": "Snowflake/snowflake-arctic-embed-l-v2.0",
              "version": "clover-v1"
            },
            {
              "slot": "rerank",
              "model": "BAAI/bge-reranker-v2-m3",
              "version": "clover-v1"
            },
            {
              "slot": "sentiment",
              "model": "cardiffnlp/twitter-xlm-roberta-base-sentiment",
              "version": "clover-v1.0"
            },
            {
              "slot": "nli",
              "model": "MoritzLaurer/deberta-v3-large-zeroshot-v2.0",
              "version": "clover-v1"
            },
            {
              "slot": "nli3",
              "model": "MoritzLaurer/deberta-v3-large-mnli-fever-anli-ling-wanli",
              "version": "clover-v1"
            },
            {
              "slot": "toxicity",
              "model": "unitary/toxic-bert",
              "version": "clover-v1"
            },
            {
              "slot": "language",
              "model": "papluca/xlm-roberta-base-language-detection",
              "version": "clover-v1"
            },
            {
              "slot": "extract",
              "model": "urchade/gliner_large-v2.1",
              "version": "clover-v1"
            },
            {
              "slot": "ocr",
              "model": "ibm-granite/granite-docling-258M",
              "version": "clover-v2"
            },
            {
              "slot": "transcribe",
              "model": "openai/whisper-large-v3-turbo",
              "version": "clover-v1"
            },
            {
              "slot": "forecast",
              "model": "amazon/chronos-2",
              "version": "clover-v2"
            },
            {
              "slot": "timeseries_understanding",
              "model": "ibm-granite/granite-timeseries-tspulse-r1",
              "version": "clover-v2-cpu"
            },
            {
              "slot": "image_embed",
              "model": "google/siglip2-so400m-patch16-384",
              "version": "clover-v1"
            },
            {
              "slot": "tabular_classifier",
              "model": "Prior-Labs/TabPFN-v2-clf",
              "version": "clover-v1"
            },
            {
              "slot": "tabular_regressor",
              "model": "Prior-Labs/TabPFN-v2-reg",
              "version": "clover-v1"
            },
            {
              "slot": "anomaly",
              "model": "scikit-learn/IsolationForest (fit per customer model)",
              "version": "clover-v1"
            },
            {
              "slot": "relations",
              "model": "Babelscape/rebel-large",
              "version": "clover-v1"
            },
            {
              "slot": "llm",
              "model": "OpenRouter ~deepseek/deepseek-v4-flash-latest (13B active / 284B total)",
              "version": "clover-llm-v2"
            },
            {
              "model": "firecrawl/html-extractor + firecrawl/anydoc",
              "slot": "web_scrape",
              "version": "clover-web-v0.2"
            },
            {
              "model": "google/gemma-4-31b-it + OpenRouter Exa + Clover Web + tenant-scoped evidence memory",
              "slot": "web_research",
              "version": "clover-research-v0.2"
            }
          ],
          "install": {
            "sql": [
              "SELECT rvbbit.register_backend('embed',     'http://clover.rvbb.it:8090/b/embed/predict',     'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('sentiment', 'http://clover.rvbb.it:8090/b/sentiment/predict', 'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('rerank',    'http://clover.rvbb.it:8090/b/rerank/predict',    'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('web_scrape', 'http://clover.rvbb.it:8090/b/web_scrape/predict', 'rvbbit', 8, 4, 60000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('web_research', 'http://clover.rvbb.it:8090/b/web_research/predict', 'rvbbit', 2, 1, 180000, 'RVBBIT_CLOVER_KEY');",
              "DELETE FROM rvbbit.embedding_cache WHERE specialist = 'embed';",
              "SELECT rvbbit.reload_backends();",
              "SELECT rvbbit.create_operator('clover_sentiment', ARRAY['t'], 'text',\n  op_description := 'Clover-ML: sentiment {score,label} for a text (hosted twitter-roberta)',\n  op_steps := '[{\"name\":\"s\",\"kind\":\"specialist\",\"specialist\":\"sentiment\",\"inputs\":{\"text\":\"{{t}}\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_relevance', ARRAY['t','criterion'], 'float8',\n  op_description := 'Clover-ML: cross-encoder relevance of t to criterion, 0..1 (hosted bge-reranker-v2-m3)',\n  op_steps := '[{\"name\":\"r\",\"kind\":\"specialist\",\"specialist\":\"rerank\",\"inputs\":{\"query\":\"{{criterion}}\",\"text\":\"{{t}}\"}}]'::jsonb);",
              "SELECT rvbbit.register_backend('nli',      'http://clover.rvbb.it:8090/b/nli/predict',      'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('nli3',     'http://clover.rvbb.it:8090/b/nli3/predict',     'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('classify', 'http://clover.rvbb.it:8090/b/classify/predict', 'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('toxicity', 'http://clover.rvbb.it:8090/b/toxicity/predict', 'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('language', 'http://clover.rvbb.it:8090/b/language/predict', 'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('extract',  'http://clover.rvbb.it:8090/b/extract/predict',  'rvbbit', 32, 25, 30000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.reload_backends();",
              "SELECT rvbbit.create_operator('clover_means', ARRAY['t','criterion'], 'bool',\n  op_description := 'Clover-ML: TRUE if t semantically matches criterion (cross-encoder, threshold 0.5)',\n  op_steps := '[\n    {\"name\":\"r\",\"kind\":\"specialist\",\"specialist\":\"rerank\",\"inputs\":{\"query\":\"{{criterion}}\",\"text\":\"{{t}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"number_gte\",\"inputs\":{\"value\":\"{{steps.r.output}}\",\"threshold\":0.5}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_entails', ARRAY['premise','hypothesis'], 'bool',\n  op_description := 'Clover-ML: TRUE if premise entails hypothesis (NLI 2-class)',\n  op_steps := '[\n    {\"name\":\"n\",\"kind\":\"specialist\",\"specialist\":\"nli\",\"inputs\":{\"premise\":\"{{premise}}\",\"hypothesis\":\"{{hypothesis}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"number_gte\",\"inputs\":{\"value\":\"{{steps.n.output.scores.entailment}}\",\"threshold\":0.5}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_contradicts', ARRAY['a','b'], 'bool',\n  op_description := 'Clover-ML: TRUE if a and b contradict (NLI 3-class)',\n  op_steps := '[\n    {\"name\":\"n\",\"kind\":\"specialist\",\"specialist\":\"nli3\",\"inputs\":{\"premise\":\"{{a}}\",\"hypothesis\":\"{{b}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"number_gte\",\"inputs\":{\"value\":\"{{steps.n.output.scores.contradiction}}\",\"threshold\":0.5}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_sentiment_score', ARRAY['t'], 'float8', op_parser := 'strip',\n  op_description := 'Clover-ML: continuous sentiment in [-1,1]',\n  op_steps := '[\n    {\"name\":\"s\",\"kind\":\"specialist\",\"specialist\":\"sentiment\",\"inputs\":{\"text\":\"{{t}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.s.output}}\",\"path\":\"score\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_classify', ARRAY['t','labels'], 'text',\n  op_description := 'Clover-ML: zero-shot classification — top label from comma-separated candidates',\n  op_steps := '[\n    {\"name\":\"c\",\"kind\":\"specialist\",\"specialist\":\"classify\",\"inputs\":{\"text\":\"{{t}}\",\"labels\":\"{{labels}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.c.output}}\",\"path\":\"label\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_toxic', ARRAY['t'], 'bool',\n  op_description := 'Clover-ML: TRUE if text is toxic (toxic-bert, threshold 0.5)',\n  op_steps := '[\n    {\"name\":\"x\",\"kind\":\"specialist\",\"specialist\":\"toxicity\",\"inputs\":{\"text\":\"{{t}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.x.output}}\",\"path\":\"toxic\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_language', ARRAY['t'], 'text',\n  op_description := 'Clover-ML: ISO language code of text',\n  op_steps := '[\n    {\"name\":\"l\",\"kind\":\"specialist\",\"specialist\":\"language\",\"inputs\":{\"text\":\"{{t}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.l.output}}\",\"path\":\"language\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_extract', ARRAY['t','entity_types'], 'jsonb',\n  op_description := 'Clover-ML: GLiNER entity extraction — types is comma-separated',\n  op_steps := '[\n    {\"name\":\"e\",\"kind\":\"specialist\",\"specialist\":\"extract\",\"inputs\":{\"text\":\"{{t}}\",\"labels\":\"{{entity_types}}\"}}\n  ]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"dessert+\", \"sql\": \"SELECT rvbbit.clover_means(''apple pie recipe'',''dessert recipes'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"LarSQL heritage case\"}, {\"name\": \"sports-\", \"sql\": \"SELECT rvbbit.clover_means(''basketball game results'',''cooking recipes'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"delivery+\", \"sql\": \"SELECT rvbbit.clover_means(''customer complaint about shipping delay'',''delivery issues'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"energy+\", \"sql\": \"SELECT rvbbit.clover_means(''renewable energy investments'',''clean energy'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_means';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"close\", \"sql\": \"SELECT rvbbit.clover_relevance(''quick sql engine'',''fast database'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.8\"}, \"description\": \"\"}, {\"name\": \"far\", \"sql\": \"SELECT rvbbit.clover_relevance(''a nice sandwich'',''fast database'')\", \"expect\": {\"type\": \"max\", \"value\": \"0.3\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_relevance';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"paid+\", \"sql\": \"SELECT rvbbit.clover_entails(''The invoice was paid on March 3rd'',''The invoice was paid'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"overdue-\", \"sql\": \"SELECT rvbbit.clover_entails(''The invoice was paid on March 3rd'',''The invoice is overdue'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"subset+\", \"sql\": \"SELECT rvbbit.clover_entails(''Several employees received a bonus in December'',''Some employees received a bonus'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"existence-explicit entailment\"}, {\"name\": \"unrelated-\", \"sql\": \"SELECT rvbbit.clover_entails(''The cat sat on the mat'',''The stock market rose today'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_entails';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"cancelled+\", \"sql\": \"SELECT rvbbit.clover_contradicts(''The meeting is at 9am'',''The meeting is cancelled'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"morning-\", \"sql\": \"SELECT rvbbit.clover_contradicts(''The meeting is at 9am'',''The meeting starts in the morning'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"open-closed+\", \"sql\": \"SELECT rvbbit.clover_contradicts(''The store is open until 9pm'',''The store closed at noon'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"neutral-\", \"sql\": \"SELECT rvbbit.clover_contradicts(''The report covers Q3 revenue'',''The office has new chairs'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_contradicts';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"love\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''i absolutely love this'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"best_purchase\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''best purchase I have made all year'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"support_good\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''the support team resolved everything quickly, great experience'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"astonish_fast\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''this warehouse is astonishingly fast'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"as_advertised\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''works exactly as advertised'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"delighted\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''delighted with the upgrade'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"recommend\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''10/10 would recommend'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.2\"}, \"description\": \"\"}, {\"name\": \"disappointing\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''utterly disappointing'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"crashes\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''the app crashes every time I open it'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"worst_service\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''worst customer service imaginable'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"waste\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''total waste of money'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"crushed_box\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''shipping took forever and the box arrived crushed'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"regret\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''i regret buying this'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"slower\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''the update made everything slower'')\", \"expect\": {\"type\": \"max\", \"value\": \"-0.2\"}, \"description\": \"\"}, {\"name\": \"neutral_lo\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''the invoice was sent on tuesday'')\", \"expect\": {\"type\": \"min\", \"value\": \"-0.4\"}, \"description\": \"\"}, {\"name\": \"neutral_hi\", \"sql\": \"SELECT rvbbit.clover_sentiment_score(''the invoice was sent on tuesday'')\", \"expect\": {\"type\": \"max\", \"value\": \"0.4\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_sentiment_score';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"label+\", \"sql\": \"SELECT rvbbit.clover_sentiment(''i love this database'')\", \"expect\": {\"type\": \"contains\", \"value\": \"positive\"}, \"description\": \"\"}, {\"name\": \"label-\", \"sql\": \"SELECT rvbbit.clover_sentiment(''terrible experience'')\", \"expect\": {\"type\": \"contains\", \"value\": \"negative\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_sentiment';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"returns\", \"sql\": \"SELECT rvbbit.clover_classify(''refund request for damaged item'',''billing, shipping, returns, technical support'')\", \"expect\": {\"type\": \"exact\", \"value\": \"returns\"}, \"description\": \"\"}, {\"name\": \"billing\", \"sql\": \"SELECT rvbbit.clover_classify(''I was charged twice this month'',''billing, shipping, returns, technical support'')\", \"expect\": {\"type\": \"exact\", \"value\": \"billing\"}, \"description\": \"\"}, {\"name\": \"tech\", \"sql\": \"SELECT rvbbit.clover_classify(''the app will not connect to wifi'',''billing, shipping, returns, technical support'')\", \"expect\": {\"type\": \"exact\", \"value\": \"technical support\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_classify';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"kind-\", \"sql\": \"SELECT rvbbit.clover_toxic(''have a wonderful day'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"insult+\", \"sql\": \"SELECT rvbbit.clover_toxic(''you are a worthless idiot'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"neutral-\", \"sql\": \"SELECT rvbbit.clover_toxic(''the quarterly report is attached'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"threat+\", \"sql\": \"SELECT rvbbit.clover_toxic(''i will hurt you if you come here'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_toxic';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"fr\", \"sql\": \"SELECT rvbbit.clover_language(''bonjour mes amis'')\", \"expect\": {\"type\": \"exact\", \"value\": \"fr\"}, \"description\": \"\"}, {\"name\": \"de\", \"sql\": \"SELECT rvbbit.clover_language(''guten morgen alle zusammen'')\", \"expect\": {\"type\": \"exact\", \"value\": \"de\"}, \"description\": \"\"}, {\"name\": \"es\", \"sql\": \"SELECT rvbbit.clover_language(''buenos dias, como estas hoy'')\", \"expect\": {\"type\": \"exact\", \"value\": \"es\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_language';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"entities\", \"sql\": \"SELECT rvbbit.clover_extract(''Sarah Chen paid $450 to Acme Corp in Denver on May 5th'',''person, organization, money, location, date'')::text\", \"expect\": {\"type\": \"contains\", \"value\": \"Sarah Chen\"}, \"description\": \"\"}, {\"name\": \"nonempty\", \"sql\": \"SELECT rvbbit.clover_extract(''Meeting with Bob at Initech tomorrow'',''person, organization'')::text\", \"expect\": {\"type\": \"not_empty\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_extract';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"email\", \"sql\": \"SELECT rvbbit.clover_pii(''Contact Sarah Chen at sarah@acme.com or 555-867-5309'')::text\", \"expect\": {\"type\": \"contains\", \"value\": \"sarah@acme.com\"}, \"description\": \"\"}, {\"name\": \"ssn\", \"sql\": \"SELECT rvbbit.clover_pii(''SSN on file: 123-45-6789'')::text\", \"expect\": {\"type\": \"contains\", \"value\": \"123-45-6789\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_pii';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"close\", \"sql\": \"SELECT rvbbit.clover_similar(''fast database'',''quick sql engine'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.45\"}, \"description\": \"\"}, {\"name\": \"far\", \"sql\": \"SELECT rvbbit.clover_similar(''fast database'',''a nice sandwich'')\", \"expect\": {\"type\": \"max\", \"value\": \"0.35\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_similar';",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"scores\", \"sql\": \"SELECT rvbbit.clover_moderate(''you are a worthless idiot'')::text\", \"expect\": {\"type\": \"contains\", \"value\": \"insult\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_moderate';",
              "SELECT rvbbit.register_backend('ocr',             'http://clover.rvbb.it:8090/b/ocr/predict',             'rvbbit', 4, 2, 180000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('document_parse',  'http://clover.rvbb.it:8090/b/document_parse/predict',  'rvbbit', 2, 1, 300000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('transcribe',      'http://clover.rvbb.it:8090/b/transcribe/predict',      'rvbbit', 4, 2, 300000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('forecast',        'http://clover.rvbb.it:8090/b/forecast/predict',        'rvbbit', 8, 2, 60000,  'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('timeseries_anomalies',  'http://clover.rvbb.it:8090/b/timeseries_anomalies/predict',  'rvbbit', 8, 4, 120000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('timeseries_impute',     'http://clover.rvbb.it:8090/b/timeseries_impute/predict',     'rvbbit', 8, 4, 120000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('timeseries_embed',      'http://clover.rvbb.it:8090/b/timeseries_embed/predict',      'rvbbit', 16, 8, 60000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('timeseries_similarity', 'http://clover.rvbb.it:8090/b/timeseries_similarity/predict', 'rvbbit', 16, 8, 60000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('image_embed',     'http://clover.rvbb.it:8090/b/image_embed/predict',     'rvbbit', 16, 4, 120000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('tabular_fit',     'http://clover.rvbb.it:8090/b/tabular_fit/predict',     'rvbbit', 1, 1, 300000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('tabular_predict', 'http://clover.rvbb.it:8090/b/tabular_predict/predict', 'rvbbit', 1, 1, 600000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('anomaly_fit',     'http://clover.rvbb.it:8090/b/anomaly_fit/predict',     'rvbbit', 1, 1, 120000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('anomaly_score',   'http://clover.rvbb.it:8090/b/anomaly_score/predict',   'rvbbit', 1, 1, 60000,  'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('relations',       'http://clover.rvbb.it:8090/b/relations/predict',       'rvbbit', 16, 4, 120000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.reload_backends();",
              "SELECT rvbbit.create_operator('clover_pii', ARRAY['t'], 'jsonb',\n  op_description := 'Clover-ML: detect PII entities (GLiNER preset: person, email, phone, address, ssn, cc, dob, ip)',\n  op_steps := '[{\"name\":\"e\",\"kind\":\"specialist\",\"specialist\":\"extract\",\"inputs\":{\"text\":\"{{t}}\",\"labels\":\"person, email, phone number, street address, social security number, credit card number, date of birth, ip address\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_similar', ARRAY['a','b'], 'float8', op_parser := 'strip',\n  op_description := 'Clover-ML: embedding cosine similarity of two texts (arctic-embed)',\n  op_steps := '[\n    {\"name\":\"ea\",\"kind\":\"specialist\",\"specialist\":\"embed\",\"inputs\":{\"text\":\"{{a}}\"}},\n    {\"name\":\"eb\",\"kind\":\"specialist\",\"specialist\":\"embed\",\"inputs\":{\"text\":\"{{b}}\"}},\n    {\"name\":\"c\",\"kind\":\"code\",\"fn\":\"cosine_similarity\",\"inputs\":{\"left\":\"{{steps.ea.output}}\",\"right\":\"{{steps.eb.output}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_moderate', ARRAY['t'], 'jsonb',\n  op_description := 'Clover-ML: full moderation category scores (toxic/severe/obscene/threat/insult/identity_hate)',\n  op_steps := '[\n    {\"name\":\"x\",\"kind\":\"specialist\",\"specialist\":\"toxicity\",\"inputs\":{\"text\":\"{{t}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.x.output}}\",\"path\":\"scores\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_ocr', ARRAY['doc'], 'text',\n  op_description := 'Clover-ML: OCR a document (image or PDF; URL or data URI) to plain text through Granite-Docling',\n  op_steps := '[\n    {\"name\":\"o\",\"kind\":\"specialist\",\"specialist\":\"ocr\",\"inputs\":{\"document\":\"{{doc}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.o.output}}\",\"path\":\"text\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_document_parse', ARRAY['doc'], 'jsonb',\n  op_description := 'Clover-ML: structured document parse — Markdown, typed blocks, tables/cells, hierarchy and page geometry (Granite-Docling)',\n  op_steps := '[{\"name\":\"p\",\"kind\":\"specialist\",\"specialist\":\"document_parse\",\"inputs\":{\"document\":\"{{doc}}\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_transcribe', ARRAY['audio'], 'text',\n  op_description := 'Clover-ML: transcribe audio (URL or data URI) to text (Whisper large-v3-turbo)',\n  op_steps := '[\n    {\"name\":\"w\",\"kind\":\"specialist\",\"specialist\":\"transcribe\",\"inputs\":{\"audio\":\"{{audio}}\"}},\n    {\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.w.output}}\",\"path\":\"text\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_forecast', ARRAY['series','horizon'], 'jsonb',\n  op_description := 'Clover-ML: forecast a numeric series (JSON array) N steps ahead — {median, quantiles} (Chronos-2)',\n  op_steps := '[\n    {\"name\":\"f\",\"kind\":\"specialist\",\"specialist\":\"forecast\",\"inputs\":{\"context\":\"{{series}}\",\"horizon\":\"{{horizon}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_forecast_drivers', ARRAY['targets','past_covariates','future_covariates','horizon'], 'jsonb',\n  op_description := 'Clover-ML: Chronos-2 multivariate forecast for named target series with historical and known-future numeric or categorical drivers; arguments are JSON objects',\n  op_steps := '[{\"name\":\"f\",\"kind\":\"specialist\",\"specialist\":\"forecast\",\"inputs\":{\"targets\":\"{{targets}}\",\"past_covariates\":\"{{past_covariates}}\",\"future_covariates\":\"{{future_covariates}}\",\"horizon\":\"{{horizon}}\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_series_anomalies', ARRAY['series'], 'jsonb',\n  op_description := 'Clover-ML: TSPulse anomaly scores for a JSON numeric series (minimum 1536 points)',\n  op_steps := '[{\"name\":\"a\",\"kind\":\"specialist\",\"specialist\":\"timeseries_anomalies\",\"inputs\":{\"values\":\"{{series}}\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_series_impute', ARRAY['series'], 'jsonb',\n  op_description := 'Clover-ML: TSPulse reconstruction of null points in a JSON numeric series (minimum 512 points)',\n  op_steps := '[{\"name\":\"i\",\"kind\":\"specialist\",\"specialist\":\"timeseries_impute\",\"inputs\":{\"values\":\"{{series}}\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_series_embed', ARRAY['series'], 'jsonb',\n  op_description := 'Clover-ML: semantic TSPulse embedding of the most recent 512 points in a JSON numeric series',\n  op_steps := '[{\"name\":\"e\",\"kind\":\"specialist\",\"specialist\":\"timeseries_embed\",\"inputs\":{\"values\":\"{{series}}\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_series_similarity', ARRAY['a','b'], 'float8', op_parser := 'strip',\n  op_description := 'Clover-ML: cosine similarity between the TSPulse shape embeddings of two JSON numeric series (minimum 512 points each)',\n  op_steps := '[{\"name\":\"s\",\"kind\":\"specialist\",\"specialist\":\"timeseries_similarity\",\"inputs\":{\"left\":\"{{a}}\",\"right\":\"{{b}}\"}},{\"name\":\"g\",\"kind\":\"code\",\"fn\":\"json_get\",\"inputs\":{\"value\":\"{{steps.s.output}}\",\"path\":\"similarity\"}}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_image_similar', ARRAY['a','b'], 'float8', op_parser := 'strip',\n  op_description := 'Clover-ML: similarity of two images, or an image and a text description (SigLIP 2 dual-tower; URL/data-URI/text inputs)',\n  op_steps := '[\n    {\"name\":\"ea\",\"kind\":\"specialist\",\"specialist\":\"image_embed\",\"inputs\":{\"text\":\"{{a}}\"}},\n    {\"name\":\"eb\",\"kind\":\"specialist\",\"specialist\":\"image_embed\",\"inputs\":{\"text\":\"{{b}}\"}},\n    {\"name\":\"c\",\"kind\":\"code\",\"fn\":\"cosine_similarity\",\"inputs\":{\"left\":\"{{steps.ea.output}}\",\"right\":\"{{steps.eb.output}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_fit', ARRAY['task','features','labels'], 'jsonb',\n  op_description := 'Clover-ML: fit a TabPFN model — task ''classifier''|''regressor'', features = JSON array of rows, labels = JSON array. Returns {blob_b64, blob_sha256, ...}: the fitted model stays YOURS, nothing persists server-side.',\n  op_steps := '[\n    {\"name\":\"f\",\"kind\":\"specialist\",\"specialist\":\"tabular_fit\",\"inputs\":{\"task\":\"{{task}}\",\"X\":\"{{features}}\",\"y\":\"{{labels}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_predict', ARRAY['model_blob_b64','features'], 'jsonb',\n  op_description := 'Clover-ML: predict with a clover_fit model blob — features = JSON array of rows. Returns {predictions, probabilities, class_labels}.',\n  op_steps := '[\n    {\"name\":\"p\",\"kind\":\"specialist\",\"specialist\":\"tabular_predict\",\"inputs\":{\"model_blob_b64\":\"{{model_blob_b64}}\",\"X\":\"{{features}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_anomaly_fit', ARRAY['features'], 'jsonb',\n  op_description := 'Clover-ML: fit an anomaly detector (isolation forest) on JSON rows. Returns {blob_b64, ...} — client-held model, higher score = more anomalous.',\n  op_steps := '[\n    {\"name\":\"f\",\"kind\":\"specialist\",\"specialist\":\"anomaly_fit\",\"inputs\":{\"X\":\"{{features}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_anomaly_score', ARRAY['model_blob_b64','features'], 'jsonb',\n  op_description := 'Clover-ML: score JSON rows against a clover_anomaly_fit model — {scores:[...]}, higher = more anomalous.',\n  op_steps := '[\n    {\"name\":\"s\",\"kind\":\"specialist\",\"specialist\":\"anomaly_score\",\"inputs\":{\"model_blob_b64\":\"{{model_blob_b64}}\",\"X\":\"{{features}}\"}}\n  ]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_relations', ARRAY['t'], 'jsonb',\n  op_description := 'Clover-ML: extract (subject, predicate, object) relation triples from text (REBEL)',\n  op_steps := '[\n    {\"name\":\"r\",\"kind\":\"specialist\",\"specialist\":\"relations\",\"inputs\":{\"text\":\"{{t}}\"}}\n  ]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"invoice\", \"sql\": \"SELECT rvbbit.clover_ocr(''https://rvbbit.ai/data/clover-tests/invoice.png'')\", \"expect\": {\"type\": \"contains\", \"value\": \"12345\"}, \"description\": \"rendered INVOICE 12345 card\"}\n]'::jsonb WHERE name = 'clover_ocr';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"fox\", \"sql\": \"SELECT lower(rvbbit.clover_transcribe(''https://rvbbit.ai/data/clover-tests/speech.wav''))\", \"expect\": {\"type\": \"contains\", \"value\": \"quick brown fox\"}, \"description\": \"espeak-generated speech\"}\n]'::jsonb WHERE name = 'clover_transcribe';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"horizon_len\", \"sql\": \"SELECT (jsonb_array_length(rvbbit.clover_forecast(''[1,2,3,4,5,6,7,8,9,10]'',''4'')->''median'') = 4)::text\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"},\n  {\"name\": \"ramp_next\", \"sql\": \"SELECT ((rvbbit.clover_forecast(''[1,2,3,4,5,6,7,8,9,10]'',''4'')->''median''->>0)::float8 BETWEEN 8 AND 14)::text\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"linear ramp continues near 11\"}\n]'::jsonb WHERE name = 'clover_forecast';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"identical\", \"sql\": \"SELECT rvbbit.clover_image_similar(''https://rvbbit.ai/data/clover-tests/red-square.png'',''https://rvbbit.ai/data/clover-tests/red-square.png'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.98\"}, \"description\": \"\"},\n  {\"name\": \"different\", \"sql\": \"SELECT rvbbit.clover_image_similar(''https://rvbbit.ai/data/clover-tests/red-square.png'',''https://rvbbit.ai/data/clover-tests/noise.png'')\", \"expect\": {\"type\": \"max\", \"value\": \"0.9\"}, \"description\": \"\"}\n]'::jsonb WHERE name = 'clover_image_similar';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"fit_predict\", \"sql\": \"WITH m AS (SELECT rvbbit.clover_fit(''classifier'', ''[[1,1],[2,1],[1,2],[8,9],[9,8],[9,9]]'', ''[\\\"small\\\",\\\"small\\\",\\\"small\\\",\\\"big\\\",\\\"big\\\",\\\"big\\\"]'') AS j) SELECT rvbbit.clover_predict(m.j->>''blob_b64'', ''[[9,9]]'')->''predictions''->>0 FROM m\", \"expect\": {\"type\": \"exact\", \"value\": \"big\"}, \"description\": \"TabPFN in-context 2-feature split\"}\n]'::jsonb WHERE name = 'clover_fit';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"regression\", \"sql\": \"WITH m AS (SELECT rvbbit.clover_fit(''regressor'', ''[[1],[2],[3],[4],[5],[6]]'', ''[2,4,6,8,10,12]'') AS j) SELECT ((rvbbit.clover_predict(m.j->>''blob_b64'', ''[[7]]'')->''predictions''->>0)::float8 BETWEEN 11 AND 17)::text FROM m\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"y=2x extrapolation\"}\n]'::jsonb WHERE name = 'clover_predict';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"outlier_ranks_higher\", \"sql\": \"WITH m AS (SELECT rvbbit.clover_anomaly_fit(''[[1,1],[1.1,0.9],[0.9,1.1],[1.05,1.0],[0.95,0.98],[1.02,1.03],[1.0,0.97]]'') AS j) SELECT ((rvbbit.clover_anomaly_score(m.j->>''blob_b64'', ''[[9,9]]'')->''scores''->>0)::float8 > (rvbbit.clover_anomaly_score(m.j->>''blob_b64'', ''[[1,1]]'')->''scores''->>0)::float8)::text FROM m\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"far point scores above cluster center\"}\n]'::jsonb WHERE name = 'clover_anomaly_fit';",
              "UPDATE rvbbit.operators SET tests = '[\n  {\"name\": \"curie\", \"sql\": \"SELECT rvbbit.clover_relations(''Marie Curie discovered radium in 1898'')::text\", \"expect\": {\"type\": \"contains\", \"value\": \"Curie\"}, \"description\": \"REBEL triple extraction\"}\n]'::jsonb WHERE name = 'clover_relations';",
              "SELECT rvbbit.register_backend('clover_llm', 'http://clover.rvbb.it:8090/v1/chat/completions', 'openai_chat', 32, 32, 120000, 'RVBBIT_CLOVER_KEY', '{\"model\": \"gemma4\"}'::jsonb);",
              "SELECT rvbbit.create_operator('clover_llm_ask', ARRAY['q'], 'text', op_description := 'Clover-LLM: one-shot ask against the hosted generalist', op_steps := '[{\"name\":\"main\",\"kind\":\"llm\",\"provider\":\"clover_llm\",\"model\":\"gemma4\",\"user\":\"{{q}}\",\"max_tokens\":400}]'::jsonb);",
              "SELECT rvbbit.create_operator('clover_llm_apply', ARRAY['t', 'instruction'], 'text',\n  op_description := 'Clover-LLM: apply an instruction or question to a text — answers ONLY from the text, returns NULL when the text lacks the answer',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are a text analysis assistant. Answer the question or follow the instruction using ONLY the given text.\\n\\nRules:\\n- Answer based ONLY on the text provided\\n- Return ONLY the answer - no preamble, no explanation\\n- Be concise and direct\\n- If the text doesn''t contain the answer, return exactly NULL\\n\\nExamples:\\nText: \\\"The sky is blue\\\" + Question: \\\"What color is the sky?\\\" -> blue\\nText: \\\"Price: $99.99\\\" + Question: \\\"How much?\\\" -> $99.99\\nText: \\\"Meeting at 3pm\\\" + Question: \\\"When?\\\" -> 3pm\\n\\nTEXT:\\n{{t}}\\n\\nQUESTION/INSTRUCTION:\\n{{instruction}}\", \"max_tokens\": 400}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"answer\", \"sql\": \"SELECT lower(rvbbit.clover_llm_apply(''The conference was moved to Denver due to weather'', ''What city?''))\", \"expect\": {\"type\": \"contains\", \"value\": \"denver\"}, \"description\": \"\"}, {\"name\": \"null_when_absent\", \"sql\": \"SELECT rvbbit.clover_llm_apply(''The sky is blue'', ''What is the CEO''''s name?'')\", \"expect\": {\"type\": \"contains\", \"value\": \"NULL\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_apply';",
              "SELECT rvbbit.create_operator('clover_llm_extract', ARRAY['t', 'schema'], 'jsonb',\n  op_description := 'Clover-LLM: extract a JSON object from freeform text per a schema you describe (fields, types, enums) — every field present, null when absent',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are a structured-data extractor. Given a text and a target schema, you output a SINGLE valid JSON object matching the schema and nothing else.\\n\\nRules:\\n- The output must be a single JSON object. No markdown fences, no prose.\\n- Every field from the schema MUST appear in the output. Use null when the text doesn''t contain that information.\\n- Coerce types to the schema: integer -> numeric, decimal -> numeric with decimals, date -> YYYY-MM-DD string, boolean -> true/false, string -> short string.\\n- For enum-like fields (e.g. \\\"urgency: 1-5\\\"), pick ONE specific value, never ranges or lists.\\n- For nested objects, mirror the schema''s nesting.\\n\\nSCHEMA:\\n{{schema}}\\n\\nTEXT:\\n{{t}}\\n\\nReturn the JSON object.\", \"max_tokens\": 700}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"invoice\", \"sql\": \"SELECT (rvbbit.clover_llm_extract(''Invoice #4451 from Acme Corp, due March 5 2024, total $1,250.50'', ''vendor: string, invoice_number: string, total: decimal, due_date: date''))->>''vendor''\", \"expect\": {\"type\": \"contains\", \"value\": \"Acme\"}, \"description\": \"\"}, {\"name\": \"null_field\", \"sql\": \"SELECT ((rvbbit.clover_llm_extract(''Order shipped yesterday'', ''tracking_number: string, carrier: string''))->''tracking_number'')::text\", \"expect\": {\"type\": \"contains\", \"value\": \"null\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_extract';",
              "SELECT rvbbit.create_operator('clover_llm_translate', ARRAY['t', 'lang'], 'text',\n  op_description := 'Clover-LLM: translate text to a target language (name or ISO code) — returns only the translation, preserves formatting and proper nouns',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"Translate the text into the target language.\\n\\nRules:\\n- Return ONLY the translated text - no preamble, no quotes, no notes.\\n- Preserve formatting (line breaks, punctuation style).\\n- Keep proper nouns unchanged when appropriate.\\n- Use natural phrasing in the target language.\\n\\nTARGET LANGUAGE: {{lang}}\\n\\nTEXT:\\n{{t}}\", \"max_tokens\": 600}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"to_spanish\", \"sql\": \"SELECT lower(rvbbit.clover_llm_translate(''hello world'', ''Spanish''))\", \"expect\": {\"type\": \"contains\", \"value\": \"hola\"}, \"description\": \"\"}, {\"name\": \"to_german\", \"sql\": \"SELECT lower(rvbbit.clover_llm_translate(''good morning'', ''de''))\", \"expect\": {\"type\": \"contains\", \"value\": \"guten\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_translate';",
              "SELECT rvbbit.create_operator('clover_llm_anonymize', ARRAY['t'], 'text',\n  op_description := 'Clover-LLM: rewrite text with ALL PII redacted — names to [NAME], emails to [EMAIL], phones to [PHONE], addresses/SSNs/cards likewise. Complements clover_pii (which detects without rewriting)',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are a PII anonymization specialist. Rewrite the text with ALL personally identifiable information replaced by bracket tags.\\n\\nIMPORTANT: err on the side of OVER-detection. If something could be PII, replace it.\\nReplacements:\\n- Person names -> [NAME]\\n- Email addresses -> [EMAIL]\\n- Phone numbers -> [PHONE]\\n- Street addresses -> [ADDRESS]\\n- SSNs -> [SSN]\\n- Credit card numbers -> [CARD]\\n- Dates of birth -> [DOB]\\n- IP addresses -> [IP]\\n\\nReturn ONLY the rewritten text - no preamble, no JSON, no notes. Keep everything that is not PII exactly as written.\\n\\nTEXT:\\n{{t}}\", \"max_tokens\": 600}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"email_phone\", \"sql\": \"SELECT rvbbit.clover_llm_anonymize(''Contact Sarah Chen at sarah@acme.com or 555-867-5309'')\", \"expect\": {\"type\": \"contains\", \"value\": \"[EMAIL]\"}, \"description\": \"\"}, {\"name\": \"no_leak\", \"sql\": \"SELECT position(''sarah@acme.com'' IN rvbbit.clover_llm_anonymize(''Email sarah@acme.com about the invoice''))::text\", \"expect\": {\"type\": \"exact\", \"value\": \"0\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_anonymize';",
              "SELECT rvbbit.create_operator('clover_llm_canonical', ARRAY['t'], 'text',\n  op_description := 'Clover-LLM: return the canonical/official form of a value — expands abbreviations, standardizes entity names (''NYC'' to ''New York City'', ''MICROSOFT CORP'' to ''Microsoft'')',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"Return the canonical/official form of this value.\\n\\nSteps:\\n1. Detect what type of entity this is (company, city, person name, address, phone, etc.)\\n2. Return the standard/canonical form.\\n\\nExamples:\\n- NYC -> New York City\\n- SF -> San Francisco\\n- DC -> Washington, D.C.\\n- MICROSOFT CORP -> Microsoft\\n- INTL BUSINESS MACHINES -> IBM\\n- j. smith -> J. Smith\\n\\nRules:\\n- Return ONLY the canonical value - no explanation, no quotes.\\n- If the value is already canonical, return it unchanged.\\n- Never invent information that is not implied by the value.\\n\\nVALUE: {{t}}\", \"max_tokens\": 100}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"city\", \"sql\": \"SELECT rvbbit.clover_llm_canonical(''NYC'')\", \"expect\": {\"type\": \"contains\", \"value\": \"New York\"}, \"description\": \"\"}, {\"name\": \"company\", \"sql\": \"SELECT rvbbit.clover_llm_canonical(''INTL BUSINESS MACHINES CORP'')\", \"expect\": {\"type\": \"contains\", \"value\": \"IBM\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_canonical';",
              "SELECT rvbbit.create_operator('clover_llm_fix', ARRAY['value', 'hint'], 'text',\n  op_description := 'Clover-LLM: repair a malformed value given a type hint — email domain typos, phone formats, mojibake, spacing (''john @ gmial.com'' + ''email'' to ''john@gmail.com'')',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"Fix this value if it has common data-quality issues, using the type hint.\\n\\nCommon fixes:\\n- Email: domain typos (gmial.com -> gmail.com), missing TLD, stray spaces or double dots\\n- Phone: standardize to (555) 123-4567 form\\n- Numbers: strip currency symbols/commas when hint asks for a number\\n- Text: fix obvious encoding damage and doubled spaces\\n\\nRules:\\n- Return ONLY the fixed value - no explanation, no quotes.\\n- If nothing is wrong, return the value unchanged.\\n- Never invent missing information; only repair what is clearly broken.\\n\\nVALUE: {{value}}\\nTYPE HINT: {{hint}}\", \"max_tokens\": 100}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"email_typo\", \"sql\": \"SELECT rvbbit.clover_llm_fix(''john @ gmial.com'', ''email'')\", \"expect\": {\"type\": \"exact\", \"value\": \"john@gmail.com\"}, \"description\": \"\"}, {\"name\": \"already_clean\", \"sql\": \"SELECT rvbbit.clover_llm_fix(''bob@yahoo.com'', ''email'')\", \"expect\": {\"type\": \"exact\", \"value\": \"bob@yahoo.com\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_fix';",
              "SELECT rvbbit.create_operator('clover_llm_date', ARRAY['t'], 'text',\n  op_description := 'Clover-LLM: pull a date out of messy text and return it as ISO 8601 (YYYY-MM-DD), or NULL when no date is present',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"Extract the date from the text and return it in ISO 8601 format.\\n\\nRules:\\n- Return ONLY the date as YYYY-MM-DD - nothing else.\\n- If only a month and year are present, use the first of the month.\\n- If only a year is present, return YYYY-01-01.\\n- If NO date is present, return exactly NULL.\\n- Never guess the current date; use only what the text states.\\n\\nTEXT: {{t}}\", \"max_tokens\": 40}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"written_out\", \"sql\": \"SELECT rvbbit.clover_llm_date(''signed on March 5th, 2021 in Boston'')\", \"expect\": {\"type\": \"exact\", \"value\": \"2021-03-05\"}, \"description\": \"\"}, {\"name\": \"none_present\", \"sql\": \"SELECT rvbbit.clover_llm_date(''the quick brown fox'')\", \"expect\": {\"type\": \"contains\", \"value\": \"NULL\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_date';",
              "SELECT rvbbit.create_operator('clover_llm_score', ARRAY['t', 'criterion'], 'float8',\n  op_description := 'Clover-LLM: judge text against any criterion you phrase in English, 0.0-1.0 — an arbitrary-rubric cousin of clover_relevance',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"Rate how well the text satisfies the criterion.\\n\\nScoring guide:\\n- 0.0-0.2: does not satisfy the criterion at all\\n- 0.2-0.4: barely / tangentially\\n- 0.4-0.6: partially satisfies it\\n- 0.6-0.8: satisfies it well\\n- 0.8-1.0: exemplary\\n\\nReturn ONLY a decimal number between 0.0 and 1.0. No explanation, no quotes.\\n\\nCRITERION: {{criterion}}\\n\\nTEXT:\\n{{t}}\", \"max_tokens\": 8}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"high\", \"sql\": \"SELECT rvbbit.clover_llm_score(''Step 1: unplug the router. Step 2: wait 10 seconds. Step 3: plug it back in.'', ''clear actionable instructions'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.6\"}, \"description\": \"\"}, {\"name\": \"low\", \"sql\": \"SELECT rvbbit.clover_llm_score(''asdf jkl whatever'', ''clear actionable instructions'')\", \"expect\": {\"type\": \"max\", \"value\": \"0.3\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_score';",
              "SELECT rvbbit.create_operator('clover_llm_supports', ARRAY['evidence', 'claim'], 'float8',\n  op_description := 'Clover-LLM: how strongly does the evidence support the claim, 0.0-1.0 — contradiction scores near 0, decisive support near 1',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are an evidential support scorer. Rate how strongly the EVIDENCE supports the CLAIM.\\n\\nScoring guide:\\n- 0.0-0.2: no support - irrelevant, or actively contradicts the claim\\n- 0.2-0.4: very weak - tangential, requires leaps, anecdote where statistics are needed\\n- 0.4-0.6: weak to moderate - relevant but not conclusive, supports only part of the claim\\n- 0.6-0.8: moderate to strong - directly relevant, would shift a reasonable person''s view\\n- 0.8-1.0: strong to decisive - directly establishes the claim\\n\\nReturn ONLY a decimal number between 0.0 and 1.0. No explanation.\\n\\nEVIDENCE:\\n{{evidence}}\\n\\nCLAIM:\\n{{claim}}\", \"max_tokens\": 8}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"strong\", \"sql\": \"SELECT rvbbit.clover_llm_supports(''In a randomized trial of 12,000 patients, the vaccine reduced infections by 94%'', ''the vaccine is effective'')\", \"expect\": {\"type\": \"min\", \"value\": \"0.7\"}, \"description\": \"\"}, {\"name\": \"contradicts\", \"sql\": \"SELECT rvbbit.clover_llm_supports(''Sales fell 40% after the redesign launched'', ''the redesign improved sales'')\", \"expect\": {\"type\": \"max\", \"value\": \"0.25\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_supports';",
              "SELECT rvbbit.create_operator('clover_llm_valid', ARRAY['value', 'rule'], 'bool',\n  op_description := 'Clover-LLM: TRUE if a value satisfies a rule phrased in English (''contains pricing'', ''is a professional tone'', ''has contact information'')',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are a semantic validator. Decide whether the VALUE satisfies the RULE.\\n\\nExamples of rules:\\n- \\\"contains pricing\\\" -> does it mention a price, cost, or dollar amount?\\n- \\\"is professional tone\\\" -> is the language formal and business-appropriate?\\n- \\\"has contact information\\\" -> does it include an email, phone, or address?\\n- \\\"contains date\\\" -> does it reference a date or time?\\n\\nBe reasonably strict but not pedantic; interpret the rule in its common-sense meaning.\\n\\nReturn ONLY true or false.\\n\\nVALUE: {{value}}\\nRULE: {{rule}}\", \"max_tokens\": 6}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"pricing_yes\", \"sql\": \"SELECT rvbbit.clover_llm_valid(''Our plan starts at $99/month'', ''contains pricing'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"pricing_no\", \"sql\": \"SELECT rvbbit.clover_llm_valid(''Have a great weekend!'', ''contains pricing'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_valid';",
              "SELECT rvbbit.create_operator('clover_llm_steelman', ARRAY['argument'], 'text',\n  op_description := 'Clover-LLM: rewrite an argument in its strongest, most defensible form — the good-faith opposite of a strawman',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are a steelmanning specialist. Present the argument in its most compelling, well-reasoned, defensible form.\\n\\nGuidelines:\\n1. Assume intelligence: what would the smartest, most informed person making this argument say?\\n2. Add supporting evidence: facts, data, or examples that strengthen the position.\\n3. Address obvious objections preemptively.\\n4. Clarify scope: define reasonable boundaries - it probably isn''t meant to be absolute.\\n5. Ground it in values reasonable people share.\\n6. Drop weak elements.\\n\\nReturn ONLY the steelmanned argument (2-4 sentences). No preamble.\\n\\nORIGINAL ARGUMENT:\\n{{argument}}\", \"max_tokens\": 700}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"nonempty\", \"sql\": \"SELECT length(rvbbit.clover_llm_steelman(''remote work is bad'')) > 80\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_steelman';",
              "SELECT rvbbit.create_operator('clover_llm_fallacies', ARRAY['argument'], 'jsonb',\n  op_description := 'Clover-LLM: detect logical fallacies in an argument — JSON array of {fallacy, explanation} with snake_case fallacy names',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"system\": \"You are a conservative logical-fallacy classifier. False positives are worse than misses. Follow the output contract and examples exactly.\", \"user\": \"Identify a fallacy only when the text presents an inference from premises to a conclusion and the inference clearly matches an allowed fallacy.\\n\\nAllowed names: ad_hominem, appeal_to_authority, appeal_to_emotion, appeal_to_popularity, appeal_to_tradition, appeal_to_nature, genetic_fallacy, tu_quoque, red_herring, false_dichotomy, false_cause, slippery_slope, circular_reasoning, hasty_generalization, straw_man, no_true_scotsman, equivocation.\\n\\nA factual description, experimental method, observation, or standalone claim without an inferential leap is clean. Repetition, averaging, sample counts, and uncertainty are not themselves fallacies. When uncertain, classify as clean.\\n\\nExamples:\\nARGUMENT: Nine out of ten people believe it, so it must be true.\\nOUTPUT: [{\\\"fallacy\\\":\\\"appeal_to_popularity\\\",\\\"explanation\\\":\\\"Popularity does not establish truth.\\\"}]\\n\\nARGUMENT: The measurements were repeated five times and averaged to reduce error.\\nOUTPUT: []\\n\\nReturn ONLY a JSON array. Return [] when clean.\\n\\nARGUMENT: {{argument}}\", \"max_tokens\": 500}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"popularity\", \"sql\": \"SELECT (rvbbit.clover_llm_fallacies(''Nine out of ten people believe it, so it must be true''))::text\", \"expect\": {\"type\": \"contains\", \"value\": \"popularity\"}, \"description\": \"\"}, {\"name\": \"clean\", \"sql\": \"SELECT jsonb_array_length(rvbbit.clover_llm_fallacies(''The measurements were repeated five times and averaged to reduce error''))::text\", \"expect\": {\"type\": \"exact\", \"value\": \"0\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_fallacies';",
              "SELECT rvbbit.create_operator('clover_llm_means', ARRAY['t', 'criterion'], 'bool',\n  op_description := 'Clover-LLM: TRUE if text semantically matches a criterion — the LLM-judged sibling of clover_means for inputs that need real thought (sarcasm, indirection, multi-clause)',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"You are a semantic matching evaluator. Given a TEXT and a CRITERION, determine if the text semantically matches the criterion.\\n\\nSTEP 1: What topic/domain is the TEXT about?\\nSTEP 2: What topic/domain is the CRITERION about?\\nSTEP 3: Are these the SAME or CLOSELY RELATED topics?\\n\\nA MATCH means the text discusses the SAME or CLOSELY RELATED topic.\\nNOT A MATCH means the topics are from completely different domains.\\n\\nExamples:\\n- MATCH: \\\"stock prices fell\\\" + \\\"financial news\\\" (both finance)\\n- MATCH: \\\"apple pie recipe\\\" + \\\"dessert recipes\\\" (both food)\\n- NO MATCH: \\\"weather forecast\\\" + \\\"financial news\\\" (different domains)\\n\\nReturn ONLY the word true or false. Nothing else.\\n\\nTEXT: {{t}}\\nCRITERION: {{criterion}}\", \"max_tokens\": 6}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"dessert\", \"sql\": \"SELECT rvbbit.clover_llm_means(''apple pie recipe'', ''dessert recipes'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"cross_domain\", \"sql\": \"SELECT rvbbit.clover_llm_means(''basketball game results'', ''cooking recipes'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"indirection\", \"sql\": \"SELECT rvbbit.clover_llm_means(''the package never showed up and support went silent for two weeks'', ''a customer having a bad delivery experience'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_means';",
              "SELECT rvbbit.create_operator('clover_llm_implies', ARRAY['premise', 'conclusion'], 'bool',\n  op_description := 'Clover-LLM: TRUE if the premise implies the conclusion — logical entailment plus common-sense inference; handles the quantifier cases (all -> some) that fast NLI models miss',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"user\": \"Determine if a PREMISE semantically implies a CONCLUSION.\\n\\nReturn true if a reasonable person would consider the conclusion likely true given the premise. This includes:\\n- Direct logical entailment (\\\"bachelor\\\" -> \\\"unmarried\\\")\\n- Quantifier logic (\\\"all employees got a bonus\\\" -> \\\"some employees got a bonus\\\")\\n- Strong causal relationships (\\\"raining\\\" -> \\\"the ground is wet\\\")\\n- Common-sense inferences that follow naturally\\n\\nReturn false only if there is no meaningful connection or the conclusion does not follow from the premise.\\n\\nReturn ONLY the word true or false. Nothing else.\\n\\nPREMISE: {{premise}}\\nCONCLUSION: {{conclusion}}\", \"max_tokens\": 6}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"subset\", \"sql\": \"SELECT rvbbit.clover_llm_implies(''All employees received a bonus in December'', ''Some employees received a bonus'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"causal\", \"sql\": \"SELECT rvbbit.clover_llm_implies(''It has been raining for hours'', ''the ground is wet'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"\"}, {\"name\": \"non_sequitur\", \"sql\": \"SELECT rvbbit.clover_llm_implies(''The cat sat on the mat'', ''The stock market rose today'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_implies';",
              "SELECT rvbbit.create_operator('clover_llm_contradicts', ARRAY['a', 'b'], 'bool',\n  op_description := 'Clover-LLM: TRUE if two texts logically contradict — LLM-judged sibling of clover_contradicts; different-subject statements are never contradictions',\n  op_steps := '[{\"name\": \"main\", \"kind\": \"llm\", \"provider\": \"clover_llm\", \"model\": \"gemma4\", \"system\": \"Classify contradiction. Your entire response must be exactly one lowercase token: true or false. Never reverse the labels.\", \"user\": \"Return true only if TEXT A and TEXT B cannot both be true in the same situation. Otherwise return false.\\n\\nExamples:\\nA: The light is on now.\\nB: The same light is off now.\\nANSWER: true\\n\\nA: The webinar starts at 10am.\\nB: The webinar starts in the morning.\\nANSWER: false\\n\\nA: Revenue increased this quarter.\\nB: The office bought new chairs.\\nANSWER: false\\n\\nRules:\\n- Same entity or event and same time or context are required.\\n- Explicit mutually exclusive facts are contradictions.\\n- A narrower statement and a compatible broader statement are not contradictions.\\n- Unrelated topics are not contradictions.\\n\\nTEXT A: {{a}}\\nTEXT B: {{b}}\\nANSWER:\", \"max_tokens\": 6}]'::jsonb);",
              "UPDATE rvbbit.operators SET tests = '[{\"name\": \"opposing\", \"sql\": \"SELECT rvbbit.clover_llm_contradicts(''The store is open now'', ''The same store is closed now'')\", \"expect\": {\"type\": \"exact\", \"value\": \"true\"}, \"description\": \"same subject, time, and mutually exclusive state\"}, {\"name\": \"different_subjects\", \"sql\": \"SELECT rvbbit.clover_llm_contradicts(''The report covers Q3 revenue'', ''The office got new chairs'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}, {\"name\": \"compatible\", \"sql\": \"SELECT rvbbit.clover_llm_contradicts(''The meeting is at 9am'', ''The meeting is in the morning'')\", \"expect\": {\"type\": \"exact\", \"value\": \"false\"}, \"description\": \"\"}]'::jsonb WHERE name = 'clover_llm_contradicts';;",
              "SELECT rvbbit.reload_backends();",
              "SELECT rvbbit.create_operator(\n  'clover_llm_draft_spec', ARRAY['task'], 'text',\n  op_description := 'Internal: draft an operator spec (strict JSON) for clover_llm_make_operator',\n  op_steps := jsonb_build_array(jsonb_build_object(\n    'name', 'main', 'kind', 'llm',\n    'provider', 'clover_llm', 'model', 'gemma4',\n    'max_tokens', 2500, 'temperature', 0.2,\n    'system', 'You author SQL semantic operators for rvbbit. Follow the specification instructions in the user message exactly. Reply with ONE JSON object only - no markdown fences, no commentary.',\n    'user', '{{task}}'\n  )));",
              "CREATE OR REPLACE FUNCTION rvbbit.clover_llm_make_operator(\n  p_description    text,\n  p_name           text DEFAULT NULL,\n  p_return_type    text DEFAULT NULL,\n  p_max_iterations int  DEFAULT 3,\n  p_dry_run        boolean DEFAULT false\n) RETURNS jsonb LANGUAGE plpgsql AS $$\nDECLARE\n  briefing   text;\n  base_task  text;\n  task       text;\n  raw        text;\n  spec       jsonb;\n  violations text[];\n  arg_arr    text[];\n  rt         text;\n  final_name text;\n  tmp        text;\n  tests_in   jsonb;\n  tests_sql  jsonb;\n  t          jsonb;\n  test_args  text[];\n  call_sql   text;\n  results    jsonb;\n  n_fail     int;\n  n_total    int;\n  fail_txt   text;\n  i          int;\n  a          text;\n  sig        text;\nBEGIN\n  IF p_name IS NOT NULL AND p_name !~ '^[a-z][a-z0-9_]{2,40}$' THEN\n    RETURN jsonb_build_object('created', false, 'error', 'p_name must match ^[a-z][a-z0-9_]{2,40}$');\n  END IF;\n  IF p_name IS NOT NULL AND EXISTS (SELECT 1 FROM rvbbit.operators WHERE name = p_name) THEN\n    RETURN jsonb_build_object('created', false, 'error', format('operator %s already exists', p_name));\n  END IF;\n\n  -- The full authoring briefing lives HERE (an arg value, never template-\n  -- rendered) so its literal {{placeholders}} survive to the model.\n  briefing := $BRIEF$An operator is one LLM prompt template exposed as a SQL function. Design one as a JSON object with this schema:\n{\n \"name\": \"snake_case, 3-40 chars\",\n \"description\": \"one sentence\",\n \"arg_names\": [\"one to four snake_case names\"],\n \"return_type\": \"bool\" | \"text\" | \"float8\" | \"jsonb\",\n \"prompt\": \"The LLM instruction template. Reference every argument as {{arg_name}} (double curly braces). End by demanding the bare answer only.\",\n \"tests\": [\n   {\"name\": \"short_id\", \"args\": [\"one literal value per arg\"],\n    \"expect\": {\"type\": \"exact|contains|regex|min|max\", \"value\": \"...\", \"pattern\": \"...\"}}\n ]\n}\n\nRules:\n- The prompt MUST contain every argument as a {{arg_name}} placeholder, e.g. an arg named \"text\" appears as {{text}}.\n- bool: prompt demands exactly true or false (lowercase); test expect = {\"type\":\"exact\",\"value\":\"true\"} or \"false\".\n- float8: prompt demands a bare number between 0 and 1; use threshold tests - clear positives {\"type\":\"min\",\"value\":\"0.7\"}, clear negatives {\"type\":\"max\",\"value\":\"0.3\"}. Never exact-match a float.\n- text: prompt demands the answer text only; prefer {\"type\":\"contains\"} or {\"type\":\"regex\"} unless output is fully canonical.\n- jsonb: prompt demands raw JSON only (no fences); test with {\"type\":\"contains\",\"value\":\"\\\"some_key\\\"\"}.\n- Write 3 to 5 tests: clear positives, clear negatives, one edge case. Test args are plain literal strings, never SQL.\n- The prompt must be self-contained and unambiguous - a small model will execute it.\n\nExample (bool):\n{\"name\":\"is_apology\",\"description\":\"TRUE if the text contains an apology\",\"arg_names\":[\"t\"],\"return_type\":\"bool\",\"prompt\":\"Does this text contain an apology? Text: {{t}}\\nAnswer with exactly one word, true or false.\",\"tests\":[{\"name\":\"sorry\",\"args\":[\"We are so sorry for the delay\"],\"expect\":{\"type\":\"exact\",\"value\":\"true\"}},{\"name\":\"neutral\",\"args\":[\"Your order shipped Tuesday\"],\"expect\":{\"type\":\"exact\",\"value\":\"false\"}}]}\n\n$BRIEF$;\n\n  base_task := briefing || 'Design an operator for this task: ' || p_description\n    || CASE WHEN p_name IS NOT NULL THEN format(' The name must be exactly: %s.', p_name) ELSE '' END\n    || CASE WHEN p_return_type IS NOT NULL THEN format(' The return_type must be: %s.', p_return_type) ELSE '' END;\n  task := base_task;\n\n  FOR i IN 1..greatest(p_max_iterations, 1) LOOP\n    raw := rvbbit.clover_llm_draft_spec(task);\n    -- strip accidental markdown fences despite instructions\n    raw := regexp_replace(regexp_replace(coalesce(raw,''), '^\\s*```(json)?\\s*', ''), '\\s*```\\s*$', '');\n\n    BEGIN\n      spec := raw::jsonb;\n    EXCEPTION WHEN OTHERS THEN\n      task := base_task || chr(10) || 'Your previous reply was not valid JSON ('\n              || SQLERRM || '). Reply with ONLY the JSON object.';\n      CONTINUE;\n    END;\n\n    -- validate the spec\n    violations := ARRAY[]::text[];\n    final_name := coalesce(p_name, spec->>'name');\n    rt := coalesce(p_return_type, spec->>'return_type');\n    IF final_name IS NULL OR final_name !~ '^[a-z][a-z0-9_]{2,40}$' THEN\n      violations := violations || 'name missing or not snake_case (3-40 chars)';\n    END IF;\n    IF rt IS NULL OR rt NOT IN ('bool','text','float8','jsonb') THEN\n      violations := violations || 'return_type must be bool|text|float8|jsonb';\n    END IF;\n    BEGIN\n      SELECT array_agg(x) INTO arg_arr FROM jsonb_array_elements_text(spec->'arg_names') x;\n    EXCEPTION WHEN OTHERS THEN arg_arr := NULL;\n    END;\n    IF arg_arr IS NULL OR array_length(arg_arr, 1) NOT BETWEEN 1 AND 4 THEN\n      violations := violations || 'arg_names must be a list of 1-4 names';\n    ELSE\n      FOREACH a IN ARRAY arg_arr LOOP\n        IF a !~ '^[a-z][a-z0-9_]{0,30}$' THEN\n          violations := violations || format('bad arg name: %s', a);\n        ELSIF (spec->>'prompt') NOT LIKE '%{{' || a || '}}%' THEN\n          violations := violations || format('prompt does not reference {{%s}}', a);\n        END IF;\n      END LOOP;\n    END IF;\n    tests_in := spec->'tests';\n    IF tests_in IS NULL OR jsonb_typeof(tests_in) <> 'array' OR jsonb_array_length(tests_in) < 2 THEN\n      violations := violations || 'tests must be a list of at least 2 cases';\n    END IF;\n\n    IF array_length(violations, 1) > 0 THEN\n      task := base_task || chr(10) || 'Your previous spec had problems: '\n              || array_to_string(violations, '; ')\n              || chr(10) || 'Previous spec: ' || raw\n              || chr(10) || 'Reply with the full corrected JSON object.';\n      CONTINUE;\n    END IF;\n\n    -- create under a temp name and test\n    tmp := 'mkop_' || substr(md5(clock_timestamp()::text || random()::text), 1, 8);\n    tests_sql := '[]'::jsonb;\n    FOR t IN SELECT * FROM jsonb_array_elements(tests_in) LOOP\n      SELECT array_agg(x) INTO test_args FROM jsonb_array_elements_text(t->'args') x;\n      IF test_args IS NULL OR array_length(test_args, 1) <> array_length(arg_arr, 1) THEN\n        tests_sql := NULL; EXIT;\n      END IF;\n      call_sql := format('SELECT rvbbit.%I(%s)', tmp,\n                         (SELECT string_agg(quote_literal(x), ', ') FROM unnest(test_args) x));\n      tests_sql := tests_sql || jsonb_build_array(jsonb_build_object(\n        'name', coalesce(t->>'name', 'case'),\n        'sql', call_sql,\n        'expect', t->'expect',\n        'description', ''));\n    END LOOP;\n    IF tests_sql IS NULL THEN\n      task := base_task || chr(10)\n              || 'Your previous spec had tests whose args count did not match arg_names. '\n              || 'Previous spec: ' || raw || chr(10) || 'Reply with the full corrected JSON object.';\n      CONTINUE;\n    END IF;\n\n    PERFORM rvbbit.create_operator(\n      op_name := tmp,\n      op_arg_names := arg_arr,\n      op_return_type := rt,\n      op_description := '[maker temp] ' || coalesce(spec->>'description', p_description),\n      op_tests := tests_sql,\n      op_steps := jsonb_build_array(jsonb_build_object(\n        'name', 'main', 'kind', 'llm',\n        'provider', 'clover_llm', 'model', 'gemma4',\n        'max_tokens', 800, 'temperature', 0.1,\n        'user', spec->>'prompt')));\n\n    SELECT jsonb_agg(to_jsonb(r)), count(*) FILTER (WHERE NOT r.passed), count(*)\n      INTO results, n_fail, n_total\n      FROM rvbbit.run_tests(tmp) r;\n\n    -- always remove the temp operator\n    sig := array_to_string(array_fill('text'::text, ARRAY[array_length(arg_arr, 1)]), ', ') || ', jsonb';\n    EXECUTE format('DROP FUNCTION IF EXISTS rvbbit.%I(%s)', tmp, sig);\n    DELETE FROM rvbbit.operators WHERE name = tmp;\n\n    IF n_total > 0 AND n_fail = 0 THEN\n      IF p_dry_run THEN\n        RETURN jsonb_build_object('created', false, 'dry_run', true, 'iterations', i,\n                                  'name', final_name, 'spec', spec, 'test_results', results);\n      END IF;\n      -- promote: same spec, real name, tests pointed at the real name\n      PERFORM rvbbit.create_operator(\n        op_name := final_name,\n        op_arg_names := arg_arr,\n        op_return_type := rt,\n        op_description := coalesce(spec->>'description', p_description) || ' (built by clover_llm_make_operator)',\n        op_tests := (SELECT jsonb_agg(jsonb_set(e, '{sql}',\n                       to_jsonb(replace(e->>'sql', 'rvbbit.' || tmp, 'rvbbit.' || final_name))))\n                     FROM jsonb_array_elements(tests_sql) e),\n        op_steps := jsonb_build_array(jsonb_build_object(\n          'name', 'main', 'kind', 'llm',\n          'provider', 'clover_llm', 'model', 'gemma4',\n          'max_tokens', 800, 'temperature', 0.1,\n          'user', spec->>'prompt')));\n      RETURN jsonb_build_object('created', true, 'name', final_name, 'iterations', i,\n                                'return_type', rt, 'arg_names', to_jsonb(arg_arr),\n                                'tests_passed', n_total, 'spec', spec, 'test_results', results);\n    END IF;\n\n    SELECT string_agg(format('%s: got %s, expected %s %s',\n                             r->>'test_name', coalesce(r->>'actual', 'NULL'),\n                             r->>'expected', coalesce(r->>'error', '')), '; ')\n      INTO fail_txt\n      FROM jsonb_array_elements(coalesce(results, '[]'::jsonb)) r\n      WHERE NOT (r->>'passed')::boolean;\n    task := base_task || chr(10) || 'Previous spec: ' || raw\n            || chr(10) || 'It was created and tested; these tests FAILED: ' || coalesce(fail_txt, '(no tests ran)')\n            || chr(10) || 'Decide whether the prompt or the tests were wrong, fix, and reply with the full corrected JSON object.';\n  END LOOP;\n\n  RETURN jsonb_build_object('created', false, 'iterations', p_max_iterations,\n                            'last_spec', spec, 'last_failures', fail_txt,\n                            'last_violations', to_jsonb(violations), 'last_raw', left(raw, 400),\n                            'error', 'did not converge; refine the description or raise p_max_iterations');\nEND $$;",
              "SELECT rvbbit.register_backend('cluster', 'http://clover.rvbb.it:8090/b/cluster/predict', 'rvbbit', 1, 1, 300000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.register_backend('tabular_explain', 'http://clover.rvbb.it:8090/b/tabular_explain/predict', 'rvbbit', 1, 1, 600000, 'RVBBIT_CLOVER_KEY');",
              "SELECT rvbbit.reload_backends();",
              "SELECT rvbbit.create_operator('clover_classify_scores', ARRAY['t','labels'], 'jsonb', op_description := 'Clover-ML: zero-shot classification with every candidate score and the winning label', op_tests := jsonb_build_array(jsonb_build_object('name','returns_scores','sql',$test$SELECT rvbbit.clover_classify_scores('refund request for damaged item','billing, shipping, returns, technical support')::text$test$,'expect',jsonb_build_object('type','contains','value','scores'))), op_steps := jsonb_build_array(jsonb_build_object('name','c','kind','specialist','specialist','classify','inputs',jsonb_build_object('text','{{t}}','labels','{{labels}}'))));",
              "SELECT rvbbit.create_operator('clover_nli', ARRAY['premise','hypothesis'], 'jsonb', op_description := 'Clover-ML: full 3-way natural-language-inference result with entailment, neutral, and contradiction scores', op_tests := jsonb_build_array(jsonb_build_object('name','contradiction_score','sql',$test$SELECT rvbbit.clover_nli('The store is open','The store is closed')::text$test$,'expect',jsonb_build_object('type','contains','value','contradiction'))), op_steps := jsonb_build_array(jsonb_build_object('name','n','kind','specialist','specialist','nli3','inputs',jsonb_build_object('premise','{{premise}}','hypothesis','{{hypothesis}}'))));",
              "SELECT rvbbit.create_operator('clover_language_info', ARRAY['t'], 'jsonb', op_description := 'Clover-ML: language code plus confidence for routing and quality thresholds', op_tests := jsonb_build_array(jsonb_build_object('name','french_confidence','sql',$test$SELECT rvbbit.clover_language_info('bonjour mes amis')::text$test$,'expect',jsonb_build_object('type','contains','value','confidence'))), op_steps := jsonb_build_array(jsonb_build_object('name','l','kind','specialist','specialist','language','inputs',jsonb_build_object('text','{{t}}'))));",
              "SELECT rvbbit.create_operator('clover_embed', ARRAY['t'], 'jsonb', op_description := 'Clover-ML: reusable text embedding vector (arctic-embed-l-v2, 1024-dim) — KNN, similarity & clustering feedstock', op_tests := jsonb_build_array(jsonb_build_object('name','text_vector','sql',$test$SELECT jsonb_array_length(rvbbit.clover_embed('fast analytical database')) > 100$test$,'expect',jsonb_build_object('type','exact','value','true'))), op_steps := jsonb_build_array(jsonb_build_object('name','e','kind','specialist','specialist','embed','inputs',jsonb_build_object('text','{{t}}'))));",
              "SELECT rvbbit.create_operator('clover_image_embed', ARRAY['item'], 'jsonb', op_description := 'Clover-ML: reusable SigLIP2 embedding for an image URL/data URI or text description', op_tests := jsonb_build_array(jsonb_build_object('name','text_vector','sql',$test$SELECT jsonb_array_length(rvbbit.clover_image_embed('a red bicycle')) > 100$test$,'expect',jsonb_build_object('type','exact','value','true'))), op_steps := jsonb_build_array(jsonb_build_object('name','e','kind','specialist','specialist','image_embed','inputs',jsonb_build_object('text','{{item}}'))));",
              "SELECT rvbbit.create_operator('clover_cluster', ARRAY['values','num_clusters'], 'jsonb', op_description := 'Clover-ML: cluster a JSON array of texts with hosted embeddings plus K-means; returns assignments, cluster members, and representatives', op_tests := jsonb_build_array(jsonb_build_object('name','two_groups','sql',$test$SELECT jsonb_array_length(rvbbit.clover_cluster(jsonb_build_array('New York','Boston','Chicago','Paris','Lyon','Marseille')::text,'2')->'assignments')$test$,'expect',jsonb_build_object('type','exact','value','6'))), op_steps := jsonb_build_array(jsonb_build_object('name','c','kind','specialist','specialist','cluster','inputs',jsonb_build_object('values','{{values}}','num_clusters','{{num_clusters}}'))));",
              "SELECT rvbbit.create_operator('clover_explain', ARRAY['model_blob_b64','model_sha256','features','feature_names'], 'jsonb', op_description := 'Clover-ML: SHAP feature attributions for a fitted TabPFN or anomaly model; returns per-row contributions, base values, predictions, and score kind', op_tests := jsonb_build_array(jsonb_build_object('name','tabpfn_regressor','sql',$test$WITH m AS (SELECT rvbbit.clover_fit('regressor',jsonb_build_array(jsonb_build_array(1,0),jsonb_build_array(2,0),jsonb_build_array(3,0),jsonb_build_array(4,0),jsonb_build_array(5,0),jsonb_build_array(6,0))::text,'[2,4,6,8,10,12]') AS j) SELECT jsonb_array_length(rvbbit.clover_explain(j->>'blob_b64',j->>'blob_sha256','[[7,0]]','[\"signal\",\"noise\"]')->'shap_values'->0) FROM m$test$,'expect',jsonb_build_object('type','exact','value','2')),jsonb_build_object('name','anomaly_model','sql',$test$WITH m AS (SELECT rvbbit.clover_anomaly_fit('[[1,1],[1.1,0.9],[0.9,1.2],[10,10]]') AS j) SELECT rvbbit.clover_explain(j->>'blob_b64',j->>'blob_sha256','[[10,10]]','[\"x\",\"y\"]')->>'score_kind' FROM m$test$,'expect',jsonb_build_object('type','contains','value','anomaly_score'))), op_steps := jsonb_build_array(jsonb_build_object('name','x','kind','specialist','specialist','tabular_explain','inputs',jsonb_build_object('model_blob_b64','{{model_blob_b64}}','model_sha256','{{model_sha256}}','X','{{features}}','feature_names','{{feature_names}}'))));",
              "SELECT rvbbit.create_operator('clover_llm_same_entity', ARRAY['left_value','right_value','entity_type'], 'bool', op_description := 'Clover-LLM: TRUE when two values identify the same real-world entity, for fuzzy joins and deduplication', op_tests := jsonb_build_array(jsonb_build_object('name','ibm_alias','sql',$test$SELECT rvbbit.clover_llm_same_entity('IBM','International Business Machines','company')$test$,'expect',jsonb_build_object('type','exact','value','true')),jsonb_build_object('name','different_companies','sql',$test$SELECT rvbbit.clover_llm_same_entity('Toyota','Honda','company')$test$,'expect',jsonb_build_object('type','exact','value','false'))), op_steps := jsonb_build_array(jsonb_build_object('name','main','kind','llm','provider','clover_llm','model','gemma4','user','Do these values identify the exact same real-world entity?\n\nENTITY TYPE: {{entity_type}}\nLEFT: {{left_value}}\nRIGHT: {{right_value}}\n\nAliases, abbreviations, harmless formatting differences, and known official names may match. Sharing an industry, category, surname, or similar meaning is not enough. If identity is materially ambiguous, return false. Return ONLY true or false.','max_tokens',6)));",
              "SELECT rvbbit.create_operator('clover_llm_merge_records', ARRAY['records','strategy'], 'jsonb', op_description := 'Clover-LLM: merge a JSON array of duplicate records into one canonical golden record using an explicit conflict strategy', op_tests := jsonb_build_array(jsonb_build_object('name','complementary_fields','sql',$test$SELECT rvbbit.clover_llm_merge_records(jsonb_build_array(jsonb_build_object('name','JOHN SMITH','email','john@example.com','phone',null),jsonb_build_object('name','John Smith','email',null,'phone','555-1234'))::text,'best_quality')::text$test$,'expect',jsonb_build_object('type','contains','value','555-1234')),jsonb_build_object('name','stats','sql',$test$SELECT rvbbit.clover_llm_merge_records(jsonb_build_array(jsonb_build_object('id',1,'name','Acme'),jsonb_build_object('id',1,'website','acme.com'))::text,'best_quality')::text$test$,'expect',jsonb_build_object('type','contains','value','_merge_stats'))), op_steps := jsonb_build_array(jsonb_build_object('name','main','kind','llm','provider','clover_llm','model','gemma4','system','You merge duplicate business records. Return one valid JSON object only, without markdown.','user','Merge the JSON array of records into one canonical record.\n\nSTRATEGY: {{strategy}}\nRECORDS: {{records}}\n\nRules:\n- Include every field appearing in any record.\n- Prefer populated, valid, well-formatted values.\n- Supported strategies: best_quality, prefer_recent, prefer_first, prefer_longest, unanimous_only.\n- Use null only when all records lack a value.\n- Include _merge_stats with records_merged, conflicting_fields, and strategy.\nReturn ONLY one valid JSON object.','max_tokens',1200,'temperature',0.1)));",
              "SELECT rvbbit.create_operator('clover_llm_timeline', ARRAY['t','reference_date'], 'jsonb', op_description := 'Clover-LLM: extract a chronological event timeline from text with normalized timestamps, actors, and event types', op_tests := jsonb_build_array(jsonb_build_object('name','clock_normalization','sql',$test$SELECT rvbbit.clover_llm_timeline('The server crashed at 3:15 PM. We deployed a fix at 4:30 PM.','2026-07-16')::text$test$,'expect',jsonb_build_object('type','contains','value','15:15')),jsonb_build_object('name','relative_date','sql',$test$SELECT rvbbit.clover_llm_timeline('Yesterday Maya signed the contract.','2026-07-16')::text$test$,'expect',jsonb_build_object('type','contains','value','2026-07-15'))), op_steps := jsonb_build_array(jsonb_build_object('name','main','kind','llm','provider','clover_llm','model','gemma4','system','You are a JSON API, not a chat assistant. Output one compact JSON array. The first character of your response must be [ and the last character must be ]. Never use Markdown or code fences.','user','Extract every stated event and return events chronologically.\n\nTEXT: {{t}}\nREFERENCE DATE: {{reference_date}}\n\nREFERENCE DATE anchors relative dates: yesterday is one calendar day before it, today is the same date, and tomorrow is one calendar day after it. Use YYYY-MM-DD when no time is stated. Use ISO 8601 date-time when a time is stated and convert 12-hour times to 24-hour time.\n\nEvery event object must contain exactly these fields: timestamp, event, actors, type, sequence. actors is an array; use [] when no actor is named. Never discard an explicitly stated event because an actor or clock time is missing.\n\nExample: Yesterday the contract was signed, with reference date 2026-07-16, becomes [{\"timestamp\":\"2026-07-15\",\"event\":\"contract signed\",\"actors\":[],\"type\":\"contract\",\"sequence\":1}].\n\nDo not invent events. Output one compact JSON array only. Begin with [ and end with ].','max_tokens',1400,'temperature',0.1)));",
              "SELECT rvbbit.create_operator('clover_llm_consensus', ARRAY['texts','focus'], 'text', op_description := 'Clover-LLM: synthesize the shared consensus across a JSON array of comments, tickets, reviews, or findings', op_tests := jsonb_build_array(jsonb_build_object('name','service_consensus','sql',$test$SELECT rvbbit.clover_llm_consensus(jsonb_build_array('The staff were helpful','Great customer service','Support solved my issue quickly','Friendly service team')::text,'main shared finding')$test$,'expect',jsonb_build_object('type','contains','value','service'))), op_steps := jsonb_build_array(jsonb_build_object('name','main','kind','llm','provider','clover_llm','model','gemma4','system','You synthesize consensus without inventing agreement. Return concise plain text only.','user','Find the strongest shared consensus across these JSON-array items.\n\nFOCUS: {{focus}}\nITEMS: {{texts}}\n\nState what most items agree on, qualify disagreements or weak evidence, and do not merely list every item. Return ONLY a concise 1-3 sentence consensus.','max_tokens',400,'temperature',0.1)));",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','email','sql',$test$SELECT rvbbit.clover_pii('Contact Sarah Chen at sarah@acme.com or 555-867-5309')::text$test$,'expect',jsonb_build_object('type','contains','value','sarah@acme.com')),jsonb_build_object('name','ssn','sql',$test$SELECT rvbbit.clover_pii('SSN on file: 123-45-6789')::text$test$,'expect',jsonb_build_object('type','contains','value','123-45-6789'))) WHERE name='clover_pii';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','close','sql',$test$SELECT rvbbit.clover_similar('fast database','quick sql engine')$test$,'expect',jsonb_build_object('type','min','value','0.45')),jsonb_build_object('name','far','sql',$test$SELECT rvbbit.clover_similar('fast database','a nice sandwich')$test$,'expect',jsonb_build_object('type','max','value','0.35'))) WHERE name='clover_similar';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','scores','sql',$test$SELECT rvbbit.clover_moderate('you are a worthless idiot')::text$test$,'expect',jsonb_build_object('type','contains','value','insult'))) WHERE name='clover_moderate';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','scores_outlier','sql',$test$WITH m AS (SELECT rvbbit.clover_anomaly_fit('[[1,1],[1.1,0.9],[0.9,1.2],[10,10]]') AS j) SELECT jsonb_array_length(rvbbit.clover_anomaly_score(j->>'blob_b64','[[10,10]]')->'scores') FROM m$test$,'expect',jsonb_build_object('type','exact','value','1'))) WHERE name='clover_anomaly_score';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','arithmetic','sql',$test$SELECT rvbbit.clover_llm_ask('What is two plus two?')$test$,'expect',jsonb_build_object('type','not_empty'))) WHERE name='clover_llm_ask';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','structured_engine','sql',$test$SELECT rvbbit.clover_document_parse('https://rvbbit.ai/data/clover-tests/invoice.png')->>'engine'$test$,'expect',jsonb_build_object('type','contains','value','granite_docling'))) WHERE name='clover_document_parse';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','named_target','sql',$test$SELECT jsonb_array_length(rvbbit.clover_forecast_drivers('{\"sales\":[1,2,3,4,5,6,7,8,9,10,11,12]}','{}','{}','4')->'series'->'sales'->'median')$test$,'expect',jsonb_build_object('type','exact','value','4'))) WHERE name='clover_forecast_drivers';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','score_length','sql',$test$SELECT jsonb_array_length(rvbbit.clover_series_anomalies((SELECT jsonb_agg(sin(i / 10.0) ORDER BY i)::text FROM generate_series(1,1536) i))->'scores')$test$,'expect',jsonb_build_object('type','exact','value','1536'))) WHERE name='clover_series_anomalies';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','fills_null','sql',$test$WITH s AS (SELECT jsonb_agg(CASE WHEN i=250 THEN NULL ELSE sin(i / 10.0) END ORDER BY i)::text AS v FROM generate_series(1,512) i) SELECT jsonb_array_length(rvbbit.clover_series_impute(v)->'values') FROM s$test$,'expect',jsonb_build_object('type','exact','value','512'))) WHERE name='clover_series_impute';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','has_vector','sql',$test$SELECT (jsonb_array_length(rvbbit.clover_series_embed((SELECT jsonb_agg(sin(i / 10.0) ORDER BY i)::text FROM generate_series(1,512) i))->'embedding') > 0)::text$test$,'expect',jsonb_build_object('type','exact','value','true'))) WHERE name='clover_series_embed';",
              "UPDATE rvbbit.operators SET tests = jsonb_build_array(jsonb_build_object('name','same_shape','sql',$test$WITH s AS (SELECT jsonb_agg(sin(i / 10.0) ORDER BY i)::text AS v FROM generate_series(1,512) i) SELECT rvbbit.clover_series_similarity(v,v) FROM s$test$,'expect',jsonb_build_object('type','min','value','0.99'))) WHERE name='clover_series_similarity';",
              "UPDATE rvbbit.backends b SET source_provider='rvbbit.ai', source_model=v.source_model, source_revision=v.source_revision, install_manifest=jsonb_build_object('capability','managed/clover','backend',v.backend_name) FROM (VALUES ('embed','Snowflake/snowflake-arctic-embed-l-v2.0','clover-v1'),('rerank','BAAI/bge-reranker-v2-m3','clover-v1'),('sentiment','cardiffnlp/twitter-xlm-roberta-base-sentiment','clover-v1.0'),('nli','MoritzLaurer/deberta-v3-large-zeroshot-v2.0','clover-v1'),('nli3','MoritzLaurer/deberta-v3-large-mnli-fever-anli-ling-wanli','clover-v1'),('classify','MoritzLaurer/deberta-v3-large-zeroshot-v2.0','clover-v1'),('toxicity','unitary/toxic-bert','clover-v1'),('language','papluca/xlm-roberta-base-language-detection','clover-v1'),('extract','urchade/gliner_large-v2.1','clover-v1'),('ocr','ibm-granite/granite-docling-258M','clover-v2'),('document_parse','ibm-granite/granite-docling-258M','clover-v2'),('transcribe','openai/whisper-large-v3-turbo','clover-v1'),('forecast','amazon/chronos-2','clover-v2'),('timeseries_anomalies','ibm-granite/granite-timeseries-tspulse-r1','clover-v2-cpu'),('timeseries_impute','ibm-granite/granite-timeseries-tspulse-r1','clover-v2-cpu'),('timeseries_embed','ibm-granite/granite-timeseries-tspulse-r1','clover-v2-cpu'),('timeseries_similarity','ibm-granite/granite-timeseries-tspulse-r1','clover-v2-cpu'),('image_embed','google/siglip2-so400m-patch16-384','clover-v1'),('tabular_fit','Prior-Labs/TabPFN-v2-clf+reg','clover-v1'),('tabular_predict','Prior-Labs/TabPFN-v2-clf+reg','clover-v1'),('tabular_explain','Prior-Labs/TabPFN-v2-clf+reg + SHAP','clover-v1'),('anomaly_fit','scikit-learn/IsolationForest','clover-v1'),('anomaly_score','scikit-learn/IsolationForest','clover-v1'),('relations','Babelscape/rebel-large','clover-v1'),('cluster','Snowflake/snowflake-arctic-embed-l-v2.0 + KMeans/HDBSCAN','clover-v1'),('clover_llm','nvidia/Gemma-4-31B-IT-NVFP4','clover-llm-v1')) AS v(backend_name,source_model,source_revision) WHERE b.name=v.backend_name;",
              "SELECT rvbbit.create_operator('clover_web_scrape', ARRAY['url'], 'jsonb', op_description := 'Clover-Web: fetch a public HTTP(S) HTML page or supported document and return cleaned Markdown, metadata, provenance, and diagnostics; static content only (no JavaScript, login, cookies, or private-network targets)', op_steps := jsonb_build_array(jsonb_build_object('name','w','kind','specialist','specialist','web_scrape','inputs',jsonb_build_object('url','{{url}}'))));",
              "SELECT rvbbit.create_operator('clover_web_markdown', ARRAY['url'], 'text', op_description := 'Clover-Web: fetch a public HTTP(S) HTML page or supported document and return cleaned Markdown; static content only (no JavaScript, login, cookies, or private-network targets)', op_steps := jsonb_build_array(jsonb_build_object('name','w','kind','specialist','specialist','web_scrape','inputs',jsonb_build_object('url','{{url}}')),jsonb_build_object('name','m','kind','code','fn','json_get','inputs',jsonb_build_object('value','{{steps.w.output}}','path','markdown'))));",
              "SELECT rvbbit.create_operator('clover_web_research', ARRAY['question'], 'jsonb', op_description := 'Clover-Research: cited public-web research with typed knowledge, tenant-scoped snapshots, exact claim lineage, contradictions, gaps, and a complete bounded trail; no browser actions, login, or side effects', op_steps := jsonb_build_array(jsonb_build_object('name','r','kind','specialist','specialist','web_research','inputs',jsonb_build_object('question','{{question}}'))));",
              "SELECT rvbbit.create_operator('clover_web_research_deep', ARRAY['question'], 'jsonb', op_description := 'Clover-Research deep mode: research a question, identify material gaps, then spend one bounded follow-the-evidence pass on linked or newly searched primary sources', op_steps := jsonb_build_array(jsonb_build_object('name','r','kind','specialist','specialist','web_research','inputs',jsonb_build_object('question','{{question}}','mode','deep'))));",
              "SELECT rvbbit.create_operator('clover_web_watch', ARRAY['question','seed_urls'], 'jsonb', op_description := 'Clover-Research watch mode: conditionally refresh a JSON array of stable public URLs, reuse byte-identical prior synthesis, and report source and claim changes', op_steps := jsonb_build_array(jsonb_build_object('name','r','kind','specialist','specialist','web_research','inputs',jsonb_build_object('question','{{question}}','seed_urls','{{seed_urls}}','mode','watch','search',false))));",
              "UPDATE rvbbit.operators SET cache_policy='never' WHERE name IN ('clover_web_scrape','clover_web_markdown','clover_web_research','clover_web_research_deep','clover_web_watch');",
              "UPDATE rvbbit.backends SET source_provider='rvbbit.ai', source_model='firecrawl/html-extractor + firecrawl/anydoc', source_revision='clover-web-v0.2', install_manifest=jsonb_build_object('capability','managed/clover','backend','web_scrape') WHERE name='web_scrape';",
              "UPDATE rvbbit.backends SET source_provider='rvbbit.ai', source_model='google/gemma-4-31b-it + OpenRouter Exa + Clover Web + tenant-scoped evidence memory', source_revision='clover-research-v0.2', install_manifest=jsonb_build_object('capability','managed/clover','backend','web_research') WHERE name='web_research';",
              "SELECT rvbbit.set_cost_policy('backend','clover_llm','model_rate', input_per_mtok => 0.10, output_per_mtok => 0.20, model => 'gemma4', notes => 'Clover included value: would-be a-la-carte cost of hosted gemma4; covered by subscription, never billed');",
              "SELECT rvbbit.create_operator('clover_triples', ARRAY['text','focus'], 'jsonb',\n  op_description := 'Clover-LLM: extract knowledge-graph triples from text as strict JSON — same contract as the built-in rvbbit.triples (subject_kind/subject/predicate/object_kind/object/confidence/evidence/properties), hosted gemma4',\n  op_steps := jsonb_build_array(jsonb_build_object(\n    'name','main','kind','llm','provider','clover_llm','model','gemma4',\n    'system','You are a strict knowledge graph extraction engine. Extract concise, useful facts as JSON triples. Return ONLY a valid JSON array. Each item MUST use exactly these keys unless optional values are needed: subject_kind, subject, predicate, object_kind, object, confidence, evidence, properties. subject and object are entity/value labels. subject_kind and object_kind are short lowercase types such as person, organization, customer, product, issue, event, metric, document, place, date, value, or concept. predicate is a snake_case relationship such as works_at, reported, affects, requested, approved, located_in, uses, owns, depends_on, caused_by, deadline_is, has_status. confidence is 0.0 to 1.0. evidence is a short quote or sentence from the input. properties is an optional object. Extract explicit facts first. Include only high-signal facts. Empty input or no facts returns []. No markdown, no commentary, no code fence.',\n    'user', E'FOCUS: {{focus}}\\n\\nTEXT:\\n{{text}}\\n\\nReturn JSON array only.',\n    'max_tokens', 1600, 'temperature', 0.1)),\n  op_tests := jsonb_build_array(\n    jsonb_build_object('name','extracts_facts',\n      'sql','SELECT (rvbbit.clover_triples(''Sarah Chen works at Acme Corp and reported the Q3 pipeline outage on March 3'', ''all''))::text',\n      'expect', jsonb_build_object('type','contains','value','works_at')),\n    jsonb_build_object('name','valid_contract',\n      'sql','SELECT rvbbit.triples_valid((rvbbit.clover_triples(''Maria Lopez owns Bluebird Bakery in Portland'', ''all''))::text)::text',\n      'expect', jsonb_build_object('type','contains','value','true')),\n    jsonb_build_object('name','empty_input',\n      'sql','SELECT (rvbbit.clover_triples('''', ''all''))::text',\n      'expect', jsonb_build_object('type','exact','value','[]'))\n  ));",
              "CREATE OR REPLACE FUNCTION rvbbit.bind_triples_to_clover()\nRETURNS text\nLANGUAGE plpgsql\nAS $btc$\nBEGIN\n    -- Route the built-in triples operator through Clover's hosted gemma4.\n    -- Every KG system (data_crawl, Document Brain, Scry data layer) calls\n    -- the operator NAME, so this one change makes them all work on installs\n    -- with no local LLM provider configured. Reversible: unbind_triples_clover().\n    UPDATE rvbbit.operators\n    SET steps = (SELECT steps FROM rvbbit.operators WHERE name = 'clover_triples'),\n        updated_at = clock_timestamp()\n    WHERE name = 'triples';\n    IF NOT FOUND THEN\n        RETURN 'triples operator not found — is pg_rvbbit installed?';\n    END IF;\n    IF (SELECT steps FROM rvbbit.operators WHERE name = 'triples') IS NULL THEN\n        RETURN 'clover_triples is not installed — install the Clover capability first';\n    END IF;\n    RETURN 'rvbbit.triples now runs on Clover (gemma4). Revert: SELECT rvbbit.unbind_triples_clover();';\nEND\n$btc$;",
              "CREATE OR REPLACE FUNCTION rvbbit.unbind_triples_clover()\nRETURNS text\nLANGUAGE plpgsql\nAS $utc$\nBEGIN\n    -- Restore the triples operator to its own prompt/model body.\n    UPDATE rvbbit.operators\n    SET steps = NULL, updated_at = clock_timestamp()\n    WHERE name = 'triples';\n    RETURN 'rvbbit.triples restored to its configured model (' ||\n           coalesce((SELECT model FROM rvbbit.operators WHERE name = 'triples'), '?') || ')';\nEND\n$utc$;",
              "CREATE OR REPLACE FUNCTION rvbbit.bind_extract_entities_to_clover()\nRETURNS text\nLANGUAGE plpgsql\nAS $bee$\nBEGIN\n    -- Create (or rebind) the extract_entities operator the Brain's NER\n    -- enrichment hardcodes, routed through Clover's hosted GLiNER-large\n    -- ('extract' backend). Covers installs where the local GLiNER pack is\n    -- absent or broken. Same contract as the pack op: (text, labels) ->\n    -- jsonb array of {text, label, ...}. Revert: unbind_extract_entities_clover().\n    IF NOT EXISTS (SELECT 1 FROM rvbbit.backends WHERE name = 'extract') THEN\n        RETURN 'Clover ''extract'' backend is not registered — install the Clover capability first';\n    END IF;\n    PERFORM rvbbit.create_operator('extract_entities', ARRAY['text','labels'], 'jsonb',\n      op_description := 'Extract entities from text with comma-separated labels (bound to Clover hosted GLiNER-large)',\n      op_steps := jsonb_build_array(jsonb_build_object(\n        'name','e','kind','specialist','specialist','extract',\n        'inputs', jsonb_build_object('text','{{text}}','labels','{{labels}}'))));\n    RETURN 'rvbbit.extract_entities now runs on Clover (GLiNER-large). Brain NER enrichment is live. Revert: SELECT rvbbit.unbind_extract_entities_clover();';\nEND\n$bee$;",
              "CREATE OR REPLACE FUNCTION rvbbit.unbind_extract_entities_clover()\nRETURNS text\nLANGUAGE plpgsql\nAS $uee$\nBEGIN\n    -- Restore extract_entities to the local GLiNER pack backend\n    -- (extract_gliner). Errors helpfully if that pack isn't installed.\n    IF NOT EXISTS (SELECT 1 FROM rvbbit.backends WHERE name = 'extract_gliner') THEN\n        RETURN 'local GLiNER pack backend (extract_gliner) is not registered — leaving the Clover binding in place';\n    END IF;\n    PERFORM rvbbit.create_operator('extract_entities', ARRAY['text','labels'], 'jsonb',\n      op_description := 'Extract entities from text using GLiNER with comma-separated labels.',\n      op_steps := jsonb_build_array(jsonb_build_object(\n        'name','e','kind','specialist','specialist','extract_gliner',\n        'inputs', jsonb_build_object('text','{{text}}','labels','{{labels}}'))));\n    RETURN 'rvbbit.extract_entities restored to the local GLiNER pack (extract_gliner)';\nEND\n$uee$;",
              "DO $clover_default$\nDECLARE cur text; ok boolean;\nBEGIN\n    -- Adopt clover_llm as the default LLM provider ONLY when the\n    -- current default can't authenticate (virgin boxes ship\n    -- default_provider=openrouter with no key, which strands every\n    -- core LLM operator on a model this key can't reach). Boxes\n    -- with a working provider are left exactly as they are.\n    SELECT trim(both '\"' from value::text) INTO cur\n      FROM rvbbit.settings WHERE key = 'default_provider';\n    SELECT (b.auth_header_env IS NULL\n            OR rvbbit.env_present(b.auth_header_env)\n            OR coalesce(rvbbit.get_secret(b.auth_header_env), '') <> '')\n      INTO ok FROM rvbbit.backends b WHERE b.name = cur;\n    IF cur IS DISTINCT FROM 'clover_llm' AND NOT coalesce(ok, false) THEN\n        PERFORM rvbbit.set_default_provider('clover_llm');\n        UPDATE rvbbit.operators SET model = ''\n         WHERE model LIKE 'openai/%';\n    END IF;\nEND $clover_default$;"
            ]
          },
          "tagline": "Semantic SQL, batteries included: 62 operators — calibrated ML, structured document and time-series specialists unmetered on every tier, plus pinned LLMs and evidence-first web research priced by speed, not per call.",
          "value_props": [
            {
              "title": "Lane-priced LLM",
              "detail": "Unlimited inference within your concurrent lanes. Metered pricing taxes curiosity; capacity pricing taxes only impatience."
            },
            {
              "title": "Unmetered ML",
              "detail": "All 29 specialist operators are unmetered at every tier — GPU batching makes them nearly free to serve, so we don’t meter them at all."
            },
            {
              "title": "Tested",
              "detail": "The operator suite is vetted against a public embedded battery; known model weaknesses stay visible instead of being hidden."
            },
            {
              "title": "Stable",
              "detail": "Pinned model versions — the models under your verdicts never change silently."
            },
            {
              "title": "Yours",
              "detail": "Fitted models (TabPFN, anomaly) are returned to YOUR database as blobs — nothing a customer makes persists on our side."
            }
          ],
          "free_tier": {
            "note": "Every operator on your own data, no credit card — unmetered ML specialists plus one LLM lane. Upgrade the first time a big LLM query makes you impatient.",
            "cta_url": "https://rvbbit.ai/buy/clover-free"
          },
          "highlights": [
            "62 operators, one flat sub: match, classify with scores, NLI, sentiment, extract, PII, structured document parsing, transcribe, multivariate forecasting with business drivers, time-series anomaly/imputation/similarity, cluster, fit/predict/explain, relations, safe web extraction, and bounded cited web research — plus LLM entity resolution, golden records, timelines, consensus, and general reasoning",
            "Granite-Docling turns PDFs and images into Markdown plus evidence-linked blocks, tables, cells and page geometry; plain-text OCR remains compatible",
            "Chronos-2 forecasts related metrics together and can incorporate historical and known-future drivers such as promotions, holidays, weather or staffing",
            "TSPulse adds CPU-side anomaly scoring, missing-point reconstruction and semantic time-series similarity without consuming L4 VRAM",
            "clover_llm_make_operator: an operator that BUILDS operators — plain English in, a created + battery-tested SQL operator out",
            "ML specialists are unmetered on every tier, including Free — lanes only pace the LLM",
            "clover_llm_implies passes the quantifier cases (all -> some) that fast NLI models miss — same battery, documented side by side",
            "clover_llm_extract: freeform text -> JSON per a schema you write in plain English",
            "Drop-in for any operator, agent(), or flow that calls an LLM — plus raw OpenAI-compatible /v1 access",
            "Pinned model identities are published in the catalog; database receipts name the managed backend used for each call",
            "Install is metadata only — nothing runs on your box",
            "You could self-host this — the operators are open. This is the paved road.",
            "Every managed call is receipted with its would-be à la carte value — watch what your subscription is worth, clearly separated from real spend",
            "clover_triples: knowledge-graph extraction on the same contract as the built-in rvbbit.triples — one optional bind_triples_to_clover() call routes every KG system (data_crawl, Document Brain, Scry) through Clover when no local LLM provider is configured",
            "bind_extract_entities_to_clover(): one call routes the Document Brain’s NER enrichment (extract_entities) through hosted GLiNER-large when the local GLiNER pack is missing or broken — same contract, better model"
          ],
          "privacy": [
            "Only operator arguments leave your database — Clover never receives table access or database credentials",
            "We never store your inputs or outputs — metering records counts, timings, and token totals only",
            "Never used for training — your traffic trains nothing",
            "Your database receipts retain the customer-side audit trail for every managed call"
          ]
        }
      }
    },
    {
      "id": "managed/hare-slots",
      "name": "hare-slots",
      "title": "Hare Slots",
      "description": "Serverless query offload: your database mints self-expiring capsules, our pool answers them with per-request isolation at any width. Buy concurrency for your local Postgres.",
      "tags": [
        "managed",
        "hare",
        "offload",
        "serverless"
      ],
      "kind": "managed",
      "catalog_visibility": "public",
      "device": "cloud",
      "operators": [],
      "backend_name": null,
      "capability_manifest": {
        "api_version": "v1",
        "kind": "managed",
        "name": "hare-slots",
        "title": "Hare Slots",
        "description": "Serverless query offload: your database mints self-expiring capsules, our pool answers them with per-request isolation at any width. Buy concurrency for your local Postgres.",
        "tags": [
          "managed",
          "hare",
          "offload",
          "serverless"
        ],
        "operators": [],
        "managed": {
          "vendor": "rvbbit.ai",
          "status": "coming_soon",
          "entitlement": "hare",
          "key_env": "RVBBIT_HARE_KEY",
          "pricing": {
            "note": "in private testing"
          },
          "tagline": "Serverless query offload — your database mints self-expiring capsules, our pool answers them. Buy concurrency for your local Postgres.",
          "value_props": [
            {
              "title": "Per-request isolation",
              "detail": "Every offloaded query gets its own worker; a dashboard refresh storm never touches your database."
            },
            {
              "title": "Zero standing creds",
              "detail": "Your brain presigns its own bucket URLs; the pool holds nothing and expires in minutes."
            },
            {
              "title": "Scale-to-zero",
              "detail": "Idle costs nothing; bursts spin up capacity on demand."
            }
          ],
          "highlights": [
            "A relief valve for Postgres under bursty analytical load",
            "Unusual for a mixed on-prem database — buy concurrency without moving your data"
          ],
          "privacy": [
            "We never store your inputs or outputs — metering records counts, timings, and token totals only",
            "Never used for training — your traffic trains nothing",
            "No standing credentials — your database presigns its own storage URLs; capsules expire in minutes"
          ]
        }
      }
    },
    {
      "acceptance": {
        "setup_sql": [],
        "target_selector": {
          "capability": true,
          "docker": true,
          "google_workspace": true,
          "gpu": false
        },
        "teardown_sql": [],
        "tests": [
          {
            "description": "Assert the connector backend and strict governed Brain source were registered.",
            "name": "google_meet_brain_connector_registered",
            "sql": "DO $$\nBEGIN\n    IF to_regprocedure('rvbbit.brain_configure_google_meet_source(text,boolean,jsonb)') IS NULL THEN\n        RAISE EXCEPTION 'Google Meet Brain connector requires pg_rvbbit migration 0250 or newer';\n    END IF;\n    IF NOT EXISTS (\n        SELECT 1 FROM rvbbit.backends\n         WHERE name='gmeet_connector' AND endpoint_url LIKE '%/sync'\n    ) THEN\n        RAISE EXCEPTION 'gmeet_connector backend is not registered';\n    END IF;\n    IF NOT EXISTS (\n        SELECT 1 FROM rvbbit.brain_sources\n         WHERE label='Google Meet' AND kind='google_meet' AND enabled\n           AND config->>'acl_mode'='calendar_invitees_strict'\n           AND coalesce((config->>'summarize_meetings')::boolean,false)\n    ) THEN\n        RAISE EXCEPTION 'Google Meet source is missing strict ACL or optional-summary policy';\n    END IF;\nEND\n$$;\n"
          }
        ]
      },
      "acceptance_tests": [
        "google_meet_brain_connector_registered"
      ],
      "backend_name": "gmeet_connector",
      "backend_transport": "rvbbit",
      "capability_role": "brain_connector",
      "catalog_visibility": "public",
      "description": "Generated Google Meet transcripts become searchable, invitee-governed Company Brain evidence, with optional derived briefs that inherit the transcript ACL.",
      "device": "cpu",
      "endpoint_path": "/sync",
      "gpu_placement": null,
      "gpu_required": false,
      "health_path": "/health",
      "id": "integrations/google-meet-brain",
      "install_docker": true,
      "install_mode": "image",
      "install_warren": true,
      "kind": "runtime_sidecar",
      "license": "apache-2.0",
      "manifest_path": "capabilities/packs/integrations/google-meet-brain/capability.yaml",
      "model_size_bytes": null,
      "name": "google_meet_brain_connector",
      "operators": [],
      "pack_api_version": "rvbbit.pack/v1",
      "pack_id": "integrations/google-meet-brain",
      "pack_manifest_path": "capabilities/packs/integrations/google-meet-brain/rvbbit-pack.yaml",
      "pack_path": "capabilities/packs/integrations/google-meet-brain",
      "provider_model": null,
      "provider_name": null,
      "provider_set_default": false,
      "repo_url": null,
      "resources": {},
      "runtime_handler": "google_meet",
      "runtime_image": "${RVBBIT_GMEET_CONNECTOR_IMAGE:-ghcr.io/ryrobes/rvbbit-gmeet-connector:latest}",
      "runtime_language": "brain_connector",
      "runtime_mode": "image",
      "runtime_name": "gmeet_connector",
      "runtime_port": 8080,
      "runtime_template": "runtime-sidecar",
      "source_model": "workspace/google-meet-transcripts",
      "source_provider": "google",
      "source_revision": null,
      "source_url": "https://developers.google.com/workspace/meet/api/guides/artifacts",
      "system_runtime": false,
      "tags": [
        "google",
        "workspace",
        "meet",
        "transcripts",
        "meetings",
        "documents",
        "brain",
        "knowledge",
        "calendar",
        "governed",
        "cpu"
      ],
      "title": "Google Meet Brain Connector",
      "vram_headroom_pct": null,
      "vram_required_bytes": null,
      "capability_manifest": {
        "api_version": "rvbbit.capability/v1",
        "backend": {
          "auth_env": "GMEET_CONNECTOR_TOKEN",
          "batch_size": 1,
          "description": "Google Meet transcript to governed Rvbbit Brain connector.",
          "max_concurrent": 1,
          "name": "gmeet_connector",
          "timeout_ms": 900000,
          "transport": "rvbbit"
        },
        "brain_source": {
          "config": {
            "acl_mode": "calendar_invitees_strict",
            "auto_transcribe": false,
            "auto_transcribe_days": 7,
            "calendar_lookup": true,
            "connector": "gmeet_connector",
            "doc_type": "meeting",
            "drive_acl": true,
            "lookback_days": 29,
            "provider": "google-meet",
            "source_kind": "google_meet",
            "summarize_meetings": true,
            "summary_max_docs": 12,
            "tombstone_missing": false
          },
          "creds_ref": "GMEET_CONNECTOR_TOKEN",
          "enabled": true,
          "folder_prefix": "/meetings",
          "kind": "google_meet",
          "label": "Google Meet"
        },
        "capability_role": "brain_connector",
        "description": "Ingest generated Google Meet transcripts as invitee-governed Brain documents, with optional same-ACL derived meeting briefs.",
        "kind": "runtime_sidecar",
        "license": "apache-2.0",
        "name": "google_meet_brain_connector",
        "runtime": {
          "device": "cpu",
          "env": {
            "CONNECTOR_TOKEN": "${GMEET_CONNECTOR_TOKEN:-}",
            "GMEET_ACL_MODE": "${GMEET_ACL_MODE:-calendar_invitees_strict}",
            "GMEET_ADMIN_SUBJECT": "${GMEET_ADMIN_SUBJECT:-}",
            "GMEET_AUTO_TRANSCRIBE": "${GMEET_AUTO_TRANSCRIBE:-false}",
            "GMEET_AUTO_TRANSCRIBE_DAYS": "${GMEET_AUTO_TRANSCRIBE_DAYS:-7}",
            "GMEET_CALENDAR_LOOKUP": "${GMEET_CALENDAR_LOOKUP:-true}",
            "GMEET_DISCOVER_USERS": "${GMEET_DISCOVER_USERS:-true}",
            "GMEET_DOMAIN": "${GMEET_DOMAIN:-}",
            "GMEET_DRIVE_ACL": "${GMEET_DRIVE_ACL:-true}",
            "GMEET_LOOKBACK_DAYS": "${GMEET_LOOKBACK_DAYS:-29}",
            "GMEET_MAX_SUBJECTS": "${GMEET_MAX_SUBJECTS:-500}",
            "GMEET_SA_KEY": "${GMEET_SA_KEY:-}",
            "GMEET_SUBJECTS": "${GMEET_SUBJECTS:-}"
          },
          "handler": "google_meet",
          "health_path": "/health",
          "image": "${RVBBIT_GMEET_CONNECTOR_IMAGE:-ghcr.io/ryrobes/rvbbit-gmeet-connector:latest}",
          "language": "brain_connector",
          "mode": "image",
          "port": 8080,
          "pull_policy": "always",
          "template": "runtime-sidecar",
          "volumes": [
            {
              "mount": "/root/.cache/google-api-python-client",
              "name": "gmeet_connector_cache"
            }
          ]
        },
        "runtime_registration": {
          "auth_env": "GMEET_CONNECTOR_TOKEN",
          "endpoint_path": "/sync",
          "labels": {
            "capability_kind": "runtime_sidecar",
            "capability_role": "brain_connector",
            "language": "brain_connector",
            "provider": "google_meet"
          },
          "language": "brain_connector",
          "name": "gmeet_connector",
          "set_default": false
        },
        "smoke": {
          "sql": [
            "DO $$\nBEGIN\n    IF to_regprocedure('rvbbit.brain_configure_google_meet_source(text,boolean,jsonb)') IS NULL THEN\n        RAISE EXCEPTION 'Google Meet Brain connector requires pg_rvbbit migration 0250 or newer';\n    END IF;\n    IF NOT EXISTS (\n        SELECT 1 FROM rvbbit.backends\n         WHERE name='gmeet_connector' AND endpoint_url LIKE '%/sync'\n    ) THEN\n        RAISE EXCEPTION 'gmeet_connector backend is not registered';\n    END IF;\n    IF NOT EXISTS (\n        SELECT 1 FROM rvbbit.brain_sources\n         WHERE label='Google Meet' AND kind='google_meet' AND enabled\n           AND config->>'acl_mode'='calendar_invitees_strict'\n    ) THEN\n        RAISE EXCEPTION 'Google Meet Brain source is not configured with strict invitee ACLs';\n    END IF;\nEND\n$$;\n"
          ]
        },
        "source": {
          "model": "workspace/google-meet-transcripts",
          "provider": "google",
          "url": "https://developers.google.com/workspace/meet/api/guides/artifacts"
        },
        "system_runtime": false,
        "tags": [
          "google",
          "workspace",
          "meet",
          "transcripts",
          "meetings",
          "documents",
          "brain",
          "knowledge",
          "calendar",
          "governed",
          "cpu"
        ],
        "title": "Google Meet Brain Connector",
        "warren": {
          "endpoint_path": "/sync",
          "health_path": "/health"
        }
      }
    }
  ]
}
