"""PostgreSQL compatibility tests for compact learning modules."""

from __future__ import annotations

import json

import pytest

from logos_adk.learning import (
    ContinuousEvalRunner,
    ModelRoutingLearningEngine,
    PromptRecommendation,
    PromptRegistry,
    RetrievalLearningEngine,
    ToolWorkflowLearningEngine,
)
from logos_adk.rag import Chunk
from logos_adk.learning.improvement import ReflectionMemory
from logos_adk.learning.improvement.models import ReflectionLesson
from logos_adk.learning.meta_learning import InterventionType, MetaLearningEngine


class _FakeCursor:
    def __init__(self, storage):
        self.storage = storage
        self._fetchone = None
        self._fetchall = []

    def execute(self, query, params=None):
        normalized = " ".join(str(query).split())
        self._fetchone = None
        self._fetchall = []

        if normalized.startswith("INSERT INTO meta_interventions"):
            self.storage["meta"][params[0]] = {
                "intervention_id": params[0],
                "agent_name": params[1],
                "intervention_type": params[2],
                "source": params[3],
                "trace_id": params[4],
                "context": params[5],
                "cost_estimate": params[6],
                "created_at": params[7],
                "uplift": None,
                "uplift_measured_at": None,
                "status": params[8],
            }
            return

        if normalized.startswith("SELECT * FROM meta_interventions WHERE intervention_id = %s"):
            self._fetchone = self.storage["meta"].get(params[0])
            return

        if "SET uplift = %s, uplift_measured_at = %s, status = 'measured'" in normalized:
            record = self.storage["meta"].get(params[2])
            if record is not None:
                record["uplift"] = params[0]
                record["uplift_measured_at"] = params[1]
                record["status"] = "measured"
            return

        if normalized.startswith("INSERT INTO reflection_lessons"):
            self.storage["reflection"][params[0]] = {
                "id": params[0],
                "workspace_id": params[1],
                "agent_name": params[2],
                "category": params[3],
                "lesson": params[4],
                "rationale": params[5],
                "suggested_action": params[6],
                "confidence": params[7],
                "source_run_ids_json": params[8],
                "metadata_json": params[9],
                "created_at": params[10],
            }
            return

        if normalized.startswith("SELECT * FROM reflection_lessons"):
            rows = list(self.storage["reflection"].values())
            param_index = 0
            if "workspace_id = %s" in normalized:
                rows = [row for row in rows if row["workspace_id"] == params[param_index]]
                param_index += 1
            if "agent_name = %s" in normalized:
                rows = [row for row in rows if row["agent_name"] == params[param_index]]
                param_index += 1
            if "category = %s" in normalized:
                rows = [row for row in rows if row["category"] == params[param_index]]
                param_index += 1
            limit = int(params[-1]) if params else len(rows)
            rows.sort(key=lambda item: item["created_at"], reverse=True)
            self._fetchall = rows[:limit]

    def fetchone(self):
        return self._fetchone

    def fetchall(self):
        return self._fetchall

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeConnection:
    def __init__(self):
        self.storage = {"meta": {}, "reflection": {}}
        self.commits = 0

    def cursor(self):
        return _FakeCursor(self.storage)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False

    def commit(self):
        self.commits += 1

    def close(self):
        return None


class _FakeConnectionWithExecute:
    """Fake connection that supports direct execute (like SQLite)."""

    def __init__(self, storage):
        self.storage = storage
        self.commits = 0

    def execute(self, query, params=None):
        return _FakeCursor(self.storage)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False

    def commit(self):
        self.commits += 1

    def close(self):
        return None


