Complete remaining medium/low issues: performance, CLI, types, CI, tests

Performance:
- Batch readiness computation (~200 queries → ~6 per page)
- Batch draft lookup in author network (N+1 → single query)
- File-based similarity matrix cache (.npy + metadata sidecar)
- 5-minute TTL embedding cache for search queries

CLI quality:
- Add pass_cfg_db decorator, convert ~30 commands to shared config/db lifecycle
- Add --dry-run to analyze, embed, embed-ideas, ideas, gaps commands
- Move 15+ in-function imports to top of data.py

Types & documentation:
- Add 16 TypedDicts to data.py, annotate 12 function return types
- Add ethics section to Post 06 (premature standardization, power asymmetry)
- Add EU AI Act Article 43 conformity mapping to Post 06
- Add NIS2 and CRA references to Post 04

CI & testing:
- Add GitHub Actions CI workflow (Python 3.11+3.12, ruff, pytest)
- Add API documentation for all 20 endpoints (data/reports/api-docs.md)
- Add 41 new tests (test_analyzer.py, test_search.py) — 64 total pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 14:06:54 +01:00
parent e7527ad68e
commit 20c45a7eba
14 changed files with 2305 additions and 1238 deletions

View File

@@ -326,6 +326,23 @@ class Database:
return None
return self._row_to_draft(row)
def get_drafts_by_names(self, names: list[str]) -> dict[str, "Draft"]:
"""Batch-fetch drafts by name. Returns {name: Draft} dict."""
if not names:
return {}
result = {}
# SQLite has a variable limit (~999), so chunk if needed
for i in range(0, len(names), 900):
chunk = names[i : i + 900]
placeholders = ",".join("?" for _ in chunk)
rows = self.conn.execute(
f"SELECT * FROM drafts WHERE name IN ({placeholders})", chunk
).fetchall()
for r in rows:
d = self._row_to_draft(r)
result[d.name] = d
return result
def list_drafts(
self,
limit: int = 100,