# Leo / Teleo DB Provenance And Load Path

Generated UTC: `2026-07-09T21:47:41Z`

Scope: read-only local repo/report inspection plus read-only VPS Postgres catalog and count queries. No production DB writes, no service restarts, no Telegram sends, and no public posting were performed.

## Executive Answer

The current Leo/Teleo knowledge base is canonical in Postgres, not Forgejo, not runtime memory, and not the local workspace. The live VPS host `77.42.65.182` currently has Docker container `teleo-pg` running database `teleo`. The canonical rows live mainly in `public.claims`, `public.sources`, `public.claim_evidence`, and `public.claim_edges`. Staging and review live in `kb_stage.*`, especially `kb_stage.kb_proposals`.

Forgejo is confirmed as part of the code/file-KB pipeline and deployment/mirror workflow. It is not confirmed by the evidence inspected here as the direct bootstrap source of the current live Postgres database. The strongest supported wording is: the older Teleo pipeline processed contributions through Forgejo and an SQLite state store, while the current Leo KB runtime uses Postgres canonical/staging tables. The exact one-time bootstrap path from Forgejo/file KB/SQLite/import tables into the current VPS `teleo` database remains unknown unless a separate bootstrap log, migration commit, or import-run record is found and tied to the live DB creation.

## Confirmed Facts

### Live Runtime

Read-only VPS command:

```bash
ssh -i ~/.ssh/livingip_hetzner_20260604_ed25519 -o BatchMode=yes -o StrictHostKeyChecking=accept-new root@77.42.65.182 \
  "docker ps --format '{{.Names}} {{.Status}}' | grep -E '^(teleo-pg|leoclean-gateway|livingip|teleo)' || true"
```

Readback included:

```text
teleo-pg Up 6 days
```

The first attempted catalog query using role `teleo` failed:

```text
FATAL: role "teleo" does not exist
```

The read-only retry used `postgres` for catalog reads and confirmed database `teleo` exists:

```text
datname
postgres
teleo
```

### Canonical And Staging Tables

Read-only catalog query confirmed these relevant tables:

```text
kb_stage.canonical_mappings
kb_stage.document_evaluations
kb_stage.edge_ref_aliases
kb_stage.import_runs
kb_stage.inventory_items
kb_stage.inventory_summary
kb_stage.kb_proposals
kb_stage.latest_inventory
kb_stage.pending_kb_proposals
kb_stage.staged_claim_edges
kb_stage.staged_claim_sources
kb_stage.staged_claims
kb_stage.staged_sources
kb_stage.telegram_file_refs
kb_stage.transform_summary
public.claim_edges
public.claim_evidence
public.claims
public.sources
public.strategy_node_anchors
```

Live counts at readback time:

```text
kb_stage.kb_proposals 26
public.claim_edges 4916
public.claim_evidence 4670
public.claims 1837
public.sources 4145
```

`kb_stage.kb_proposals` status counts:

```text
applied 2
approved 3
canceled 7
pending_review 14
```

Proposal type/status counts:

```text
add_edge applied 1
add_edge pending_review 4
attach_evidence applied 1
attach_evidence approved 3
attach_evidence canceled 7
attach_evidence pending_review 10
```

### Current Claim Schema

`public.claims` columns read back live:

```text
id uuid
type text
text text
status text
confidence numeric
tags ARRAY
created_by uuid
superseded_by uuid
created_at timestamp with time zone
updated_at timestamp with time zone
```

This confirms the retained report claim: current `public.claims` has `text`, `status`, `confidence`, `tags`, and `superseded_by`, but no canonical `body` column and no generic metadata JSONB column.

`public.sources` carries source-side detail:

```text
id uuid
source_type text
url text
storage_path text
excerpt text
hash text
captured_at timestamp with time zone
created_by uuid
created_at timestamp with time zone
```

`kb_stage.kb_proposals` carries proposal payload and ledger fields:

```text
id uuid
proposal_type text
status text
proposed_by_handle text
proposed_by_agent_id uuid
channel text
source_ref text
rationale text
payload jsonb
reviewed_by_handle text
reviewed_by_agent_id uuid
reviewed_at timestamp with time zone
review_note text
applied_by_handle text
applied_by_agent_id uuid
applied_at timestamp with time zone
created_at timestamp with time zone
updated_at timestamp with time zone
```

### Apply Path

The repo contains a guarded apply path:

- `scripts/approve_proposal.py` moves exactly one strict pending proposal to `approved` only when it has a supported type and `payload.apply_payload`.
- `scripts/apply_proposal.py` applies an approved proposal into canonical `public.*` rows through the narrow `kb_apply` role.
- `scripts/apply_worker.py` can apply approved+applyable proposals, but it is report-only unless explicitly enabled.
- Supported narrow proposal types are `revise_strategy`, `add_edge`, and `attach_evidence`.