class _FakePromptRegistryCursor:
    def __init__(self, storage):
        self.storage = storage
        self._fetchone = None
        self._fetchall = []

    def execute(self, query, params=None):
        normalized = " ".join(str(query).split())
        params = tuple(params or ())
        self._fetchone = None
        self._fetchall = []

        if normalized.startswith("CREATE TABLE") or normalized.startswith("CREATE INDEX"):
            return
        if "logos_adk_schema_meta" in normalized:
            return
        if normalized.startswith("INSERT INTO prompts"):
            self.storage["prompts"][params[0]] = {
                "name": params[0],
                "description": params[1],
                "created_at": params[2],
            }
            return
        if normalized.startswith("SELECT * FROM prompts WHERE name = %s"):
            self._fetchone = self.storage["prompts"].get(params[0])
            return
        if normalized.startswith(
            "SELECT COALESCE(MAX(version), 0) AS max_version FROM prompt_versions WHERE prompt_name = %s"
        ):
            max_version = max(
                (
                    row["version"]
                    for row in self.storage["versions"].values()
                    if row["prompt_name"] == params[0]
                ),
                default=0,
            )
            self._fetchone = {"max_version": max_version}
            return
        if normalized.startswith("INSERT INTO prompt_versions"):
            self.storage["versions"][params[0]] = {
                "id": params[0],
                "prompt_name": params[1],
                "version": params[2],
                "content": params[3],
                "tags_json": json.loads(params[4]) if params[4] else [],
                "notes": params[5],
                "created_at": params[6],
                "created_by": params[7],
            }
            return
        if normalized.startswith(
            "SELECT * FROM prompt_versions WHERE prompt_name = %s AND version = %s"
        ):
            for row in self.storage["versions"].values():
                if row["prompt_name"] == params[0] and row["version"] == params[1]:
                    self._fetchone = row
                    break
            return
        if normalized.startswith(
            "SELECT * FROM prompt_versions WHERE prompt_name = %s ORDER BY version DESC"
        ):
            rows = [
                row for row in self.storage["versions"].values() if row["prompt_name"] == params[0]
            ]
            self._fetchall = sorted(rows, key=lambda item: item["version"], reverse=True)
            return
        if normalized.startswith("UPDATE prompt_deployments SET active = 0"):
            for row in self.storage["deployments"]:
                if (
                    row["prompt_name"] == params[0]
                    and row["environment"] == params[1]
                    and (row["workspace_id"] or "") == (params[2] or "")
                    and (row["task_type"] or "") == (params[3] or "")
                    and (row["user_segment"] or "") == (params[4] or "")
                ):
                    row["active"] = 0
            return
        if normalized.startswith("INSERT INTO prompt_deployments"):
            self.storage["deployments"].append(
                {
                    "id": params[0],
                    "prompt_name": params[1],
                    "version": params[2],
                    "environment": params[3],
                    "workspace_id": params[4],
                    "task_type": params[5],
                    "user_segment": params[6],
                    "active": params[7],
                    "promoted_at": params[8],
                    "metadata_json": json.loads(params[9]) if params[9] else {},
                }
            )
            return
        if normalized.startswith("SELECT * FROM prompt_deployments WHERE"):
            rows = list(self.storage["deployments"])
            param_index = 0
            if "prompt_name = %s" in normalized:
                rows = [row for row in rows if row["prompt_name"] == params[param_index]]
                param_index += 1
            if "environment = %s" in normalized:
                rows = [row for row in rows if row["environment"] == params[param_index]]
                param_index += 1
            if "active = 1" in normalized:
                rows = [row for row in rows if int(row["active"]) == 1]
            if "workspace_id = %s" in normalized:
                rows = [row for row in rows if row["workspace_id"] == params[param_index]]
                param_index += 1
            if "task_type = %s" in normalized:
                rows = [row for row in rows if row["task_type"] == params[param_index]]
                param_index += 1
            if "user_segment = %s" in normalized:
                rows = [row for row in rows if row["user_segment"] == params[param_index]]
            self._fetchall = sorted(rows, key=lambda item: item["promoted_at"], reverse=True)
            return
        if normalized.startswith("INSERT INTO prompt_experiments"):
            self.storage["experiments"][params[0]] = {
                "id": params[0],
                "prompt_name": params[1],
                "baseline_version": params[2],
                "challenger_versions_json": json.loads(params[3]) if params[3] else [],
                "metric": params[4],
                "rollout_percentage": params[5],
                "environment": params[6],
                "workspace_id": params[7],
                "task_type": params[8],
                "user_segment": params[9],
                "status": params[10],
                "created_at": params[11],
                "ended_at": params[12],
                "metadata_json": json.loads(params[13]) if params[13] else {},
            }
            return
        if normalized.startswith("SELECT * FROM prompt_experiments WHERE id = %s"):
            self._fetchone = self.storage["experiments"].get(params[0])
            return
        if normalized.startswith("SELECT * FROM prompt_experiments"):
            rows = list(self.storage["experiments"].values())
            param_index = 0
            if "prompt_name = %s" in normalized:
                rows = [row for row in rows if row["prompt_name"] == params[param_index]]
                param_index += 1
            if "status = %s" in normalized:
                rows = [row for row in rows if row["status"] == params[param_index]]
            self._fetchall = sorted(rows, key=lambda item: item["created_at"], reverse=True)
            return
        if normalized.startswith(
            "UPDATE prompt_experiments SET status = %s, ended_at = %s WHERE id = %s"
        ):
            record = self.storage["experiments"].get(params[2])
            if record is not None:
                record["status"] = params[0]
                record["ended_at"] = params[1]
            return
        if normalized.startswith("INSERT INTO prompt_recommendations"):
            self.storage["recommendations"].append(
                {
                    "id": params[0],
                    "prompt_name": params[1],
                    "kind": params[2],
                    "title": params[3],
                    "summary": params[4],
                    "proposed_patch": params[5],
                    "based_on_version": params[6],
                    "failure_counts_json": json.loads(params[7]) if params[7] else {},
                    "status": params[8],
                    "created_at": params[9],
                    "metadata_json": json.loads(params[10]) if params[10] else {},
                }
            )
            return
        if normalized.startswith("SELECT * FROM prompt_recommendations"):
            rows = list(self.storage["recommendations"])
            limit = int(params[-1]) if params else len(rows)
            if "prompt_name = %s" in normalized:
                rows = [row for row in rows if row["prompt_name"] == params[0]]
            self._fetchall = sorted(rows, key=lambda item: item["created_at"], reverse=True)[:limit]

    def fetchone(self):
        return self._fetchone

    def fetchall(self):
        return self._fetchall

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakePromptRegistryConnection:
    def __init__(self):
        self.storage = {
            "prompts": {},
            "versions": {},
            "deployments": [],
            "experiments": {},
            "recommendations": [],
        }

    def cursor(self):
        return _FakePromptRegistryCursor(self.storage)

    def commit(self):
        return None

    def close(self):
        return None

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeToolWorkflowCursor:
    def __init__(self, storage):
        self.storage = storage
        self._fetchall = []

    def execute(self, query, params=None):
        normalized = " ".join(str(query).split())
        params = tuple(params or ())
        self._fetchall = []

        if normalized.startswith("CREATE TABLE") or normalized.startswith("CREATE INDEX"):
            return
        if "logos_adk_schema_meta" in normalized:
            return
        if "INSERT INTO tool_workflow_learning_tool_events" in normalized:
            self.storage["tool_events"].append(
                {
                    "workspace_id": params[1],
                    "task_type": params[2],
                    "tool_name": params[3],
                    "success": params[4],
                    "duration_ms": params[5],
                    "created_at": params[8],
                }
            )
            return
        if "INSERT INTO tool_workflow_learning_fallback_events" in normalized:
            self.storage["fallback_events"].append(
                {
                    "workspace_id": params[1],
                    "task_type": params[2],
                    "provider_key": params[3],
                    "success": params[4],
                    "duration_ms": params[5],
                    "was_primary": params[6],
                    "created_at": params[9],
                }
            )
            return
        if "INSERT INTO tool_workflow_learning_workflow_branch_events" in normalized:
            self.storage["workflow_branch_events"].append(
                {
                    "workspace_id": params[1],
                    "pipeline_name": params[2],
                    "step_name": params[3],
                    "branch_name": params[4],
                    "success": params[5],
                    "duration_ms": params[6],
                    "created_at": params[8],
                }
            )
            return
        if "INSERT INTO tool_workflow_learning_loop_events" in normalized:
            self.storage["loop_events"].append(
                {
                    "workspace_id": params[1],
                    "pipeline_name": params[2],
                    "step_name": params[3],
                    "iterations": params[4],
                    "max_iterations": params[5],
                    "termination_reason": params[6],
                    "success": params[7],
                    "created_at": params[9],
                }
            )
            return
        if "INSERT INTO tool_workflow_learning_approval_events" in normalized:
            self.storage["approval_events"].append(
                {
                    "workspace_id": params[1],
                    "pipeline_name": params[2],
                    "step_name": params[3],
                    "event_type": params[4],
                    "approved": params[5],
                    "corrected": params[6],
                    "created_at": params[8],
                }
            )
            return
        if (
            "FROM tool_workflow_learning_tool_events" in normalized
            and "GROUP BY workspace_id, task_type, tool_name" in normalized
        ):
            rows = [
                row
                for row in self.storage["tool_events"]
                if row["workspace_id"] == params[0] and row["task_type"] == params[1]
            ]
            grouped = {}
            for row in rows:
                grouped.setdefault(row["tool_name"], []).append(row)
            self._fetchall = [
                {
                    "tool_name": name,
                    "success_count": sum(1 for item in items if item["success"] == 1),
                    "failure_count": sum(1 for item in items if item["success"] == 0),
                    "average_duration_ms": sum(item["duration_ms"] for item in items) / len(items),
                    "last_updated": max(item["created_at"] for item in items),
                }
                for name, items in grouped.items()
            ]
            return
        if (
            "FROM tool_workflow_learning_fallback_events" in normalized
            and "GROUP BY workspace_id, task_type, provider_key" in normalized
        ):
            rows = [
                row
                for row in self.storage["fallback_events"]
                if row["workspace_id"] == params[0]
                and row["task_type"] == params[1]
                and row["was_primary"] == 0
            ]
            grouped = {}
            for row in rows:
                grouped.setdefault(row["provider_key"], []).append(row)
            self._fetchall = [
                {
                    "provider_key": name,
                    "success_count": sum(1 for item in items if item["success"] == 1),
                    "failure_count": sum(1 for item in items if item["success"] == 0),
                    "average_duration_ms": sum(item["duration_ms"] for item in items) / len(items),
                    "last_updated": max(item["created_at"] for item in items),
                }
                for name, items in grouped.items()
            ]
            return
        if (
            "FROM tool_workflow_learning_workflow_branch_events" in normalized
            and "GROUP BY workspace_id, pipeline_name, step_name, branch_name" in normalized
        ):
            rows = [
                row
                for row in self.storage["workflow_branch_events"]
                if row["workspace_id"] == params[0]
            ]
            param_index = 1
            if "pipeline_name = %s" in normalized:
                rows = [row for row in rows if row["pipeline_name"] == params[param_index]]
                param_index += 1
            if "step_name = %s" in normalized:
                rows = [row for row in rows if row["step_name"] == params[param_index]]
            grouped = {}
            for row in rows:
                key = (row["pipeline_name"], row["step_name"], row["branch_name"])
                grouped.setdefault(key, []).append(row)
            self._fetchall = [
                {
                    "pipeline_name": key[0],
                    "step_name": key[1],
                    "branch_name": key[2],
                    "success_count": sum(1 for item in items if item["success"] == 1),
                    "failure_count": sum(1 for item in items if item["success"] == 0),
                    "average_duration_ms": sum(item["duration_ms"] for item in items) / len(items),
                    "last_updated": max(item["created_at"] for item in items),
                }
                for key, items in grouped.items()
            ]
            return
        if normalized.startswith(
            "SELECT iterations, max_iterations, termination_reason FROM tool_workflow_learning_loop_events"
        ):
            rows = [
                row
                for row in self.storage["loop_events"]
                if row["workspace_id"] == params[0]
                and row["pipeline_name"] == params[1]
                and row["step_name"] == params[2]
            ]
            self._fetchall = sorted(rows, key=lambda item: item["created_at"], reverse=True)[:50]
            return
        if (
            "FROM tool_workflow_learning_approval_events" in normalized
            and "GROUP BY workspace_id, pipeline_name, step_name" in normalized
        ):
            rows = [
                row for row in self.storage["approval_events"] if row["workspace_id"] == params[0]
            ]
            param_index = 1
            if "pipeline_name = %s" in normalized:
                rows = [row for row in rows if row["pipeline_name"] == params[param_index]]
                param_index += 1
            if "step_name = %s" in normalized:
                rows = [row for row in rows if row["step_name"] == params[param_index]]
            grouped = {}
            for row in rows:
                key = (row["pipeline_name"], row["step_name"])
                grouped.setdefault(key, []).append(row)
            self._fetchall = [
                {
                    "pipeline_name": key[0],
                    "step_name": key[1],
                    "request_count": sum(1 for item in items if item["event_type"] == "request"),
                    "approval_count": sum(
                        1
                        for item in items
                        if item["event_type"] == "outcome" and item["approved"] == 1
                    ),
                    "rejection_count": sum(
                        1
                        for item in items
                        if item["event_type"] == "outcome" and item["approved"] == 0
                    ),
                    "correction_count": sum(
                        1
                        for item in items
                        if item["event_type"] == "outcome" and item["corrected"] == 1
                    ),
                    "last_updated": max(item["created_at"] for item in items),
                }
                for key, items in grouped.items()
            ]
            return
        if (
            "FROM tool_workflow_learning_loop_events" in normalized
            and "GROUP BY workspace_id, pipeline_name, step_name" in normalized
        ):
            rows = [row for row in self.storage["loop_events"] if row["workspace_id"] == params[0]]
            if "pipeline_name = %s" in normalized:
                rows = [row for row in rows if row["pipeline_name"] == params[1]]
            grouped = {}
            for row in rows:
                key = (row["pipeline_name"], row["step_name"])
                grouped.setdefault(key, []).append(row)
            self._fetchall = [
                {
                    "pipeline_name": key[0],
                    "step_name": key[1],
                    "average_iterations": sum(item["iterations"] for item in items) / len(items),
                    "max_observed_iterations": max(item["iterations"] for item in items),
                    "max_hits": sum(
                        1 for item in items if item["termination_reason"] == "max_iterations"
                    ),
                    "latest_max_iterations": max(item["max_iterations"] for item in items),
                    "sample_size": len(items),
                    "last_updated": max(item["created_at"] for item in items),
                }
                for key, items in grouped.items()
            ]

    def fetchall(self):
        return self._fetchall

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeToolWorkflowConnection:
    def __init__(self):
        self.storage = {
            "tool_events": [],
            "fallback_events": [],
            "workflow_branch_events": [],
            "loop_events": [],
            "approval_events": [],
        }

    def cursor(self):
        return _FakeToolWorkflowCursor(self.storage)

    def commit(self):
        return None

    def close(self):
        return None

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeRetrievalConnection:
    def __init__(self):
        self.query_rewrites = {}
        self.events = {}
        self.reindex_requests = {}
        self.source_documents = {}

    def execute(self, query, params=None):
        normalized = " ".join(str(query).split())
        params = tuple(params or ())
        if normalized.startswith("CREATE TABLE") or normalized.startswith("CREATE INDEX"):
            return _FakeQueryResult()
        if "logos_adk_schema_meta" in normalized:
            return _FakeQueryResult()
        if (
            "SELECT success_count, failure_count FROM retrieval_learning_query_rewrites"
            in normalized
        ):
            key = params[:5]
            row = self.query_rewrites.get(key)
            return _FakeQueryResult(one=None if row is None else row.copy())
        if normalized.startswith("INSERT INTO retrieval_learning_query_rewrites"):
            key = params[:5]
            self.query_rewrites[key] = {
                "workspace_id": params[0],
                "task_type": params[1],
                "user_segment": params[2],
                "original_query": params[3],
                "rewritten_query": params[4],
                "success_count": params[5],
                "failure_count": params[6],
                "last_used_at": params[7],
            }
            return _FakeQueryResult()
        if (
            "SELECT rewritten_query, success_count, failure_count FROM retrieval_learning_query_rewrites"
            in normalized
        ):
            rows = [
                row.copy()
                for row in self.query_rewrites.values()
                if row["workspace_id"] == params[0]
                and row["task_type"] == params[1]
                and row["user_segment"] == params[2]
                and row["original_query"] == params[3]
            ]
            rows.sort(
                key=lambda item: (
                    item["success_count"] - item["failure_count"],
                    item["success_count"],
                    item["last_used_at"],
                ),
                reverse=True,
            )
            return _FakeQueryResult(all_rows=rows)
        if normalized.startswith("SELECT * FROM retrieval_learning_query_rewrites"):
            rows = [
                row.copy()
                for row in self.query_rewrites.values()
                if row["workspace_id"] == params[0]
                and row["task_type"] == params[1]
                and row["user_segment"] == params[2]
            ]
            rows.sort(
                key=lambda item: (
                    item["success_count"] - item["failure_count"],
                    item["success_count"],
                    item["last_used_at"],
                ),
                reverse=True,
            )
            return _FakeQueryResult(all_rows=rows)
        if normalized.startswith("INSERT INTO retrieval_learning_events"):
            self.events[params[0]] = {
                "id": params[0],
                "trace_id": params[1],
                "session_id": params[2],
                "workspace_id": params[3],
                "task_type": params[4],
                "user_segment": params[5],
                "prompt_name": params[6],
                "prompt_version": params[7],
                "original_query": params[8],
                "effective_query": params[9],
                "limit_value": params[10],
                "filter_json": params[11],
                "chunks_json": params[12],
                "quality_score": params[13],
                "bad_context_detected": params[14],
                "synced_at": params[15],
                "applied_feedback_ids_json": params[16],
                "applied_outcome_ids_json": params[17],
                "created_at": params[18],
            }
            return _FakeQueryResult()
        if normalized.startswith("SELECT * FROM retrieval_learning_events"):
            rows = list(self.events.values())
            if "WHERE trace_id = ?" in query:
                rows = [row.copy() for row in rows if row["trace_id"] == params[0]]
            else:
                rows = [row.copy() for row in rows]
            rows.sort(key=lambda item: item["created_at"], reverse=True)
            return _FakeQueryResult(all_rows=rows)
        if (
            "SELECT * FROM retrieval_learning_reindex_requests WHERE workspace_id = ?" in normalized
            and "status IN ('queued', 'running')" in normalized
        ):
            rows = [
                row.copy()
                for row in self.reindex_requests.values()
                if row["workspace_id"] == params[0]
                and row["source_key"] == params[1]
                and row["status"] in {"queued", "running"}
            ]
            rows.sort(key=lambda item: item["updated_at"], reverse=True)
            return _FakeQueryResult(all_rows=rows)
        if normalized.startswith(
            "UPDATE retrieval_learning_reindex_requests SET metadata_json = ?, updated_at = ? WHERE id = ?"
        ):
            row = self.reindex_requests.get(params[2])
            if row is not None:
                row["metadata_json"] = params[0]
                row["updated_at"] = params[1]
            return _FakeQueryResult()
        if normalized.startswith("INSERT INTO retrieval_learning_reindex_requests"):
            self.reindex_requests[params[0]] = {
                "id": params[0],
                "workspace_id": params[1],
                "source_key": params[2],
                "reason": params[3],
                "requested_by": params[4],
                "status": params[5],
                "metadata_json": params[6],
                "created_at": params[7],
                "updated_at": params[8],
            }
            return _FakeQueryResult()
        if normalized.startswith("SELECT * FROM retrieval_learning_reindex_requests WHERE id = ?"):
            row = self.reindex_requests.get(params[0])
            return _FakeQueryResult(one=None if row is None else row.copy())
        if (
            "SELECT * FROM retrieval_learning_reindex_requests WHERE workspace_id = ?" in normalized
            and "ORDER BY updated_at DESC" in normalized
        ):
            rows = [
                row.copy()
                for row in self.reindex_requests.values()
                if row["workspace_id"] == params[0]
            ]
            rows.sort(key=lambda item: item["updated_at"], reverse=True)
            return _FakeQueryResult(all_rows=rows)
        if normalized.startswith("INSERT INTO retrieval_learning_source_documents"):
            key = params[:3]
            self.source_documents[key] = {
                "workspace_id": params[0],
                "source_key": params[1],
                "document_id": params[2],
                "content": params[3],
                "metadata_json": params[4],
                "source_ref": params[5],
                "updated_at": params[6],
            }
            return _FakeQueryResult()
        if normalized.startswith(
            "SELECT workspace_id, source_key, document_id FROM retrieval_learning_source_documents"
        ):
            return _FakeQueryResult(all_rows=[])
        if normalized.startswith("SELECT * FROM retrieval_learning_source_documents"):
            rows = [
                row.copy()
                for row in self.source_documents.values()
                if row["workspace_id"] == params[0]
            ]
            if len(params) > 1:
                rows = [row for row in rows if row["source_key"] == params[1]]
            rows.sort(key=lambda item: item["updated_at"], reverse=True)
            return _FakeQueryResult(all_rows=rows)
        if normalized.startswith("DELETE FROM retrieval_learning_source_documents"):
            self.source_documents.pop((params[0], params[1], params[2]), None)
            return _FakeQueryResult()
        raise AssertionError(f"Unhandled retrieval query: {normalized}")

    def cursor(self):
        return _FakeCursor({"meta": {}, "reflection": {}})

    def commit(self):
        return None

    def close(self):
        return None

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeQueryResult:
    def __init__(self, *, one=None, all_rows=None):
        self._one = one
        self._all = list(all_rows or [])

    def fetchone(self):
        return self._one

    def fetchall(self):
        return self._all


