Personal project · System & data model

AI Politician

A reasoning engine that turns a public question into a sourced, versioned political position — checks its own work, measures its own fairness, and records every step so the record can be audited, never quietly rewritten.

Python SQLAlchemy · SQLite LLM pipeline (Claude API) JSON-Schema validation FastAPI Jinja2 static site pytest · 68 tests ~5,400 LOC · 29 modules · 12 tables
01

In plain English — the whole journey

No jargon. Here is what happens from the moment a question arrives to the moment an answer is public — and how the system keeps improving its own past answers.

1 Someone asks a question

A real-world question comes in — "Why does Australia sell uranium to India but not use nuclear power at home?"

2 It gathers the evidence

It searches the web, collects real sources, and grades each one for trustworthiness — an official government report counts for more than a random blog.

3 It writes a first draft

It drafts an answer based only on what the evidence actually supports — not on opinion.

4 It argues with itself

It criticises its own draft, rewrites it, then deliberately argues the opposite side to catch its own bias before anyone else can.

5 It fact-checks itself

Before publishing, it re-opens every source it cited and confirms the figures it quoted are really there. If a number can't be found, the answer is blocked.

6 It publishes — or holds back

Pass every check and the answer goes live on the public website. Fail one and it's set aside for a human. It never publishes what it couldn't verify.

7 It records everything it did

Every step is saved to a permanent log that can't be secretly edited later, so anyone can trace exactly how the answer was formed.

8 It keeps re-checking its old answers

As new questions are answered, the system spots when older answers now clash or look weak — and sends them back through the process. The old version stays on the record; a new, improved version replaces it in public.
↺ loops back to step 2

02

What keeps it honest — in plain words

The point of the whole system is trust. These are the guardrails, each in one sentence.

It shows its work

Every answer links to real sources and keeps the full record of how it was written.

It fact-checks its own numbers

Before publishing, it re-reads its sources and blocks anything it can't verify.

It measures its own fairness

It scores whether it treats each political party by the same standard — and publishes the score.

It argues the other side

Every answer is re-argued from the opposite view to catch bias before a reader would.

It notices when it's out of date

Old answers are flagged for review automatically as their facts age.

It can be challenged

Anyone can file a correction, which forces a revised version — the old one stays on the record.

It keeps score of itself

Its predictions are tracked, so you can later check whether it was actually right.

It can't be secretly edited

Everything is written to a tamper-proof log with a published fingerprint that changes if history is altered.

03

The same journey, in detail

Each question runs through a fixed multi-stage pipeline. Automated quality gates decide whether the result is trustworthy enough to publish; anything that fails is held or escalated for a human. Every stage is written to a tamper-evident log.

Issuea question enters the queue
1 · Evidenceweb search + tiering
2 · Draft
3 · Critique
4 · Revise
5 · Inversionargue the opposite
Automated quality gates
passes
Publishversioned position
Public websiteread-only, static
fails / ambiguous
Held or escalatedfor human oversight
Every step is written to a tamper-evident audit log (SHA-256 hash chain).
GATES The three checks a position must clear: enough credible evidence (at least two reputable sources and one primary/official source), substantiation (the specific figures it cites are actually found in the cited source text), and balance (sources aren't all leaning one way; topic coverage is measured).
04

Database schema

A normalised relational model built around versioning: a policy area keeps a full history of position versions, each tied to the constitution version it was reasoned from, the sources it cites, and the verbatim log of how it was produced. Nothing is overwritten — a revision adds a new version and supersedes the old one.

%%{init: {'theme':'base','themeVariables':{'fontFamily':'-apple-system,Segoe UI,Roboto,sans-serif','fontSize':'13px','primaryColor':'#f4f1e8','primaryTextColor':'#20303f','primaryBorderColor':'#16324f','lineColor':'#16324f'}}}%%
erDiagram
  ISSUES ||--o{ POLICIES : "spawns"
  POLICIES ||--o{ POSITION_VERSIONS : "has versions of"
  CONSTITUTION_VERSIONS ||--o{ POSITION_VERSIONS : "reasoned from"
  POSITION_VERSIONS ||--o{ REASONING_LOGS : "records each step"
  POSITION_VERSIONS ||--o{ POSITION_SOURCES : "cites"
  SOURCES ||--o{ POSITION_SOURCES : "cited in"
  POSITION_VERSIONS ||--o{ SOCIAL_POSTS : "drafts"

  ISSUES {
    int id PK
    string slug UK
    text question
    string status
  }
  POLICIES {
    int id PK
    string slug UK
    string title
    int issue_id FK
  }
  CONSTITUTION_VERSIONS {
    int id PK
    int version
    text principles_json
    string checksum
    string status
  }
  POSITION_VERSIONS {
    int id PK
    int policy_id FK
    int constitution_version_id FK
    int version
    string status
    string kind
    float confidence
    text position_md
    text key_claims_json
    text oversight_flags_json
  }
  SOURCES {
    int id PK
    string url
    int tier
    string publisher
    string origin
  }
  POSITION_SOURCES {
    int id PK
    int position_version_id FK
    int source_id FK
  }
  REASONING_LOGS {
    int id PK
    int position_version_id FK
    string step
    string agent
    int output_tokens
  }
  SOCIAL_POSTS {
    int id PK
    int position_version_id FK
    string platform
    string status
  }
  STATEMENTS {
    int id PK
    string slug UK
    text body_md
    string status
  }
  CHANGELOG_ENTRIES {
    int id PK
    string entity_slug
    string change_type
    text summary
  }
PK primary key FK foreign key UK unique key one ──< many (a policy has many versions)
AUDIT The audit log isn't a table — it's a separate append-only file where each entry embeds the SHA-256 hash of the entry before it. Editing or deleting any past record breaks the chain, so the history is tamper-evident. STATEMENTS and CHANGELOG_ENTRIES stand alone (the changelog references entities by slug, not a foreign key).