Evidence with supportive metadata

This commit is contained in:
2026-04-29 15:52:37 +02:00
parent 6c0a7db5e4
commit eb1513e463
10 changed files with 194 additions and 9 deletions

View File

@@ -48,6 +48,7 @@ class RegistryStore:
connection.executescript(migration_path.read_text(encoding="utf-8"))
self._ensure_content_chunks_table(connection)
self._ensure_approved_source_ref_columns(connection)
self._ensure_evidence_relationship_columns(connection)
self._ensure_expectation_gaps_table(connection)
def connect(self) -> sqlite3.Connection:
@@ -70,6 +71,41 @@ class RegistryStore:
f"ALTER TABLE {table} ADD COLUMN source_refs TEXT NOT NULL DEFAULT '[]'"
)
def _ensure_evidence_relationship_columns(
self,
connection: sqlite3.Connection,
) -> None:
for table in ("candidate_evidence", "approved_evidence"):
columns = {
row["name"]
for row in connection.execute(f"PRAGMA table_info({table})").fetchall()
}
if "target_kind" not in columns:
connection.execute(
f"ALTER TABLE {table} ADD COLUMN target_kind TEXT NOT NULL DEFAULT 'capability'"
)
if "target_id" not in columns:
connection.execute(f"ALTER TABLE {table} ADD COLUMN target_id INTEGER")
if "reference_kind" not in columns:
connection.execute(
f"ALTER TABLE {table} ADD COLUMN reference_kind TEXT NOT NULL DEFAULT 'source'"
)
if "reference_id" not in columns:
connection.execute(
f"ALTER TABLE {table} ADD COLUMN reference_id INTEGER"
)
connection.execute(
f"""
UPDATE {table}
SET target_kind = COALESCE(NULLIF(target_kind, ''), 'capability'),
target_id = COALESCE(target_id, capability_id),
reference_kind = COALESCE(NULLIF(reference_kind, ''), 'source')
WHERE target_id IS NULL
OR target_kind = ''
OR reference_kind = ''
"""
)
def _ensure_content_chunks_table(self, connection: sqlite3.Connection) -> None:
connection.execute(
"""
@@ -355,16 +391,21 @@ class RegistryStore:
connection.execute(
"""
INSERT INTO candidate_evidence
(repository_id, analysis_run_id, capability_id, type,
reference, strength, source_refs)
VALUES (?, ?, ?, ?, ?, ?, ?)
(repository_id, analysis_run_id, capability_id,
target_kind, target_id, type, reference,
reference_kind, reference_id, strength, source_refs)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
repository_id,
analysis_run_id,
capability_id,
"capability",
capability_id,
evidence.type,
evidence.reference,
"source",
None,
evidence.strength,
self._source_refs_to_json(evidence.source_refs),
),
@@ -409,7 +450,8 @@ class RegistryStore:
).fetchall()
evidence_rows = connection.execute(
"""
SELECT id, capability_id, type, reference, strength, status, source_refs
SELECT id, capability_id, target_kind, target_id, type, reference,
reference_kind, reference_id, strength, status, source_refs
FROM candidate_evidence
WHERE repository_id = ? AND analysis_run_id = ?
ORDER BY id
@@ -442,6 +484,10 @@ class RegistryStore:
strength=row["strength"],
status=row["status"],
source_refs=self._source_refs_from_json(row["source_refs"]),
target_kind=row["target_kind"],
target_id=row["target_id"],
reference_kind=row["reference_kind"],
reference_id=row["reference_id"],
)
)
@@ -1709,20 +1755,30 @@ class RegistryStore:
type: str,
reference: str,
strength: str,
target_kind: str = "capability",
target_id: int | None = None,
reference_kind: str = "source",
reference_id: int | None = None,
source_refs: list[SourceReference] | None = None,
) -> int:
target_id = capability_id if target_id is None else target_id
with self.connect() as connection:
cursor = connection.execute(
"""
INSERT INTO approved_evidence
(repository_id, capability_id, type, reference, strength, source_refs)
VALUES (?, ?, ?, ?, ?, ?)
(repository_id, capability_id, target_kind, target_id, type,
reference, reference_kind, reference_id, strength, source_refs)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
repository_id,
capability_id,
target_kind,
target_id,
type,
reference,
reference_kind,
reference_id,
strength,
self._source_refs_to_json(source_refs or []),
),
@@ -1737,6 +1793,10 @@ class RegistryStore:
type: str | None = None,
reference: str | None = None,
strength: str | None = None,
target_kind: str | None = None,
target_id: int | None = None,
reference_kind: str | None = None,
reference_id: int | None = None,
) -> None:
self._update_approved_row(
table="approved_evidence",
@@ -1747,6 +1807,10 @@ class RegistryStore:
"type": type,
"reference": reference,
"strength": strength,
"target_kind": target_kind,
"target_id": target_id,
"reference_kind": reference_kind,
"reference_id": reference_id,
},
)
@@ -1837,15 +1901,20 @@ class RegistryStore:
connection.execute(
"""
INSERT INTO approved_evidence
(repository_id, capability_id, type, reference, strength,
(repository_id, capability_id, target_kind, target_id,
type, reference, reference_kind, reference_id, strength,
source_refs)
VALUES (?, ?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
repository_id,
approved_capability_id,
evidence.target_kind,
evidence.target_id or approved_capability_id,
evidence.type,
evidence.reference,
evidence.reference_kind,
evidence.reference_id,
evidence.strength,
self._source_refs_to_json(evidence.source_refs),
),
@@ -1883,7 +1952,8 @@ class RegistryStore:
).fetchall()
evidence_rows = connection.execute(
"""
SELECT id, capability_id, type, reference, strength, source_refs
SELECT id, capability_id, target_kind, target_id, type, reference,
reference_kind, reference_id, strength, source_refs
FROM approved_evidence
WHERE repository_id = ?
ORDER BY id
@@ -1914,6 +1984,10 @@ class RegistryStore:
reference=row["reference"],
strength=row["strength"],
source_refs=self._source_refs_from_json(row["source_refs"]),
target_kind=row["target_kind"],
target_id=row["target_id"],
reference_kind=row["reference_kind"],
reference_id=row["reference_id"],
)
)