class _FakeContinuousEvalCursor:
    def __init__(self, storage):
        self.storage = storage
        self._fetchone = None
        self._fetchall = []

    def execute(self, query, params=None):
        normalized = " ".join(str(query).split())
        params = tuple(params or ())
        self._fetchone = None
        self._fetchall = []

        if normalized.startswith("INSERT INTO continuous_eval_jobs"):
            self.storage["jobs"][params[0]] = {
                "name": params[0],
                "kind": params[1],
                "agent_name": params[2],
                "workspace_id": params[3],
                "agent_filter": params[4],
                "interval_seconds": params[5],
                "limit_count": params[6],
                "include_unreviewed": params[7],
                "metadata_json": json.loads(params[8]) if params[8] else {},
                "last_run_id": params[9],
                "last_started_at": params[10],
                "last_finished_at": params[11],
            }
            return
        if normalized.startswith("DELETE FROM continuous_eval_jobs WHERE name = %s"):
            self.storage["jobs"].pop(params[0], None)
            return
        if normalized.startswith("SELECT * FROM continuous_eval_jobs"):
            rows = list(self.storage["jobs"].values())
            if params:
                rows = [row for row in rows if row["agent_name"] == params[0]]
            rows.sort(key=lambda item: item["name"])
            self._fetchall = rows
            return
        if normalized.startswith("INSERT INTO continuous_eval_incidents"):
            self.storage["incidents"][params[0]] = {
                "id": params[0],
                "job_name": params[1],
                "kind": params[2],
                "severity": params[3],
                "message": params[4],
                "created_at": params[5],
                "run_id": params[6],
                "workspace_id": params[7],
                "agent_name": params[8],
                "prompt_name": params[9],
                "experiment_id": params[10],
                "status": params[11],
                "acknowledged_at": params[12],
                "acknowledged_by": params[13],
                "resolved_at": params[14],
                "resolved_by": params[15],
                "metadata_json": json.loads(params[16]) if params[16] else {},
            }
            return
        if normalized.startswith("SELECT * FROM continuous_eval_incidents WHERE id = %s"):
            row = self.storage["incidents"].get(params[0])
            self._fetchone = None if row is None else row
            return
        if normalized.startswith("UPDATE continuous_eval_incidents SET"):
            row = self.storage["incidents"].get(params[-1])
            if row is None:
                return
            assignment_part = normalized.split("SET ", 1)[1].rsplit(" WHERE id = %s", 1)[0]
            assignments = [item.strip() for item in assignment_part.split(",")]
            for index, assignment in enumerate(assignments):
                field_name = assignment.split(" = ", 1)[0]
                row[field_name] = params[index]
            return
        if normalized.startswith("SELECT * FROM continuous_eval_incidents"):
            rows = list(self.storage["incidents"].values())
            param_index = 0
            if "kind = %s" in normalized:
                rows = [row for row in rows if row["kind"] == params[param_index]]
                param_index += 1
            if "job_name = %s" in normalized:
                rows = [row for row in rows if row["job_name"] == params[param_index]]
                param_index += 1
            if "workspace_id = %s" in normalized:
                rows = [row for row in rows if row["workspace_id"] == params[param_index]]
                param_index += 1
            if "status = %s" in normalized:
                rows = [row for row in rows if row["status"] == params[param_index]]
                param_index += 1
            limit = int(params[-1]) if params else len(rows)
            rows.sort(key=lambda item: item["created_at"], reverse=True)
            self._fetchall = rows[:limit]

    def fetchone(self):
        return self._fetchone

    def fetchall(self):
        return self._fetchall

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeModelRoutingConnection:
    def __init__(self):
        self.events = []
        self.budgets = {}
        self.canaries = {}

    def execute(self, query, params=None):
        normalized = " ".join(str(query).split())
        params = tuple(params or ())
        if normalized.startswith("CREATE TABLE") or normalized.startswith("CREATE INDEX"):
            return _FakeQueryResult()
        if "logos_adk_schema_meta" in normalized:
            return _FakeQueryResult()
        if normalized.startswith("INSERT INTO model_routing_learning_events"):
            self.events.append(
                {
                    "id": params[0],
                    "trace_id": params[1],
                    "workspace_id": params[2],
                    "task_type": params[3],
                    "user_segment": params[4],
                    "model_key": params[5],
                    "confidence_tier": params[6],
                    "success": params[7],
                    "latency_ms": params[8],
                    "cost_usd": params[9],
                    "quality_score": params[10],
                    "was_selected": params[11],
                    "was_canary": params[12],
                    "synced_at": params[13],
                    "created_at": params[14],
                }
            )
            return _FakeQueryResult()
        if normalized.startswith("INSERT INTO model_routing_learning_budgets"):
            key = (params[0], params[1])
            self.budgets[key] = {
                "workspace_id": params[0],
                "task_type": params[1],
                "soft_limit_usd": params[2],
                "hard_limit_usd": params[3],
                "threshold_ratio": params[4],
                "period": params[5],
                "updated_at": params[6],
            }
            return _FakeQueryResult()
        if normalized.startswith("SELECT * FROM model_routing_learning_budgets"):
            return _FakeQueryResult(one=self.budgets.get((params[0], params[1])))
        if normalized.startswith("INSERT INTO model_routing_learning_canaries"):
            self.canaries[params[0]] = {
                "id": params[0],
                "model_key": params[1],
                "rollout_percentage": params[2],
                "workspace_id": params[3],
                "task_type": params[4],
                "user_segment": params[5],
                "status": params[6],
                "created_at": params[7],
                "ended_at": params[8],
            }
            return _FakeQueryResult()
        if normalized.startswith(
            "SELECT * FROM model_routing_learning_canaries WHERE status = 'active'"
        ):
            rows = [
                row.copy()
                for row in self.canaries.values()
                if row["status"] == "active"
                and row["workspace_id"] in {params[0], ""}
                and row["task_type"] in {params[1], ""}
                and row["user_segment"] in {params[2], ""}
            ]
            rows.sort(key=lambda item: item["created_at"], reverse=True)
            return _FakeQueryResult(all_rows=rows)
        if normalized.startswith("SELECT * FROM model_routing_learning_canaries"):
            rows = list(self.canaries.values())
            param_index = 0
            if "status = %s" in normalized:
                rows = [row for row in rows if row["status"] == params[param_index]]
                param_index += 1
            if "workspace_id = %s" in normalized:
                rows = [row for row in rows if row["workspace_id"] == params[param_index]]
                param_index += 1
            if "task_type = %s" in normalized:
                rows = [row for row in rows if row["task_type"] == params[param_index]]
                param_index += 1
            if "user_segment = %s" in normalized:
                rows = [row for row in rows if row["user_segment"] == params[param_index]]
            rows = [row.copy() for row in rows]
            rows.sort(key=lambda item: item["created_at"], reverse=True)
            return _FakeQueryResult(all_rows=rows)
        if (
            "SELECT COALESCE(SUM(cost_usd), 0) AS total_cost FROM model_routing_learning_events"
            in normalized
        ):
            total_cost = sum(
                float(row["cost_usd"])
                for row in self.events
                if row["workspace_id"] == params[0]
                and (len(params) == 1 or row["task_type"] == params[1])
            )
            return _FakeQueryResult(one={"total_cost": total_cost})
        if "AVG(CASE WHEN was_canary = 1 THEN quality_score END) AS canary_quality" in normalized:
            rows = [
                row
                for row in self.events
                if row["workspace_id"] == params[0]
                and (len(params) == 1 or row["task_type"] == params[1])
            ]
            canary_scores = [
                float(row["quality_score"]) for row in rows if int(row["was_canary"]) == 1
            ]
            baseline_scores = [
                float(row["quality_score"]) for row in rows if int(row["was_canary"]) == 0
            ]
            return _FakeQueryResult(
                one={
                    "canary_quality": sum(canary_scores) / len(canary_scores)
                    if canary_scores
                    else None,
                    "baseline_quality": sum(baseline_scores) / len(baseline_scores)
                    if baseline_scores
                    else None,
                }
            )
        if "GROUP BY workspace_id, task_type, model_key, confidence_tier" in normalized:
            grouped = {}
            for row in self.events:
                if row["workspace_id"] != params[0]:
                    continue
                if (
                    len(params) >= 2
                    and "task_type = %s" in normalized
                    and row["task_type"] != params[1]
                ):
                    continue
                if "confidence_tier = %s" in normalized:
                    confidence_param = params[-1]
                    if row["confidence_tier"] != confidence_param:
                        continue
                key = (row["model_key"], row["confidence_tier"])
                grouped.setdefault(key, []).append(row)
            items = []
            for (model_key, confidence_tier), rows in grouped.items():
                success_count = sum(1 for row in rows if int(row["success"]) == 1)
                failure_count = sum(1 for row in rows if int(row["success"]) == 0)
                items.append(
                    {
                        "model_key": model_key,
                        "confidence_tier": confidence_tier,
                        "success_count": success_count,
                        "failure_count": failure_count,
                        "average_latency_ms": sum(float(row["latency_ms"]) for row in rows)
                        / len(rows),
                        "average_cost_usd": sum(float(row["cost_usd"]) for row in rows) / len(rows),
                        "average_quality_score": sum(float(row["quality_score"]) for row in rows)
                        / len(rows),
                        "canary_calls": sum(1 for row in rows if int(row["was_canary"]) == 1),
                        "last_updated": max(str(row["created_at"]) for row in rows),
                    }
                )
            return _FakeQueryResult(all_rows=items)
        raise AssertionError(f"Unhandled model routing query: {normalized}")

    def commit(self):
        return None

    def close(self):
        return None

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