Current worker limitation from retained reports and code: it does not create new `public.claims` or `public.sources` rows. Rich/freeform approved proposals that need claim/source creation must be normalized, rehearsed in clone/staging, and then applied through a reviewed packet or a widened apply contract.

### Agent Self-Update Rule

The agent-facing bridge states that the canonical KB is Postgres, not runtime memory. Normal chat/agent action can stage reviewable proposals in `kb_stage.kb_proposals`, but it must not directly mutate canonical `public.*` rows.

For strategy/self updates:

1. Leo reads canonical context from Postgres through the `teleo-kb` bridge.
2. Leo proposes a change such as `revise_strategy` into `kb_stage.kb_proposals`.
3. A reviewer/operator approves it.
4. The guarded apply tool/worker writes `public.strategies` and `public.strategy_nodes` and stamps the proposal `applied`.
5. A render step, where configured, refreshes Leo's rendered self/context from canonical DB state.

File-backed `agent-state/` is operational continuity, not canonical truth. Its schema explicitly says "State != Git" and the bridge says "agent memory = local/runtime continuity; Postgres KB = canonical collective knowledge."

## Inferred Facts

These are likely but not fully proven by this pass:

- The current Postgres DB was built after or alongside the older Forgejo/file-KB/SQLite pipeline, because the repo still contains the older pipeline model and also contains Postgres-native staging/import objects.
- `kb_stage.import_runs`, `staged_claims`, `staged_sources`, `staged_claim_edges`, and `staged_claim_sources` suggest an import/transform path existed for loading data into Postgres, but this pass did not tie a specific import run to the original live DB bootstrap.
- The old file-KB pipeline and Postgres-native path currently coexist in the codebase and reports. Forgejo remains relevant for code deployment and old file-KB PR workflows, but canonical Leo answers and KB apply status are now Postgres-backed.

## Unknowns

- The exact initial bootstrap command or migration that created and populated live VPS database `teleo`.
- Whether the first live Postgres canonical rows were imported from Forgejo checkout files, from a SQLite backup, from staged import tables, or from a separate SQL dump.
- Which exact commit, operator, or import-run record first declared the Postgres DB canonical.
- Whether `kb_stage.import_runs` contains a complete bootstrap history. I did not query row contents here because the deliverable only required structure/provenance, and table contents may include operational source material.

## How Loading Works Now

### Code And Service Loading

The repo README and deploy scripts show:

```text
Forgejo/Git remotes -> deploy checkout -> deploy/auto-deploy.sh -> rsync into /opt/teleo-eval runtime dirs -> selective systemd restarts
```

`deploy/auto-deploy.sh` fetches `main`, fast-forwards the deploy checkout, syntax-checks Python, syncs `lib/`, `telegram/`, `diagnostics/`, `agent-state/`, `tests/`, and Hermes skills into runtime paths, then restarts changed services. `deploy/sync-mirror.sh` shows Forgejo as authoritative for the older mirror flow, with GitHub public mirror integration.

This is code/runtime deployment. It is not proof that Forgejo is the live Postgres KB.

### Legacy File-KB Pipeline Loading

The README describes an older/mainline pipeline:

```text
inbox/queue -> extract -> validate -> evaluate -> merge through Forgejo -> effects
```

It also says the daemon talks to a Forgejo git server and an SQLite WAL state store, and that external contributor PRs mirror from GitHub to Forgejo. This proves Forgejo's role in the historical file/PR pipeline.

### Current Postgres KB Loading

The current Postgres-native path is:

```text
agent/user/change request
-> teleo-kb bridge or proposal generator
-> kb_stage.kb_proposals pending_review
-> reviewer/operator approval
-> strict apply_payload or reviewed packet
-> guarded apply as kb_apply/operator
-> canonical public.* rows
-> applied ledger readback
-> rendered/context surfaces refresh
```

Narrow supported canonical writes:

- `add_edge` -> insert into `public.claim_edges`
- `attach_evidence` -> insert into `public.claim_evidence` using existing `source_id`
- `revise_strategy` -> update/insert `public.strategies` and `public.strategy_nodes`

Rich proposal packets can generate `public.claims`, `public.sources`, `public.claim_edges`, and `public.claim_evidence` SQL, but the retained July 9 packets are clone/rehearsal-proven unless explicitly production-applied.

### Restore / Shadow Loading Evidence

`ops/sqlite_to_postgres_dump.py` converts a Teleo SQLite backup into a Postgres restore script under a separate schema, with constraints and indexes not recreated. `ops/run_sqlite_postgres_restore_canary.sh` restores a SQLite backup into a disposable local Postgres container and compares source/target counts. `ops/verify_gcp_cloudsql_restore_readback.py` verifies Cloud SQL restore parity from retained drill proof and CSV counts.

