"""Authorized persistence port for signal intelligence cluster metadata."""
from __future__ import annotations
import sqlite3
from pathlib import Path
from .writer_policy import WriterPolicy, load_writer_policy
class SignalIntelligenceRepository:
"""Own cluster/score enrichment without changing the scoring policy."""
_FIELDS = ("cluster_id", "radar_score", "score_breakdown")
def __init__(self, connection: sqlite3.Connection, *, policy: WriterPolicy | None = None) -> None:
self.connection = connection
policy_path = Path(__file__).resolve().parents[1] / "architecture" / "data-ownership.yaml"
self.policy = policy or load_writer_policy(policy_path)
self.policy.require("signal_intelligence", "signals", list(self._FIELDS))
def apply_cluster(self, cluster_id: str, signal_ids: list[str], bonus: float) -> None:
"""Apply the existing cluster metadata update to known signals only."""
for signal_id in signal_ids:
row = self.connection.execute(
"SELECT 1 FROM signals WHERE signal_id = ?", (signal_id,)
).fetchone()
if row is None:
raise ValueError(f"cannot update missing signal_id: {signal_id}")
# Keep legacy NULL propagation; this is a structural, not behavioral, slice.
self.connection.execute(
"UPDATE signals SET cluster_id=?, "
"radar_score=MIN(radar_score+?,100.0), "
"score_breakdown=COALESCE(score_breakdown,'{}') "
"WHERE signal_id=?",
(cluster_id, bonus, signal_id),
)