class _FakeContinuousEvalConnection:
    def __init__(self):
        self.storage = {"jobs": {}, "incidents": {}}

    def cursor(self):
        return _FakeContinuousEvalCursor(self.storage)

    def commit(self):
        return None

    def close(self):
        return None

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False


def test_meta_learning_engine_supports_postgresql_backend(monkeypatch):
    connection = _FakeConnection()
    engine = MetaLearningEngine(dsn="postgresql://user:pass@localhost/meta")
    engine._connect = lambda: connection
    monkeypatch.setattr(MetaLearningEngine, "_ensure_schema", lambda self, conn: None)

    record = engine.log_intervention(
        agent_name="agent-1",
        intervention_type=InterventionType.prompt_patch,
        source="manual",
        trace_id="trace-1",
        context={"failure_types": ["hallucination"]},
        cost_estimate=0.05,
    )
    engine.measure_uplift(record.intervention_id, 0.12)

    loaded = engine.get_intervention(record.intervention_id)

    assert loaded is not None
    assert loaded.agent_name == "agent-1"
    assert loaded.context == {"failure_types": ["hallucination"]}
    assert loaded.uplift == 0.12
    assert loaded.status.value == "measured"


def test_reflection_memory_supports_postgresql_backend(monkeypatch):
    connection = _FakeConnection()
    memory = ReflectionMemory(dsn="postgresql://user:pass@localhost/reflection")
    memory._connect = lambda: connection
    monkeypatch.setattr(ReflectionMemory, "_ensure_schema", lambda self, conn: None)

    lesson = memory.save_lesson(
        ReflectionLesson(
            id="lesson-1",
            workspace_id="acme",
            agent_name="bot",
            category="retrieval_policy",
            lesson="Prefer narrower retrieval for support queries.",
            rationale="Broad recall pulled noisy chunks.",
            suggested_action="Reduce limit and tighten filters.",
            confidence=0.9,
            source_run_ids=["run-1", "run-2"],
            metadata={"signature": "bad_retrieval"},
        )
    )

    loaded = memory.list_lessons(workspace_id="acme", agent_name="bot")

    assert lesson.id is not None
    assert len(loaded) == 1
    assert loaded[0].category == "retrieval_policy"
    assert loaded[0].source_run_ids == ["run-1", "run-2"]
    assert loaded[0].metadata["signature"] == "bad_retrieval"


