Spec: Synthesis Engine — Auto-Aggregate Discussion Threads
Task ID: f302fe3e-c145-495c-aa64-a61529227e30
Layer: Agora
Status: done
Created: 2026-04-12
Goal
Build an automated synthesis engine that aggregates discussion threads into structured summaries at key moments:
After debate rounds - wire Synthesizer persona output as a first-class synthesis artifact
After 10+ comments on an artifact - auto-trigger LLM summarization
Weekly per landscape - domain-wide synthesis of all activity in a domain
On merge/archive decisions - rationale explanationSchema
artifact_syntheses table (already exists in DB from prior migration):
- id TEXT PK
- artifact_id TEXT FK -> artifacts.id
- source_comment_ids TEXT (JSON array of IDs)
- synthesis_text TEXT
- methodology TEXT (e.g. "debate-synthesizer", "llm-summarization")
- confidence_score REAL
- trigger_type TEXT (debate-round, comment-threshold, weekly, merge-archive)
- synthesized_by TEXT
- created_at TIMESTAMP
API
- POST /api/artifacts/{artifact_id}/synthesize - trigger synthesis
- Body: { "synthesized_by": "agent-id", "comment_ids": [...] } (optional)
- Returns: synthesis record
- GET /api/artifacts/{artifact_id}/synthesis - get latest synthesis
- Query: ?all=true for all syntheses
Module: synthesis_engine.py
Functions:
- synthesize_debate_session(conn, session_id, analysis_id) - extract Synthesizer output
- synthesize_comment_thread(conn, artifact_id, comment_ids, synthesized_by) - LLM synthesis
- auto_synthesize_if_threshold(conn, artifact_id) - check count and auto-trigger
- synthesize_landscape_weekly(conn, landscape_id) - weekly domain sweep
- synthesize_merge_archive_rationale(conn, artifact_id, decision, rationale, decided_by)
- get_synthesis(conn, artifact_id) - get latest
- get_all_syntheses(conn, artifact_id) - get all
Work Log
2026-04-18
- Bug fix: PostgreSQL compatibility — synthesis_engine.py was written for SQLite but the API uses PostgreSQL via PGConnection wrapper
- Root cause:
conn.cursor() doesn't exist on PGConnection; uses conn.execute() instead
- SQLite
? placeholders → PostgreSQL %s
datetime('now', '-N hours') → NOW() - INTERVAL 'N hours'
datetime('now') → NOW()
- Commit: a4e465ddf — [Agora] Fix synthesis_engine.py for PostgreSQL compatibility [task:f302fe3e-c145-495c-aa64-a61529227e30]
2026-04-12
- DB schema already exists (artifact_syntheses table created in prior migration)
- artifact_comments has types: discussion, proposal, question, evidence, objection
- Created synthesis_engine.py with all 4 trigger types and read helpers
- Added POST /api/artifacts/{id}/synthesize and GET /api/artifacts/{id}/synthesis to api.py
- Debate synthesis auto-detects target_artifact_id from debate_sessions
- Comment auto-synthesis guards against re-synthesis within 1-hour cooldown window
- Weekly landscape synthesis pulls from artifact_comments + debate_sessions for past 7 days