This is evidence of a restore/shadow/parity workflow. It is not direct evidence that live VPS `teleo` was originally bootstrapped from Forgejo.

## Canonical Vs Staging Vs Workspace

### Canonical

Canonical means live Postgres rows in `public.*` on the current canonical DB:

- `public.claims`
- `public.sources`
- `public.claim_evidence`
- `public.claim_edges`
- strategy/self tables such as `public.strategies`, `public.strategy_nodes`, and anchors such as `public.strategy_node_anchors`

A KB change is implemented only when canonical rows and the `kb_stage.kb_proposals` ledger show the applied state.

### Staging

Staging means durable but not canonical proposal/import state in `kb_stage.*`:

- `kb_stage.kb_proposals`
- `kb_stage.pending_kb_proposals`
- staged/import tables such as `staged_claims`, `staged_sources`, `staged_claim_edges`, `staged_claim_sources`, and `import_runs`

`approved` does not mean implemented. `applied` plus canonical row readback is the implementation proof.

### Workspace

Workspace means repo files, local reports, generated SQL packets, clone rehearsal logs, and deployment scripts. Workspace artifacts can explain or rehearse a change, but they are not canonical KB truth unless applied to the canonical DB and read back.

Forgejo/Git is canonical for repo/code history in the older pipeline and deployment flow. It is not the canonical Leo KB state.

## Direct Answers

### How do we load?

Code loads through Git/Forgejo/GitHub mirror and `deploy/auto-deploy.sh` into VPS runtime directories. KB truth loads through Postgres staging and guarded apply: proposals in `kb_stage.kb_proposals`, reviewer approval, strict apply payload or reviewed packet, canonical `public.*` writes, then readback.

### How did the current DB originate relative to Forgejo?

Confirmed: Forgejo was central to the older PR/file-KB pipeline and deployment/mirror workflow. Confirmed: current Leo KB truth is Postgres. Unknown: the exact original bootstrap path that populated the current live Postgres `teleo` database. No inspected file or live readback proves "the live Postgres DB was initially built from Forgejo." Treat Forgejo as code/file-workflow provenance unless a separate bootstrap/import artifact proves a direct DB origin.

### How can or should Leo update itself?

Leo should read canonical Postgres context, stage proposed self/strategy/claim changes in `kb_stage.kb_proposals`, and wait for reviewer/operator approval. It should not directly update canonical `public.*` rows or treat runtime memory as canonical. For a strategy/self update, the safe path is `revise_strategy` proposal -> approval -> guarded apply -> render/readback.

### What is canonical vs staging vs workspace?

Canonical is live Postgres `public.*`. Staging is `kb_stage.*` proposals/imports. Workspace is repo files, reports, diagrams, generated SQL packets, and rehearsal artifacts. Forgejo/Git is code/file workflow provenance, not current KB truth.

## Evidence Files Inspected

- `README.md`
- `deploy/auto-deploy.sh`
- `deploy/sync-mirror.sh`
- `systemd/teleo-auto-deploy.service`
- `ops/sqlite_to_postgres_dump.py`
- `ops/run_sqlite_postgres_restore_canary.sh`
- `ops/verify_gcp_cloudsql_restore_readback.py`
- `scripts/approve_proposal.py`
- `scripts/apply_proposal.py`
- `scripts/apply_worker.py`
- `scripts/kb_proposal_review_packet.py`
- `scripts/kb_proposal_normalize.py`
- `scripts/kb_rich_proposal_creation_plan.py`
- `scripts/kb_apply_prereqs.sql`
- `hermes-agent/leoclean-bin/cloudsql_memory_tool.py`
- `hermes-agent/leoclean-skills/vps/teleo-kb-bridge/SKILL.md`
- `hermes-agent/leoclean-skills/gcp/teleo-kb-bridge/SKILL.md`
- `agent-state/SCHEMA.md`
- `agent-state/lib-state.sh`
- `docs/reports/leo-working-state-20260709/current-truth-index.md`
- `docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md`
- `docs/reports/leo-working-state-20260709/operator-surface-map.md`
- `docs/reports/leo-working-state-20260709/kb-apply-canary-plan-current.md`
- `docs/reports/leo-working-state-20260709/kb-apply-canary-execute-current.md`
- `docs/reports/leo-working-state-20260709/claim-source-contract-preview-current.md`
- `docs/reports/leo-working-state-20260709/rich-proposal-creation-plan-mapped-current.md`
- `docs/reports/leo-working-state-20260709/cross-surface-resolution-current.md`

## Claim Ceiling

This report proves current structure and current load/apply semantics from repo evidence plus live read-only schema/count readbacks. It does not prove the original live DB bootstrap story. The missing proof would be a retained initial import log, migration SQL, `kb_stage.import_runs` bootstrap record, DB creation audit trail, or old operator notes tied to the first population of VPS database `teleo`.