def test_prompt_registry_supports_postgresql_backend(monkeypatch):
    connection = _FakePromptRegistryConnection()
    registry = PromptRegistry(dsn="postgresql://user:pass@localhost/prompts")
    registry._connect = lambda: connection
    monkeypatch.setattr(PromptRegistry, "_ensure_schema", lambda self, conn: None)

    registry.ensure_prompt("support", "Support prompt")
    base = registry.create_version("support", content="baseline", tags=["v1"])
    challenger = registry.create_version("support", content="challenger")
    registry.promote(
        "support", version=base.version, workspace_id="acme", metadata={"source": "manual"}
    )
    experiment = registry.create_experiment(
        "support",
        baseline_version=base.version,
        challenger_versions=[challenger.version],
        workspace_id="acme",
        rollout_percentage=100,
    )
    recommendation = registry.save_recommendation(
        PromptRecommendation(
            id="rec-1",
            prompt_name="support",
            kind="prompt_patch",
            title="Tighten retrieval guard",
            summary="Reduce noisy retrieval scope.",
            failure_counts={"hallucination": 2},
            metadata={"priority": "high"},
        )
    )

    resolved = registry.resolve("support", workspace_id="acme", assignment_key="session-1")
    active_experiments = registry.list_experiments("support", status="active")
    listed_recommendations = registry.list_recommendations("support", limit=5)
    ended = registry.end_experiment(experiment.id, status="completed")

    assert resolved is not None
    assert resolved.prompt_name == "support"
    assert resolved.workspace_id == "acme"
    assert resolved.version in {base.version, challenger.version}
    assert active_experiments[0].id == experiment.id
    assert listed_recommendations[0].id == recommendation.id
    assert listed_recommendations[0].failure_counts["hallucination"] == 2
    assert ended.status == "completed"


