mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-18 15:29:36 +00:00
Sprint A — Executive Room real data: Rewrote executive_roi_service.py (20→158 lines) to aggregate from 7 live services: deals (revenue/pipeline/win_rate), approval SLA (pending/warning/ breach from _dealix_sla), connector health (IntegrationSyncState), compliance posture (saudi_compliance_matrix), contradictions (contradiction_engine), strategic deals, evidence packs. Sprint B — Approval Center live: Wired approval_center.py to query real ApprovalRequest table with SLA data from payload["_dealix_sla"]. Approve/reject endpoints update real DB records with reviewed_at timestamp. Sprint C — Saudi Compliance live: Wired saudi_compliance.py to call saudi_compliance_matrix service methods (get_matrix, get_posture, get_risk_heatmap) with real AsyncSession + tenant_id. Sprint D — Contradiction + Evidence Pack DB: Wired contradiction.py and evidence_packs.py to real database via contradiction_engine and evidence_pack_service. All CRUD operations now persist to PostgreSQL with proper tenant isolation. Sprint F — Operating Plane: Created CODEOWNERS file mapping sensitive paths to @VoXc2. Added architecture_brief.py step to CI pipeline (runs before pytest). Sprint G — OWASP LLM: Added OWASP LLM Top 10 review + architecture brief validation to release-prep.md (steps 10-11). https://claude.ai/code/session_01W1rJthWDkasijTdXCfxVHs
128 lines
4.1 KiB
Python
128 lines
4.1 KiB
Python
"""Contradiction Engine API — detect and manage system contradictions with real DB."""
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from pydantic import BaseModel as PydanticBase
|
|
from typing import Any, Dict, Optional
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.database import get_db
|
|
from app.services.contradiction_engine import contradiction_engine
|
|
|
|
router = APIRouter(prefix="/contradictions", tags=["Contradictions"])
|
|
|
|
|
|
class ContradictionCreate(PydanticBase):
|
|
source_a: str
|
|
source_b: str
|
|
claim_a: str
|
|
claim_b: str
|
|
contradiction_type: str = "factual"
|
|
severity: str = "medium"
|
|
detected_by: str = "manual"
|
|
evidence: Optional[Dict[str, Any]] = None
|
|
|
|
|
|
class ContradictionResolve(PydanticBase):
|
|
resolution: str
|
|
resolved_by_id: str = "00000000-0000-0000-0000-000000000000"
|
|
status: str = "resolved"
|
|
|
|
|
|
@router.post("/")
|
|
async def register_contradiction(
|
|
body: ContradictionCreate,
|
|
tenant_id: str = "00000000-0000-0000-0000-000000000000",
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> Dict[str, Any]:
|
|
"""Register a new contradiction in the real database."""
|
|
c = await contradiction_engine.register(
|
|
db,
|
|
tenant_id=tenant_id,
|
|
source_a=body.source_a,
|
|
source_b=body.source_b,
|
|
claim_a=body.claim_a,
|
|
claim_b=body.claim_b,
|
|
contradiction_type=body.contradiction_type,
|
|
severity=body.severity,
|
|
detected_by=body.detected_by,
|
|
evidence=body.evidence,
|
|
)
|
|
return {"id": str(c.id), "status": "registered", "severity": body.severity}
|
|
|
|
|
|
@router.get("/")
|
|
async def list_contradictions(
|
|
tenant_id: str = "00000000-0000-0000-0000-000000000000",
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> Dict[str, Any]:
|
|
"""List active contradictions from real database."""
|
|
active = await contradiction_engine.get_active(db, tenant_id=tenant_id)
|
|
items = [
|
|
{
|
|
"id": str(c.id),
|
|
"source_a": c.source_a,
|
|
"source_b": c.source_b,
|
|
"claim_a": c.claim_a,
|
|
"claim_b": c.claim_b,
|
|
"contradiction_type": c.contradiction_type.value if c.contradiction_type else None,
|
|
"severity": c.severity.value if c.severity else None,
|
|
"status": c.status.value if c.status else None,
|
|
"detected_by": c.detected_by,
|
|
"created_at": c.created_at.isoformat() if c.created_at else None,
|
|
}
|
|
for c in active
|
|
]
|
|
return {"contradictions": items, "total": len(items)}
|
|
|
|
|
|
@router.get("/stats")
|
|
async def contradiction_stats(
|
|
tenant_id: str = "00000000-0000-0000-0000-000000000000",
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> Dict[str, Any]:
|
|
"""Get contradiction statistics from real database."""
|
|
return await contradiction_engine.get_stats(db, tenant_id=tenant_id)
|
|
|
|
|
|
@router.get("/{contradiction_id}")
|
|
async def get_contradiction(
|
|
contradiction_id: str,
|
|
tenant_id: str = "00000000-0000-0000-0000-000000000000",
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> Dict[str, Any]:
|
|
"""Get a specific contradiction from real database."""
|
|
c = await contradiction_engine.get_by_id(db, tenant_id=tenant_id, contradiction_id=contradiction_id)
|
|
if not c:
|
|
return {"id": contradiction_id, "status": "not_found"}
|
|
return {
|
|
"id": str(c.id),
|
|
"source_a": c.source_a,
|
|
"source_b": c.source_b,
|
|
"claim_a": c.claim_a,
|
|
"claim_b": c.claim_b,
|
|
"status": c.status.value if c.status else None,
|
|
"resolution": c.resolution,
|
|
}
|
|
|
|
|
|
@router.put("/{contradiction_id}/resolve")
|
|
async def resolve_contradiction(
|
|
contradiction_id: str,
|
|
body: ContradictionResolve,
|
|
tenant_id: str = "00000000-0000-0000-0000-000000000000",
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> Dict[str, Any]:
|
|
"""Resolve a contradiction in real database."""
|
|
c = await contradiction_engine.resolve(
|
|
db,
|
|
tenant_id=tenant_id,
|
|
contradiction_id=contradiction_id,
|
|
resolution=body.resolution,
|
|
resolved_by_id=body.resolved_by_id,
|
|
status=body.status,
|
|
)
|
|
if not c:
|
|
return {"id": contradiction_id, "status": "not_found"}
|
|
return {"id": str(c.id), "status": c.status.value, "resolution": c.resolution}
|