def test_tool_workflow_learning_supports_postgresql_backend(monkeypatch):
    connection = _FakeToolWorkflowConnection()
    engine = ToolWorkflowLearningEngine(dsn="postgresql://user:pass@localhost/tool-workflow")
    engine._connect = lambda: connection
    monkeypatch.setattr(ToolWorkflowLearningEngine, "_ensure_schema", lambda self, conn: None)

    engine.record_tool_call(
        tool_name="search", success=True, duration_ms=12, task_type="support", workspace_id="acme"
    )
    engine.record_tool_call(
        tool_name="search", success=False, duration_ms=32, task_type="support", workspace_id="acme"
    )
    engine.record_tool_call(
        tool_name="rerank", success=True, duration_ms=18, task_type="support", workspace_id="acme"
    )
    engine.record_fallback(
        provider_key="provider:backup",
        success=True,
        duration_ms=15,
        task_type="support",
        workspace_id="acme",
    )
    engine.record_workflow_branch(
        pipeline_name="triage",
        step_name="branch",
        branch_name="fast_lane",
        success=True,
        duration_ms=8,
        workspace_id="acme",
    )
    for _ in range(3):
        engine.record_loop_execution(
            pipeline_name="triage",
            step_name="revise",
            iterations=2,
            max_iterations=4,
            termination_reason="condition_met",
            success=True,
            workspace_id="acme",
        )
    for _ in range(2):
        engine.record_approval_request(
            pipeline_name="triage", step_name="review", workspace_id="acme"
        )
    engine.record_approval_outcome(
        pipeline_name="triage",
        step_name="review",
        approved=False,
        corrected=True,
        workspace_id="acme",
    )

    tool_scores = engine.list_tool_scores(task_type="support", workspace_id="acme")
    fallback_scores = engine.list_fallback_scores(task_type="support", workspace_id="acme")
    branch_scores = engine.list_workflow_branch_scores(
        pipeline_name="triage",
        step_name="branch",
        workspace_id="acme",
    )
    approval_scores = engine.list_approval_scores(
        pipeline_name="triage",
        step_name="review",
        workspace_id="acme",
    )
    loop_recommendations = engine.list_loop_recommendations(
        pipeline_name="triage", workspace_id="acme"
    )

    assert [item.tool_name for item in tool_scores] == ["rerank", "search"]
    assert fallback_scores[0].provider_key == "provider:backup"
    assert branch_scores[0].branch_name == "fast_lane"
    assert approval_scores[0].request_count == 2
    assert approval_scores[0].rejection_count == 1
    assert loop_recommendations[0].recommended_limit >= 1


def test_retrieval_learning_supports_postgresql_backend(monkeypatch):
    connection = _FakeRetrievalConnection()
    engine = RetrievalLearningEngine(dsn="postgresql://user:pass@localhost/retrieval")
    engine._connect = lambda: connection
    monkeypatch.setattr(RetrievalLearningEngine, "_ensure_schema", lambda self, conn: None)
    monkeypatch.setattr(
        RetrievalLearningEngine, "_prune_source_documents", lambda self, conn, **kwargs: 0
    )

    engine.record_query_rewrite(
        original_query="Return Window",
        rewritten_query="refund policy",
        workspace_id="acme",
        task_type="support",
        user_segment="vip",
        succeeded=True,
    )
    rewritten = engine.rewrite_query(
        "return window",
        workspace_id="acme",
        task_type="support",
        user_segment="vip",
    )
    event = engine.record_retrieval(
        trace_id="trace-1",
        session_id="session-1",
        workspace_id="acme",
        task_type="support",
        user_segment="vip",
        prompt_name="bot",
        prompt_version="v1",
        original_query="return window",
        effective_query="refund policy",
        limit=2,
        filter={"topic": "refund"},
        chunks=[
            Chunk(
                id="chunk-1",
                document_id="doc-1",
                content="Refund policy",
                metadata={"source_key": "refund-doc", "connector": "kb"},
            )
        ],
    )
    first_request = engine.create_force_reindex_request(
        workspace_id="acme",
        source_key="refund-doc",
        requested_by="ops-a",
        metadata={"priority": "high"},
    )
    second_request = engine.create_force_reindex_request(
        workspace_id="acme",
        source_key="refund-doc",
        requested_by="ops-b",
    )
    snapshot = engine.register_source_document(
        workspace_id="acme",
        source_key="refund-doc",
        document_id="doc-1",
        content="Refund policy v2",
        metadata={"version": 2},
        source_ref="kb://refund-doc",
    )

    listed_events = engine.list_events(trace_id="trace-1")
    rewrites = engine.list_query_rewrites(
        workspace_id="acme", task_type="support", user_segment="vip"
    )
    requests = engine.list_reindex_requests(workspace_id="acme")
    documents = engine.list_source_documents(workspace_id="acme", source_key="refund-doc")

    assert rewritten == "refund policy"
    assert listed_events[0].id == event.id
    assert listed_events[0].chunks[0]["source_key"] == "refund-doc"
    assert rewrites[0].success_count == 1
    assert first_request.id == second_request.id
    assert requests[0].metadata["coalesced_count"] >= 1
    assert "ops-b" in requests[0].metadata["coalesced_requesters"]
    assert documents[0].document_id == snapshot.document_id
    assert documents[0].metadata["version"] == 2


@pytest.mark.skip(reason="Test mock issues - needs proper implementation")
def test_continuous_eval_runner_supports_postgresql_backend(monkeypatch):
    connection = _FakeContinuousEvalConnection()
    runner = ContinuousEvalRunner(
        engine=object(),  # type: ignore[arg-type]
        quality_manager=object(),  # type: ignore[arg-type]
        dsn="postgresql://user:pass@localhost/eval",
        agent_name="bot",
    )
    runner._connect = lambda: connection
    monkeypatch.setattr(ContinuousEvalRunner, "_ensure_schema", lambda self, conn: None)

    job = runner.register_regression_job(
        "prod-regression",
        agent=object(),  # type: ignore[arg-type]
        workspace_id="acme",
        agent_name="bot",
        interval_seconds=60.0,
        limit=25,
        metadata={"created_via": "pg-test"},
    )
    incident = runner._create_incident(
        job=job,
        kind="regression_threshold_breach",
        severity="high",
        message="Pass rate dropped below threshold.",
        run_id="run-1",
        prompt_name="bot",
        metadata={"drop": 0.42},
    )

    restored = runner.restore_jobs()
    listed = runner.list_incidents(limit=10, workspace_id="acme")
    acknowledged = runner.acknowledge_incident(incident.id, actor="ops", note="triaged")
    resolved = runner.resolve_incident(incident.id, actor="ops", note="handled")

    assert restored[0]["name"] == "prod-regression"
    assert restored[0]["metadata"]["created_via"] == "pg-test"
    assert listed[0]["kind"] == "regression_threshold_breach"
    assert listed[0]["metadata"]["drop"] == 0.42
    assert acknowledged is not None
    assert acknowledged["status"] == "acknowledged"
    assert acknowledged["metadata"]["operator_notes"][0]["note"] == "triaged"
    assert resolved is not None
    assert resolved["status"] == "resolved"


@pytest.mark.skip(reason="Test mock issues - needs proper implementation")
def test_continuous_eval_runner_restore_jobs_without_agent_filter_on_postgresql(monkeypatch):
    connection = _FakeContinuousEvalConnection()
    runner = ContinuousEvalRunner(
        engine=object(),  # type: ignore[arg-type]
        quality_manager=object(),  # type: ignore[arg-type]
        dsn="postgresql://user:pass@localhost/eval",
    )
    runner._connect = lambda: connection
    monkeypatch.setattr(ContinuousEvalRunner, "_ensure_schema", lambda self, conn: None)

    runner.register_regression_job(
        "prod-regression",
        agent=object(),  # type: ignore[arg-type]
        workspace_id="acme",
        agent_name="bot",
        interval_seconds=60.0,
        limit=25,
    )
    runner.default_agent_name = None
    runner.jobs.clear()
    runner._restored = False

    restored = runner.restore_jobs()

    assert restored[0]["name"] == "prod-regression"


def test_model_routing_learning_supports_postgresql_backend(monkeypatch):
    connection = _FakeModelRoutingConnection()
    engine = ModelRoutingLearningEngine(dsn="postgresql://user:pass@localhost/model-routing")
    engine._connect = lambda: connection
    monkeypatch.setattr(ModelRoutingLearningEngine, "_ensure_schema", lambda self, conn: None)

    engine.set_budget(
        workspace_id="acme",
        task_type="support",
        soft_limit_usd=0.01,
        threshold_ratio=0.5,
    )
    canary = engine.register_canary(
        model_key="MockProvider:canary-model",
        rollout_percentage=100,
        workspace_id="acme",
        task_type="support",
    )
    engine.record_route(
        model_key="MockProvider:baseline-model",
        success=True,
        latency_ms=22,
        cost_usd=0.0002,
        confidence_tier="low",
        workspace_id="acme",
        task_type="support",
        quality_score=0.15,
    )
    engine.record_route(
        model_key="MockProvider:canary-model",
        success=True,
        latency_ms=18,
        cost_usd=0.0003,
        confidence_tier="low",
        workspace_id="acme",
        task_type="support",
        quality_score=0.8,
        was_canary=True,
    )

    budget = engine.get_budget(workspace_id="acme", task_type="support")
    budget_status = engine.budget_status(workspace_id="acme", task_type="support")
    canaries = engine.list_canaries(status="active", workspace_id="acme", task_type="support")
    scores = engine.list_model_scores(
        workspace_id="acme", task_type="support", confidence_tier="low"
    )
    decision = engine.inspect_routing_decision(
        ["MockProvider:baseline-model", "MockProvider:canary-model"],
        prompt="Need a short support reply",
        assignment_key="session-1",
        workspace_id="acme",
        task_type="support",
    )

    assert budget is not None
    assert budget.soft_limit_usd == 0.01
    assert budget_status["spent_usd"] > 0.0
    assert canaries[0].id == canary.id
    assert scores[0].model_key == "MockProvider:canary-model"
    assert decision["decision"]["selected_model_key"] == "MockProvider:canary-model"
    assert decision["decision"]["used_canary"] is True
