Document Working Leo DB identity provenance
Some checks are pending
CI / lint-and-test (push) Waiting to run

- Map VPS Hermes, Forgejo, SOUL rendering, and document-artifact boundaries.

- Expand Cory-style benchmark for identity render, decision matrix, and source refs.

- Retain live-readback diagrams/reports and focused test coverage.

`docs/reports/leo-working-state-20260709/current-truth-index.md`
`docs/reports/leo-working-state-20260709/leo-db-loading-diagram-20260709T214741Z.mmd`
`docs/reports/leo-working-state-20260709/leo-db-loading-diagram-20260709T214741Z.svg`
`docs/reports/leo-working-state-20260709/leo-db-provenance-report-20260709T214741Z.md`
`docs/reports/leo-working-state-20260709/leo-db-state-21-forgejo-load-agent-loop.svg`
`docs/reports/leo-working-state-20260709/leo-db-state-22-identity-render-matrix-artifacts.svg`
`docs/reports/leo-working-state-20260709/vps-hermes-db-mapping-20260709.md`
`docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md`
`docs/reports/leo-working-state-20260709/working-leo-open-ended-benchmark-spec.json`
`scripts/working_leo_open_ended_benchmark.py`
`tests/test_working_leo_open_ended_benchmark.py`
This commit is contained in:
twentyOne2x 2026-07-09 23:59:27 +02:00
parent 1826206053
commit ae00beeb3b
11 changed files with 1592 additions and 4 deletions

View file

@ -13,6 +13,8 @@ Use this file before making status claims. Prefer fresh VPS/GCP readbacks when c
- Open-ended live Telegram canary JSON: `docs/reports/leo-working-state-20260709/telegram-live-open-ended-cory-style-20260709.json` - Open-ended live Telegram canary JSON: `docs/reports/leo-working-state-20260709/telegram-live-open-ended-cory-style-20260709.json`
- Fable onboarding prompt: `docs/reports/leo-working-state-20260709/fable-leo-teleo-onboarding.md` - Fable onboarding prompt: `docs/reports/leo-working-state-20260709/fable-leo-teleo-onboarding.md`
- Operator surface map: `docs/reports/leo-working-state-20260709/operator-surface-map.md` - Operator surface map: `docs/reports/leo-working-state-20260709/operator-surface-map.md`
- VPS/Hermes/DB mapping: `docs/reports/leo-working-state-20260709/vps-hermes-db-mapping-20260709.md`
- DB provenance/load-path report: `docs/reports/leo-working-state-20260709/leo-db-provenance-report-20260709T214741Z.md`
## Telegram And Live Leo Proof ## Telegram And Live Leo Proof
@ -58,6 +60,10 @@ Use this file before making status claims. Prefer fresh VPS/GCP readbacks when c
- Leoclean DB versus workspace map: `docs/reports/leo-working-state-20260709/leo-db-state-18-db-vs-workspace.svg` - Leoclean DB versus workspace map: `docs/reports/leo-working-state-20260709/leo-db-state-18-db-vs-workspace.svg`
- Claim/body/metadata schema map: `docs/reports/leo-working-state-20260709/leo-db-state-19-claims-body-metadata.svg` - Claim/body/metadata schema map: `docs/reports/leo-working-state-20260709/leo-db-state-19-claims-body-metadata.svg`
- Cross-surface strategy anchor proof: `docs/reports/leo-working-state-20260709/leo-db-state-20-cross-surface-anchor.svg` - Cross-surface strategy anchor proof: `docs/reports/leo-working-state-20260709/leo-db-state-20-cross-surface-anchor.svg`
- Forgejo/load/agent update loop map: `docs/reports/leo-working-state-20260709/leo-db-state-21-forgejo-load-agent-loop.svg`
- Identity render / decision matrix / document artifact map: `docs/reports/leo-working-state-20260709/leo-db-state-22-identity-render-matrix-artifacts.svg`
- DB loading diagram SVG: `docs/reports/leo-working-state-20260709/leo-db-loading-diagram-20260709T214741Z.svg`
- DB loading diagram Mermaid source: `docs/reports/leo-working-state-20260709/leo-db-loading-diagram-20260709T214741Z.mmd`
## Current Claim Ceiling ## Current Claim Ceiling
@ -68,6 +74,9 @@ Use this file before making status claims. Prefer fresh VPS/GCP readbacks when c
- Helmer 7 Powers is full-coverage packet and ledger clone-proven, not production-applied. - Helmer 7 Powers is full-coverage packet and ledger clone-proven, not production-applied.
- Mapped rich approved proposal packet is clone/rehearsal-proven for the supported subset, not production-applied. - Mapped rich approved proposal packet is clone/rehearsal-proven for the supported subset, not production-applied.
- The strategy-anchor companion write for mapped rich proposal `14fa5ecc` is clone-proven and reversible, not production-applied. - The strategy-anchor companion write for mapped rich proposal `14fa5ecc` is clone-proven and reversible, not production-applied.
- DB-first identity rendering is now documented from the July 9 PDFs plus VPS readback: canonical identity rows feed rendered `SOUL.md`, direct SOUL edits are not canonical DB updates, and no active renderer/timer/hook is proven in the current VPS readback.
- The decision-matrix approval schema is still a target design on the current VPS: `kb_stage.matrix_voters`, `kb_stage.proposal_votes`, and `kb_stage.proposal_decisions` were not present in live schema readback.
- Pending/approved document proposals are real `kb_stage.kb_proposals` rows with `source_ref`s, but inspected `source_ref`s did not directly match `public.sources`; they still need review/apply mapping into canonical sources/evidence/edges.
- Governance-gate, concept-map, and Rio strategy targets remain explicitly deferred because current schema has no safe direct write path for them. - Governance-gate, concept-map, and Rio strategy targets remain explicitly deferred because current schema has no safe direct write path for them.
- The live VPS runtime behavior should not be changed while the DB apply path is stabilized. - The live VPS runtime behavior should not be changed while the DB apply path is stabilized.
- GCP parity remains blocked by account auth/access facts until a fresh readback proves otherwise. - GCP parity remains blocked by account auth/access facts until a fresh readback proves otherwise.

View file

@ -0,0 +1,40 @@
flowchart LR
subgraph repo["Repo / Forgejo / Git workflow"]
A["Forgejo / Git remotes<br/>code + legacy file-KB PR flow"]
B["deploy/auto-deploy.sh<br/>fetch main, syntax-check, rsync runtime dirs"]
C["VPS runtime dirs<br/>/opt/teleo-eval, /home/teleo profile"]
A --> B --> C
end
subgraph pg["Docker Postgres on VPS 77.42.65.182"]
D["teleo-pg container<br/>database teleo"]
E["canonical public.*<br/>claims, sources, claim_evidence, claim_edges<br/>strategies, strategy_nodes, anchors"]
F["staging kb_stage.*<br/>kb_proposals, pending proposals,<br/>staged/import tables"]
D --> E
D --> F
end
subgraph load["KB loading and apply"]
G["Leo / user / operator request"]
H["teleo-kb bridge or proposal generator"]
I["kb_stage.kb_proposals<br/>pending_review"]
J["reviewer/operator approval<br/>approved"]
K["strict apply_payload or reviewed packet"]
L["guarded apply<br/>kb_apply/operator"]
M["ledger stamped applied<br/>canonical readback"]
G --> H --> I --> J --> K --> L --> E --> M
I -. "not canonical yet" .-> F
end
subgraph self["Agent self-update loop"]
N["Leo reads canonical context<br/>Postgres first, not runtime memory"]
O["Leo proposes self/strategy change<br/>revise_strategy"]
P["apply updates strategies/nodes"]
Q["renderer/context refresh<br/>Leo reads new self"]
E --> N --> O --> I
L --> P --> Q --> N
end
C --> H
C --> D
A -. "confirmed code/file workflow provenance<br/>direct live DB bootstrap unknown" .-> D

View file

@ -0,0 +1,122 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1480" height="980" viewBox="0 0 1480 980" role="img" aria-labelledby="title desc">
<title id="title">Leo / Teleo DB provenance and loading path</title>
<desc id="desc">Diagram separating Forgejo repo provenance, Docker Postgres canonical tables, staging proposals, approval apply path, and Leo self-update loop.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#1f2937"/>
</marker>
<style>
.bg { fill: #fbfbf8; }
.band { fill: #ffffff; stroke: #d0d7de; stroke-width: 2; rx: 10; }
.bandTitle { font: 700 18px Arial, sans-serif; fill: #111827; }
.box { fill: #f8fafc; stroke: #475569; stroke-width: 2; rx: 8; }
.boxRepo { fill: #eef6ff; stroke: #2563eb; }
.boxDb { fill: #ecfdf5; stroke: #059669; }
.boxStage { fill: #fff7ed; stroke: #ea580c; }
.boxApply { fill: #f5f3ff; stroke: #7c3aed; }
.boxUnknown { fill: #fef2f2; stroke: #dc2626; stroke-dasharray: 6 5; }
.label { font: 700 15px Arial, sans-serif; fill: #0f172a; }
.small { font: 13px Arial, sans-serif; fill: #334155; }
.tiny { font: 12px Arial, sans-serif; fill: #475569; }
.edge { stroke: #1f2937; stroke-width: 2.2; fill: none; marker-end: url(#arrow); }
.edgeDashed { stroke: #64748b; stroke-width: 2; stroke-dasharray: 7 5; fill: none; marker-end: url(#arrow); }
.note { font: 13px Arial, sans-serif; fill: #7f1d1d; }
</style>
</defs>
<rect class="bg" width="1480" height="980"/>
<text x="48" y="52" style="font:700 28px Arial, sans-serif; fill:#111827;">Leo / Teleo DB Provenance And Loading Path</text>
<text x="48" y="82" class="small">Confirmed current state: Docker Postgres is canonical. Forgejo is proven for repo/code and legacy file-KB workflow; direct initial DB bootstrap from Forgejo is not proven.</text>
<rect x="40" y="120" width="410" height="270" class="band"/>
<text x="64" y="152" class="bandTitle">Repo / Forgejo / Deployment</text>
<rect x="70" y="180" width="340" height="68" class="box boxRepo"/>
<text x="90" y="207" class="label">Forgejo / Git remotes</text>
<text x="90" y="229" class="small">code, legacy file-KB PR flow, mirrors</text>
<rect x="70" y="282" width="340" height="76" class="box boxRepo"/>
<text x="90" y="309" class="label">deploy/auto-deploy.sh</text>
<text x="90" y="331" class="small">fetch main, syntax-check, rsync runtime dirs</text>
<text x="90" y="349" class="tiny">restarts changed services only</text>
<rect x="520" y="120" width="430" height="348" class="band"/>
<text x="544" y="152" class="bandTitle">Docker Postgres Canonical DB</text>
<rect x="560" y="180" width="350" height="68" class="box boxDb"/>
<text x="580" y="207" class="label">teleo-pg container</text>
<text x="580" y="229" class="small">VPS 77.42.65.182, database teleo</text>
<rect x="560" y="282" width="350" height="92" class="box boxDb"/>
<text x="580" y="309" class="label">canonical public.*</text>
<text x="580" y="331" class="small">claims, sources, claim_evidence, claim_edges</text>
<text x="580" y="350" class="small">strategies, strategy_nodes, anchors</text>
<rect x="560" y="396" width="350" height="48" class="box boxUnknown"/>
<text x="580" y="425" class="label">Initial DB bootstrap: unknown</text>
<rect x="1015" y="120" width="420" height="348" class="band"/>
<text x="1039" y="152" class="bandTitle">Staging / Review / Apply</text>
<rect x="1055" y="180" width="340" height="82" class="box boxStage"/>
<text x="1075" y="207" class="label">kb_stage.*</text>
<text x="1075" y="229" class="small">kb_proposals, pending proposals</text>
<text x="1075" y="247" class="small">staged/import tables and transform summaries</text>
<rect x="1055" y="296" width="340" height="72" class="box boxApply"/>
<text x="1075" y="323" class="label">reviewer/operator approval</text>
<text x="1075" y="345" class="small">pending_review -&gt; approved</text>
<rect x="1055" y="396" width="340" height="48" class="box boxApply"/>
<text x="1075" y="425" class="label">guarded apply -&gt; applied readback</text>
<rect x="145" y="540" width="1190" height="330" class="band"/>
<text x="169" y="572" class="bandTitle">Current KB Loading And Leo Self-Update Loop</text>
<rect x="190" y="620" width="190" height="70" class="box boxApply"/>
<text x="210" y="648" class="label">Leo / user request</text>
<text x="210" y="670" class="small">question, correction, strategy change</text>
<rect x="430" y="620" width="210" height="70" class="box boxApply"/>
<text x="450" y="648" class="label">teleo-kb bridge</text>
<text x="450" y="670" class="small">reads canonical, stages proposals</text>
<rect x="690" y="620" width="210" height="70" class="box boxStage"/>
<text x="710" y="648" class="label">kb_stage.kb_proposals</text>
<text x="710" y="670" class="small">pending_review, payload jsonb</text>
<rect x="950" y="620" width="210" height="70" class="box boxApply"/>
<text x="970" y="648" class="label">approval + apply</text>
<text x="970" y="670" class="small">strict apply_payload or packet</text>
<rect x="550" y="760" width="380" height="70" class="box boxDb"/>
<text x="570" y="788" class="label">canonical state changes</text>
<text x="570" y="810" class="small">public.* rows, strategies/nodes, applied ledger</text>
<rect x="980" y="760" width="280" height="70" class="box boxDb"/>
<text x="1000" y="788" class="label">render/context refresh</text>
<text x="1000" y="810" class="small">Leo reads new self from DB</text>
<path d="M410 214 H560" class="edge"/>
<path d="M240 248 V282" class="edge"/>
<path d="M410 320 C475 320 480 214 560 214" class="edge"/>
<path d="M910 214 H1055" class="edgeDashed"/>
<path d="M735 248 V282" class="edge"/>
<path d="M910 328 H1055" class="edgeDashed"/>
<path d="M1225 262 V296" class="edge"/>
<path d="M1225 368 V396" class="edge"/>
<path d="M1055 420 H910 V350" class="edge"/>
<path d="M380 655 H430" class="edge"/>
<path d="M640 655 H690" class="edge"/>
<path d="M900 655 H950" class="edge"/>
<path d="M1055 690 C1055 742 930 742 860 760" class="edge"/>
<path d="M930 795 H980" class="edge"/>
<path d="M1120 760 C1120 535 790 520 740 282" class="edgeDashed"/>
<path d="M740 374 C730 470 515 540 535 620" class="edgeDashed"/>
<text x="940" y="240" class="tiny">code/workflow provenance</text>
<text x="938" y="354" class="tiny">proposals are not canonical</text>
<text x="584" y="430" class="note">Need bootstrap log/import run to prove origin.</text>
<text x="190" y="900" class="small">Rule: approved is not applied. Canonical proof requires public.* row readback plus kb_stage ledger status = applied.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1,331 @@
# 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`.

View file

@ -0,0 +1,101 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="920" viewBox="0 0 1440 920" role="img" aria-labelledby="title desc">
<title id="title">Current Leo DB provenance, loading, and agent update loop</title>
<desc id="desc">Diagram explaining confirmed current state: Forgejo is code and pipeline provenance, Docker Postgres is the canonical KB database, staged proposals are reviewed and applied into public tables, and Leo updates its knowledge by proposing and reading DB rows rather than editing itself directly.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#334155"/>
</marker>
<marker id="softarrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#64748b"/>
</marker>
</defs>
<rect width="1440" height="920" fill="#f8fafc"/>
<text x="56" y="64" font-family="Arial, sans-serif" font-size="34" font-weight="700" fill="#0f172a">Leo DB provenance, loading, and self-update loop</text>
<text x="56" y="102" font-family="Arial, sans-serif" font-size="18" fill="#334155">Current evidence: Forgejo/repo pipeline moves code and archived source metadata; the live KB authority is Docker Postgres on the VPS.</text>
<rect x="56" y="124" width="1328" height="52" rx="8" fill="#e0f2fe" stroke="#38bdf8" stroke-width="1.5"/>
<text x="78" y="156" font-family="Arial, sans-serif" font-size="18" font-weight="700" fill="#075985">Canonical DB location:</text>
<text x="268" y="156" font-family="Arial, sans-serif" font-size="18" fill="#075985">VPS 77.42.65.182 -> Docker container teleo-pg -> Postgres database teleo -> schemas public and kb_stage</text>
<rect x="56" y="218" width="292" height="178" rx="8" fill="#ffffff" stroke="#475569" stroke-width="2"/>
<text x="82" y="255" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#1e293b">Forgejo / repo</text>
<text x="82" y="288" font-family="Arial, sans-serif" font-size="16" fill="#334155">Confirmed role</text>
<text x="104" y="318" font-family="Arial, sans-serif" font-size="15" fill="#475569">- code hosting and old PR pipeline</text>
<text x="104" y="344" font-family="Arial, sans-serif" font-size="15" fill="#475569">- archived source file links</text>
<text x="104" y="370" font-family="Arial, sans-serif" font-size="15" fill="#475569">- deploy provenance inputs</text>
<rect x="56" y="450" width="292" height="136" rx="8" fill="#fff7ed" stroke="#f97316" stroke-width="2"/>
<text x="82" y="486" font-family="Arial, sans-serif" font-size="22" font-weight="700" fill="#9a3412">Initial DB origin</text>
<text x="82" y="519" font-family="Arial, sans-serif" font-size="15" fill="#9a3412">Open question: a one-time seed/import</text>
<text x="82" y="544" font-family="Arial, sans-serif" font-size="15" fill="#9a3412">from Forgejo-managed files may exist,</text>
<text x="82" y="569" font-family="Arial, sans-serif" font-size="15" fill="#9a3412">but current evidence does not prove it.</text>
<rect x="412" y="214" width="292" height="386" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="3"/>
<text x="438" y="252" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#1d4ed8">Load paths</text>
<text x="438" y="286" font-family="Arial, sans-serif" font-size="16" fill="#334155">How data gets into the KB</text>
<rect x="438" y="308" width="240" height="82" rx="6" fill="#eff6ff" stroke="#93c5fd"/>
<text x="458" y="340" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#1e3a8a">1. Files / chat / sources</text>
<text x="458" y="366" font-family="Arial, sans-serif" font-size="15" fill="#1e3a8a">converted into proposals or packets</text>
<rect x="438" y="414" width="240" height="82" rx="6" fill="#eff6ff" stroke="#93c5fd"/>
<text x="458" y="446" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#1e3a8a">2. Approval boundary</text>
<text x="458" y="472" font-family="Arial, sans-serif" font-size="15" fill="#1e3a8a">proposal status, review, exact SQL</text>
<rect x="438" y="520" width="240" height="54" rx="6" fill="#dbeafe" stroke="#60a5fa"/>
<text x="458" y="553" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#1e3a8a">3. Guarded apply into Postgres</text>
<rect x="768" y="214" width="312" height="386" rx="8" fill="#ffffff" stroke="#059669" stroke-width="3"/>
<text x="794" y="252" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#047857">Canonical Postgres</text>
<text x="794" y="286" font-family="Arial, sans-serif" font-size="16" fill="#334155">teleo.public is the applied KB</text>
<rect x="794" y="308" width="260" height="164" rx="6" fill="#ecfdf5" stroke="#86efac"/>
<text x="816" y="340" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#064e3b">public.claims</text>
<text x="816" y="366" font-family="Arial, sans-serif" font-size="15" fill="#064e3b">canonical concise claim rows</text>
<text x="816" y="394" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#064e3b">public.sources</text>
<text x="816" y="420" font-family="Arial, sans-serif" font-size="15" fill="#064e3b">source excerpts, URLs, hashes</text>
<text x="816" y="448" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#064e3b">public.claim_evidence / edges</text>
<rect x="794" y="502" width="260" height="72" rx="6" fill="#d1fae5" stroke="#34d399"/>
<text x="816" y="533" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#064e3b">strategy_nodes / anchors</text>
<text x="816" y="558" font-family="Arial, sans-serif" font-size="15" fill="#064e3b">agent strategy and telos graph links</text>
<rect x="1136" y="214" width="248" height="386" rx="8" fill="#ffffff" stroke="#b45309" stroke-width="3"/>
<text x="1160" y="252" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#92400e">Staging</text>
<text x="1160" y="286" font-family="Arial, sans-serif" font-size="16" fill="#334155">kb_stage is not applied truth</text>
<rect x="1160" y="308" width="198" height="98" rx="6" fill="#fffbeb" stroke="#fbbf24"/>
<text x="1178" y="340" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#78350f">kb_proposals</text>
<text x="1178" y="366" font-family="Arial, sans-serif" font-size="15" fill="#78350f">pending / approved / applied</text>
<text x="1178" y="391" font-family="Arial, sans-serif" font-size="15" fill="#78350f">payload and review metadata</text>
<rect x="1160" y="438" width="198" height="98" rx="6" fill="#fef3c7" stroke="#fbbf24"/>
<text x="1178" y="470" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#78350f">staged_claims</text>
<text x="1178" y="496" font-family="Arial, sans-serif" font-size="15" fill="#78350f">body and raw frontmatter</text>
<text x="1178" y="521" font-family="Arial, sans-serif" font-size="15" fill="#78350f">warnings and source refs</text>
<rect x="412" y="664" width="968" height="150" rx="8" fill="#ffffff" stroke="#7c3aed" stroke-width="3"/>
<text x="438" y="703" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#5b21b6">How Leo updates itself</text>
<text x="438" y="737" font-family="Arial, sans-serif" font-size="16" fill="#334155">Knowledge and strategy updates are DB lifecycle events, not silent model self-edits.</text>
<text x="462" y="773" font-family="Arial, sans-serif" font-size="15" fill="#4c1d95">1. Leo reads public.* and kb_stage.* to answer with applied/proposed/approved distinctions.</text>
<text x="462" y="799" font-family="Arial, sans-serif" font-size="15" fill="#4c1d95">2. If a chat requests a KB change, Leo stages a proposal or emits a reviewed apply packet.</text>
<text x="462" y="825" font-family="Arial, sans-serif" font-size="15" fill="#4c1d95">3. A guarded human-approved apply writes canonical rows; Leo then re-queries and behaves from the new DB state.</text>
<path d="M348 308 H412" stroke="#334155" stroke-width="3" marker-end="url(#arrow)"/>
<path d="M704 546 H768" stroke="#334155" stroke-width="3" marker-end="url(#arrow)"/>
<path d="M1080 390 H1136" stroke="#64748b" stroke-width="3" marker-end="url(#softarrow)"/>
<path d="M1136 508 C1040 640 850 630 704 546" fill="none" stroke="#64748b" stroke-width="3" stroke-dasharray="8 8" marker-end="url(#softarrow)"/>
<path d="M924 600 V664" stroke="#334155" stroke-width="3" marker-end="url(#arrow)"/>
<path d="M1380 739 C1410 739 1410 390 1358 390" fill="none" stroke="#64748b" stroke-width="3" stroke-dasharray="7 7" marker-end="url(#softarrow)"/>
<path d="M348 518 C374 518 382 518 412 518" fill="none" stroke="#f97316" stroke-width="3" stroke-dasharray="8 8" marker-end="url(#softarrow)"/>
<text x="365" y="290" font-family="Arial, sans-serif" font-size="14" fill="#334155">deploy/code path</text>
<text x="708" y="530" font-family="Arial, sans-serif" font-size="14" fill="#334155">apply</text>
<text x="1090" y="374" font-family="Arial, sans-serif" font-size="14" fill="#64748b">read/status</text>
<text x="940" y="642" font-family="Arial, sans-serif" font-size="14" fill="#334155">answer from DB</text>
<text x="365" y="497" font-family="Arial, sans-serif" font-size="14" fill="#c2410c">unproven seed/import</text>
<rect x="56" y="654" width="292" height="160" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="2"/>
<text x="82" y="690" font-family="Arial, sans-serif" font-size="21" font-weight="700" fill="#334155">Working interpretation</text>
<text x="82" y="724" font-family="Arial, sans-serif" font-size="15" fill="#475569">Forgejo can explain code provenance</text>
<text x="82" y="749" font-family="Arial, sans-serif" font-size="15" fill="#475569">and maybe historical bootstrap.</text>
<text x="82" y="780" font-family="Arial, sans-serif" font-size="15" fill="#475569">It is not the current canonical</text>
<text x="82" y="805" font-family="Arial, sans-serif" font-size="15" fill="#475569">claim/evidence/source database.</text>
<rect x="210" y="858" width="1020" height="38" rx="8" fill="#0f172a"/>
<text x="252" y="883" font-family="Arial, sans-serif" font-size="17" fill="#ffffff">Safe agent update loop: read DB -> stage proposal -> approval/apply packet -> canonical Postgres rows -> Leo re-reads new truth.</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,83 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" role="img" aria-labelledby="title desc">
<title id="title">DB-first identity rendering, decision matrix status, and document artifact linkage</title>
<desc id="desc">Diagram showing that Leo identity is canonical in Postgres rows, rendered to SOUL.md as runtime context, decision matrix tables are designed but absent on live VPS, and document artifacts are staging files or refs until applied into canonical sources and evidence.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#334155"/>
</marker>
<marker id="dasharrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#64748b"/>
</marker>
</defs>
<rect width="1440" height="900" fill="#f8fafc"/>
<text x="54" y="64" font-family="Arial, sans-serif" font-size="34" font-weight="700" fill="#0f172a">Identity render, decision matrix, and document artifact state</text>
<text x="54" y="102" font-family="Arial, sans-serif" font-size="18" fill="#334155">Current VPS truth: Postgres is canonical; SOUL.md is a runtime render; decision matrix is designed but not shipped; document refs are staging until applied.</text>
<rect x="54" y="150" width="392" height="278" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="3"/>
<text x="82" y="190" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#1d4ed8">Canonical identity graph</text>
<text x="82" y="222" font-family="Arial, sans-serif" font-size="16" fill="#334155">Docker Postgres: teleo.public</text>
<rect x="82" y="246" width="336" height="134" rx="6" fill="#eff6ff" stroke="#93c5fd"/>
<text x="104" y="278" font-family="Arial, sans-serif" font-size="15" fill="#1e3a8a">personas, agents</text>
<text x="104" y="306" font-family="Arial, sans-serif" font-size="15" fill="#1e3a8a">shared_root, beliefs, blindspots</text>
<text x="104" y="334" font-family="Arial, sans-serif" font-size="15" fill="#1e3a8a">strategy_nodes, strategy_node_anchors</text>
<text x="104" y="362" font-family="Arial, sans-serif" font-size="15" fill="#1e3a8a">claims, sources, evidence on demand</text>
<text x="82" y="406" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#1d4ed8">Canonical change = row-level DB proof first</text>
<rect x="524" y="150" width="392" height="278" rx="8" fill="#ffffff" stroke="#7c3aed" stroke-width="3"/>
<text x="552" y="190" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#5b21b6">SOUL.md runtime render</text>
<text x="552" y="222" font-family="Arial, sans-serif" font-size="16" fill="#334155">/home/teleo/.hermes/profiles/leoclean/SOUL.md</text>
<rect x="552" y="246" width="336" height="108" rx="6" fill="#f5f3ff" stroke="#c4b5fd"/>
<text x="574" y="278" font-family="Arial, sans-serif" font-size="15" fill="#4c1d95">Rendered from DB: 0013 Leo V2 Identity Graph</text>
<text x="574" y="306" font-family="Arial, sans-serif" font-size="15" fill="#4c1d95">Runtime context, not a KB dump</text>
<text x="574" y="334" font-family="Arial, sans-serif" font-size="15" fill="#4c1d95">Direct edits are profile edits, not canonical truth</text>
<rect x="552" y="376" width="336" height="30" rx="6" fill="#fee2e2" stroke="#fca5a5"/>
<text x="574" y="397" font-family="Arial, sans-serif" font-size="14" font-weight="700" fill="#991b1b">No active renderer/timer proven in current readback</text>
<rect x="994" y="150" width="392" height="278" rx="8" fill="#ffffff" stroke="#dc2626" stroke-width="3"/>
<text x="1022" y="190" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#b91c1c">Decision matrix status</text>
<text x="1022" y="222" font-family="Arial, sans-serif" font-size="16" fill="#334155">Designed target, absent in live schema</text>
<rect x="1022" y="246" width="336" height="108" rx="6" fill="#fef2f2" stroke="#fca5a5"/>
<text x="1044" y="278" font-family="Arial, sans-serif" font-size="15" fill="#7f1d1d">Missing: kb_stage.matrix_voters</text>
<text x="1044" y="306" font-family="Arial, sans-serif" font-size="15" fill="#7f1d1d">Missing: kb_stage.proposal_votes</text>
<text x="1044" y="334" font-family="Arial, sans-serif" font-size="15" fill="#7f1d1d">Missing: kb_stage.proposal_decisions</text>
<text x="1022" y="390" font-family="Arial, sans-serif" font-size="15" fill="#334155">Current approval state lives in kb_stage.kb_proposals</text>
<rect x="54" y="520" width="392" height="250" rx="8" fill="#ffffff" stroke="#b45309" stroke-width="3"/>
<text x="82" y="560" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#92400e">Document artifacts</text>
<text x="82" y="592" font-family="Arial, sans-serif" font-size="16" fill="#334155">Files and staging rows before canonical apply</text>
<rect x="82" y="616" width="336" height="96" rx="6" fill="#fffbeb" stroke="#fbbf24"/>
<text x="104" y="648" font-family="Arial, sans-serif" font-size="15" fill="#78350f">telegram_file_refs: 19 referenced, 4 downloaded</text>
<text x="104" y="676" font-family="Arial, sans-serif" font-size="15" fill="#78350f">document_evaluations: negative decisions</text>
<text x="104" y="704" font-family="Arial, sans-serif" font-size="15" fill="#78350f">raw PDFs / extracted text live as files</text>
<text x="82" y="746" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#92400e">These are not canonical evidence yet</text>
<rect x="524" y="520" width="392" height="250" rx="8" fill="#ffffff" stroke="#059669" stroke-width="3"/>
<text x="552" y="560" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#047857">Proposal ledger</text>
<text x="552" y="592" font-family="Arial, sans-serif" font-size="16" fill="#334155">kb_stage.kb_proposals</text>
<rect x="552" y="616" width="336" height="96" rx="6" fill="#ecfdf5" stroke="#86efac"/>
<text x="574" y="648" font-family="Arial, sans-serif" font-size="15" fill="#064e3b">14 pending_review, 3 approved</text>
<text x="574" y="676" font-family="Arial, sans-serif" font-size="15" fill="#064e3b">all inspected rows have source_ref strings</text>
<text x="574" y="704" font-family="Arial, sans-serif" font-size="15" fill="#064e3b">source_ref did not directly match public.sources</text>
<text x="552" y="746" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#047857">Real DB state, but not canonical truth</text>
<rect x="994" y="520" width="392" height="250" rx="8" fill="#ffffff" stroke="#0f766e" stroke-width="3"/>
<text x="1022" y="560" font-family="Arial, sans-serif" font-size="24" font-weight="700" fill="#0f766e">Canonical evidence</text>
<text x="1022" y="592" font-family="Arial, sans-serif" font-size="16" fill="#334155">teleo.public after approved apply</text>
<rect x="1022" y="616" width="336" height="96" rx="6" fill="#f0fdfa" stroke="#5eead4"/>
<text x="1044" y="648" font-family="Arial, sans-serif" font-size="15" fill="#134e4a">public.sources</text>
<text x="1044" y="676" font-family="Arial, sans-serif" font-size="15" fill="#134e4a">public.claim_evidence</text>
<text x="1044" y="704" font-family="Arial, sans-serif" font-size="15" fill="#134e4a">public.claim_edges / claims / strategy rows</text>
<text x="1022" y="746" font-family="Arial, sans-serif" font-size="15" font-weight="700" fill="#0f766e">Canonical only after guarded apply + readback</text>
<path d="M446 288 H524" stroke="#334155" stroke-width="3" marker-end="url(#arrow)"/>
<text x="462" y="270" font-family="Arial, sans-serif" font-size="14" fill="#334155">render/sync</text>
<path d="M916 288 H994" stroke="#64748b" stroke-width="3" stroke-dasharray="8 8" marker-end="url(#dasharrow)"/>
<text x="932" y="270" font-family="Arial, sans-serif" font-size="14" fill="#64748b">should gate, but absent</text>
<path d="M446 646 H524" stroke="#334155" stroke-width="3" marker-end="url(#arrow)"/>
<text x="462" y="628" font-family="Arial, sans-serif" font-size="14" fill="#334155">proposal source_ref</text>
<path d="M916 646 H994" stroke="#334155" stroke-width="3" marker-end="url(#arrow)"/>
<text x="932" y="628" font-family="Arial, sans-serif" font-size="14" fill="#334155">approved apply</text>
<rect x="178" y="828" width="1084" height="40" rx="8" fill="#0f172a"/>
<text x="218" y="854" font-family="Arial, sans-serif" font-size="17" fill="#ffffff">Benchmark rule: Leo must name the changed layer: canonical DB rows, staging ledger, runtime SOUL render, or raw document files.</text>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View file

@ -0,0 +1,744 @@
# VPS, Hermes, and DB Mapping - 2026-07-09
Generated UTC: `2026-07-09T21:49:34Z`
This document captures the current working understanding of the Leo-on-VPS runtime, the NousResearch Hermes agent installation, the `leoclean` profile, and the Teleo knowledge database. It separates confirmed current facts from inferred behavior and open questions.
## One-Line Model
Leo on the VPS is a NousResearch Hermes gateway process running the `leoclean` profile under systemd. The profile supplies runtime identity, sessions, skills, and tools, but the canonical knowledge base is Dockerized Postgres (`teleo-pg`, database `teleo`), not `.hermes` runtime memory and not Forgejo.
## Confirmed Current Surfaces
| Surface | Current role | Current location / identifier |
| --- | --- | --- |
| VPS host | Live runtime host | `77.42.65.182` |
| Service manager | Keeps Telegram gateway alive | `/etc/systemd/system/leoclean-gateway.service` |
| Service process | Active Hermes gateway | `hermes -p leoclean gateway run` |
| Service user/cwd | Runtime Unix boundary | user `teleo`, cwd `/home/teleo` |
| Upstream Hermes checkout | NousResearch Hermes agent code | `/home/teleo/.hermes/hermes-agent` |
| Active Hermes profile | Leo runtime profile | `/home/teleo/.hermes/profiles/leoclean` |
| Teleo deployment checkout | Live deploy/source workspace | `/opt/teleo-eval/workspaces/deploy-infra` |
| Canonical KB database | Applied collective knowledge | Docker container `teleo-pg`, Postgres database `teleo` |
| Staging/proposal schema | Review ledger and staged material | `teleo.kb_stage` |
| Canonical schema | Applied claims, evidence, graph, strategy | `teleo.public` |
| Repo evidence pack | Local committed July 9 truth | `docs/reports/leo-working-state-20260709/` |
Fresh VPS readback showed `leoclean-gateway.service` active/running with `MainPID=3252143`, `NRestarts=0`, and process command:
```text
/home/teleo/.hermes/hermes-agent/venv/bin/python3 /home/teleo/.hermes/hermes-agent/venv/bin/hermes -p leoclean gateway run
```
## Service Unit
The production gateway is systemd-managed:
```ini
[Service]
Type=simple
User=teleo
WorkingDirectory=/home/teleo
ExecStart=/home/teleo/.hermes/hermes-agent/venv/bin/hermes -p leoclean gateway run
Restart=always
RestartSec=5
Environment=HOME=/home/teleo
```
Implication: `systemctl` and the process table are the liveness source of truth. A generic Hermes CLI status readback can be stale or misleading if it does not understand the systemd-managed process.
## NousResearch Hermes Layer
Confirmed upstream runtime checkout:
```text
/home/teleo/.hermes/hermes-agent
origin: https://github.com/NousResearch/hermes-agent.git
branch: main
HEAD: b2f477a30b3c05d0f383c543af98496ae8a96070
```
This is the agent runtime. It provides the gateway, profile system, skills, terminal/browser/tooling surfaces, model routing, sessions, memories, and cron-style capabilities.
The active Leo-specific profile is not the upstream repository itself. It is:
```text
/home/teleo/.hermes/profiles/leoclean
```
The profile contains:
- `config.yaml`: model, terminal, browser, memory, gateway, display, and tool configuration.
- `SOUL.md`: runtime identity context rendered from Teleo Postgres.
- `state.db`, `state.db-wal`, `state.db-shm`: local Hermes runtime state.
- `sessions/`: prior Hermes session transcripts and runtime continuity.
- `memories/`: Hermes profile memory files.
- `skills/`: installed profile skills, including `teleo-kb-bridge` and `live-leo-telegram`.
- `bin/teleo-kb`, `bin/kb_tool.py`, `bin/cloudsql_memory_tool.py`: DB-facing KB bridge tools.
- `kb_stage/proposals`, `kb_stage/evaluations`, `kb_stage/reports`, `workspace/ingested`: local profile artifacts and synchronized reports, not the canonical DB.
Redacted config readback shows:
```text
model.provider: openrouter
model.default: anthropic/claude-sonnet-4-6
model.smart_routing: true
model.smart_routing_model: google/gemini-2.5-flash
agent.max_turns: 90
agent.gateway_timeout: 1800
terminal.backend: local
memory.enabled: true
memory.search: sqlite_fts5
```
Sensitive fields such as API keys, tokens, credentials, and voice keys are intentionally omitted from this report.
## Leo's SOUL File
The active profile has:
```text
/home/teleo/.hermes/profiles/leoclean/SOUL.md
```
The file begins:
```text
# Leo - SOUL
> Rendered from the Teleo Postgres DB.
> Renderer: 0013 Leo V2 Identity Graph.
> Canonical claim/source evidence depth stays on demand via `teleo-kb`;
> this file is runtime identity context, not a KB dump.
```
Current interpretation:
- `SOUL.md` is important runtime context for Leo's identity and behavior.
- It is not itself the canonical KB.
- It is generated or rendered from canonical Postgres surfaces and then loaded as profile context.
- When the DB changes, Leo may need a render/sync step for `SOUL.md` or reports to reflect the latest canonical identity graph.
The SOUL file also includes rules that matter for DB changes:
- Runtime model is set by the active Hermes profile config and must be checked from the profile, not guessed.
- Changes to Leo's own identity, beliefs, and positions require review; Leo should not self-merge or self-edit.
- Canonical truth is distinct from runtime memory.
## Identity Compilation From The Database
The two July 9 PDFs supplied for this pass sharpen the identity model:
- `LivingIP-Master-Build-Guide.pdf` says the architectural north star is database-first agent identity. Agent identities are durable database records; runtime context is assembled from DB-backed identity, mission, memory, knowledge, conversations, tasks, decisions, artifacts, and events.
- The same guide says the Leo V2 identity graph makes Leo's soul a graph in Postgres, not a static file.
- The identity graph surfaces named in the guide are `public.personas`, `public.shared_root`, `public.strategy_nodes`, `public.strategy_node_anchors`, `public.claims(type='concept')`, beliefs, blindspots, rules, peers, and source-backed claim/evidence rows.
- It says the intended renderer walks the graph into a fixed `SOUL.md` order: Telos, Guiding Policy, Role, Lens, Voice, Strategy, Beliefs, Blindspots, Behavioral Rules, Peers.
- It also says evidence depth stays on demand through `teleo-kb`; the SOUL file is identity context, not a KB dump.
Current working model:
```text
canonical Postgres identity graph
-> renderer / sync step
-> /home/teleo/.hermes/profiles/leoclean/SOUL.md
-> Hermes/leoclean runtime prompt context
-> Leo answers, using teleo-kb for deeper claim/source/evidence retrieval
```
Therefore:
- Editing `SOUL.md` directly changes a runtime profile artifact.
- Editing `SOUL.md` directly does not prove the canonical DB changed.
- A later render from Postgres can overwrite direct `SOUL.md` edits if those edits were not first represented in canonical DB rows.
- The durable fix for identity/strategy changes is canonical DB apply first, then render/sync `SOUL.md`, then verify Leo reads the new identity.
## SOUL Render Status On VPS
The intended apply-worker loop is explicit in `scripts/apply_worker.py`:
```text
Leo proposes -> HUMAN approves -> WORKER applies -> renderer runs -> Leo reads the new self
```
The current production readback does not prove that the loop is active:
- `/etc/systemd/system/teleo-kb-apply-worker.service` exists.
- The worker is `disabled` and `inactive (dead)`.
- The unit intentionally ships inert: without `KB_APPLY_WORKER_ENABLED=1`, it is report-only.
- The unit allows `KB_APPLY_RENDER_CMD=...`, but no active render command was found in systemd readback.
- Searches under `/home/teleo` and `/opt/teleo-eval` found `SOUL.md` and references to the intended renderer, but did not find a deployed `render-soul.sh`, `render_soul.py`, or equivalent live renderer script.
This means the correct current answer to the user's hypothesis is:
```text
It is plausible for SOUL.md to lag canonical DB rows if the renderer hook is absent.
It is also plausible for a direct SOUL.md patch to appear live while not being canonical.
But it is not currently proven that SOUL.md recomposes every 24 hours.
The PDF says restart can re-render from the already-canonical DB, but live service/timer evidence does not show an active scheduled 24-hour renderer.
```
Benchmark implication:
Leo must not answer "I changed my soul" as if it changed the DB. It must name whether the changed surface is:
1. `public.*` canonical identity/strategy rows;
2. `kb_stage.*` proposal/review rows;
3. `SOUL.md` runtime render artifact;
4. `.hermes` runtime memory/session state.
## Teleo Deployment / Repo Layer
Confirmed deployment checkout on the VPS:
```text
/opt/teleo-eval/workspaces/deploy-infra
github remote: https://github.com/living-ip/teleo-infrastructure.git
origin remote: http://localhost:3000/teleo/teleo-infrastructure.git
branch: main
HEAD: 2e2dcff4d30fde04cfa6f2a6fe9da67d42f70658
```
Current interpretation:
- This workspace is the live deploy/source area used by current work.
- It has both a local Forgejo remote and a GitHub remote.
- Forgejo appears to be a code/review/deploy provenance surface for this infrastructure, not the canonical KB database.
- The live KB does not come from reading files in this workspace at answer time; Leo answers by querying Postgres through `teleo-kb` or DB tooling.
## Forgejo Relationship
Confirmed current role:
- Forgejo exists as a containerized code hosting/review surface on the VPS.
- The deployment checkout still has a Forgejo-style `origin` remote at `http://localhost:3000/teleo/teleo-infrastructure.git`.
- Repo code and historical PR pipeline references use Forgejo for code provenance and source/archive links.
Not proven:
- It is not currently proven that the canonical live KB was built directly from the Forgejo database.
- It is not currently proven that Forgejo remains an authoritative source for claims/evidence/sources.
Best current wording:
```text
Forgejo is part of the code/deploy provenance story. Docker Postgres is the canonical KB authority. A one-time historical seed/import path from repo-managed files may exist, but current evidence does not prove that the live DB is built from Forgejo DB state.
```
## Docker Postgres KB
Confirmed current DB readback:
```text
container: teleo-pg
image: postgres:16
database: teleo
schemas: public, kb_stage
```
Current table counts from read-only VPS query:
| Object | Count |
| --- | ---: |
| `public` tables | 28 |
| `kb_stage` tables | 11 |
| `public.claims` | 1837 |
| `public.sources` | 4145 |
| `public.claim_edges` | 4916 |
| `public.claim_evidence` | 4670 |
| `kb_stage.kb_proposals` | 26 |
## Canonical DB Objects
The main canonical objects are in `public`.
### `public.claims`
Columns:
```text
id uuid
type text
text text
status text
confidence numeric
tags ARRAY
created_by uuid
superseded_by uuid
created_at timestamptz
updated_at timestamptz
```
Important: current `public.claims` does not have a canonical `body` column and does not have a general `metadata` JSONB column.
### `public.sources`
Columns:
```text
id uuid
source_type text
url text
storage_path text
excerpt text
hash text
captured_at timestamptz
created_by uuid
created_at timestamptz
```
`sources.excerpt`, `url`, `storage_path`, and `hash` carry much of the evidence provenance.
### `public.claim_evidence`
Columns:
```text
claim_id uuid
source_id uuid
role USER-DEFINED
weight numeric
created_by uuid
created_at timestamptz
```
This is the claim-to-source evidence join table.
### `public.claim_edges`
Columns:
```text
id uuid
from_claim uuid
to_claim uuid
edge_type USER-DEFINED
weight numeric
created_by uuid
created_at timestamptz
```
This is the canonical claim graph.
### `public.strategy_nodes`
Columns:
```text
id uuid
agent_id uuid
node_type text
title text
body text
rank integer
status text
horizon text
measure text
source_ref text
metadata jsonb
created_at timestamptz
updated_at timestamptz
```
Strategy nodes are richer than claims. They have `body` and `metadata`, which makes them a better canonical target for agent strategy, telos, objectives, and policy nodes.
### `public.strategy_node_anchors`
Columns:
```text
id uuid
from_node_id uuid
anchor_role text
to_node_id uuid
to_shared_root_id uuid
belief_id uuid
claim_id uuid
source_id uuid
weight numeric
note text
created_at timestamptz
```
Important live constraint discovered during clone proof: one anchor row can target exactly one of `to_node_id`, `to_shared_root_id`, `belief_id`, `claim_id`, or `source_id`.
## Staging / Proposal Objects
The main staging objects are in `kb_stage`.
### `kb_stage.kb_proposals`
Columns:
```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 timestamptz
review_note text
applied_by_handle text
applied_by_agent_id uuid
applied_at timestamptz
created_at timestamptz
updated_at timestamptz
```
This is the durable proposal ledger. A row here can mean a change is proposed, approved, or applied, but the canonical proof is still whether matching `public.*` rows exist.
### `kb_stage.staged_claims`
Columns:
```text
run_id uuid
path text
legacy_id text
title text
body text
claim_type text
status text
confidence_numeric numeric
tags ARRAY
created_by_handle text
created_at_legacy timestamptz
source_ref text
sourced_from text
warnings ARRAY
raw_frontmatter jsonb
created_at timestamptz
```
This is where body-like text and raw frontmatter can exist before canonical apply. Applying a staged claim currently requires a mapping decision: body/frontmatter must be converted into canonical claim text, tags, sources, evidence, strategy-node body/metadata, or a future schema extension.
## Decision Matrix Status
The database reference PDF describes a target governance design:
```text
kb_stage.matrix_voters
kb_stage.proposal_votes
kb_stage.proposal_decisions
```
The target design is:
- voters key on `public.agents.id`;
- each proposal has one row per voter;
- vote rows retain weight snapshots, vote, and rationale;
- a proposal decision row stores the weighted tally and drives the `reviewed_by` outcome record;
- Leo cannot approve its own proposal because the proposer is excluded from the tally.
Fresh live schema readback on the VPS does not show those tables. The only matrix/proposal/document-adjacent tables currently visible are:
```text
kb_stage.canonical_mappings
kb_stage.document_evaluations
kb_stage.kb_proposals
kb_stage.pending_kb_proposals
kb_stage.telegram_file_refs
```
Therefore:
- The decision matrix is a designed target, not a shipped live approval table set on the current VPS.
- Current approval evidence lives in `kb_stage.kb_proposals` fields: `status`, `reviewed_by_*`, `reviewed_at`, `review_note`, `applied_by_*`, `applied_at`.
- A future matrix should point back to proposal rows by proposal ID and to voter identities by `agents.id`.
- Today, Leo must not claim "the decision matrix approved this" unless it first finds the matrix tables and a concrete vote/decision row.
## Pending Proposals And Document Artifacts
Current live status counts:
```text
applied add_edge 1
applied attach_evidence 1
approved attach_evidence 3
canceled attach_evidence 7
pending_review add_edge 4
pending_review attach_evidence 10
```
Current document workflow counts:
```text
kb_stage.telegram_file_refs.status=downloaded 4
kb_stage.telegram_file_refs.status=referenced 19
kb_stage.document_evaluations.decision=rejected_as_out_of_scope 1
```
Live pending/approved proposal inspection showed:
- all `approved` and `pending_review` rows have a `source_ref`;
- many `source_ref` values are Telegram labels, URLs, or local document paths;
- none of the inspected `source_ref` values directly matched a `public.sources.id`, `public.sources.url`, or `public.sources.storage_path`;
- most payloads contain UUID-like references, but some pending document/evidence proposals do not.
So the current answer is nuanced:
```text
The pending queue is not because nothing persisted. The queue is real DB state in kb_stage.kb_proposals.
It is also not simply because documents are totally unpointed; the proposals have source_ref strings.
The gap is that many proposals are only artifact/proposal-pointed, not canonical-source-pointed.
They still need review plus a mapping/apply step that creates or links public.sources, public.claim_evidence, public.claim_edges, public.claims, or strategy rows as appropriate.
```
Benchmark implication:
Leo should distinguish:
- `kb_stage.telegram_file_refs`: uploaded Telegram file metadata and download status;
- raw files under the profile cache or `kb_stage/evaluations`: document bytes/extracted text/evaluation packets;
- `kb_stage.document_evaluations`: records of evaluated docs that should not become canonical;
- `kb_stage.kb_proposals.source_ref`: a proposal-level pointer to a source, thread, file, or artifact;
- `public.sources`: canonical evidence source rows after approval/apply;
- `public.claim_evidence`: canonical attachment between a claim and a source.
The product failure is not merely "missing files." It is missing or incomplete conversion from artifact/proposal pointers into canonical source/evidence/claim/edge rows.
## The `teleo-kb` Bridge
Repo-local bridge files:
```text
hermes-agent/leoclean-bin/teleo-kb
hermes-agent/leoclean-bin/kb_tool.py
hermes-agent/leoclean-bin/cloudsql_memory_tool.py
hermes-agent/leoclean-skills/vps/teleo-kb-bridge/SKILL.md
```
VPS active profile target:
```text
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb
```
Bridge behavior:
- `teleo-kb context/search/show/evidence/edges/list-proposals/show-proposal` are the normal KB answer surface.
- In auto mode, `teleo-kb` tries the Cloud SQL bridge only when local dependencies and status checks are available; otherwise it falls back to local Docker Postgres on the VPS.
- On the VPS, local mode reaches Docker with `teleo-pg` and database `teleo`.
- The bridge can stage reviewable proposals in `kb_stage.kb_proposals`.
- The bridge is not the normal canonical write path into `public.*`.
The source code states the key rule:
```text
Canonical knowledge writes remain locked. The only write surface here is a
proposal ledger under kb_stage: agents can propose a mutation for review, but
this tool does not apply it to public.claims, public.claim_edges, or evidence.
```
## How Leo Loads Context
The live Telegram path is:
```text
Telegram group
-> leoclean-gateway.service
-> /home/teleo/.hermes/hermes-agent/venv/bin/hermes -p leoclean gateway run
-> profile config, SOUL.md, memories, sessions, skills
-> teleo-kb bridge when KB grounding is needed
-> Docker Postgres teleo.public + teleo.kb_stage
-> Telegram answer
```
For KB-specific answers, the intended path is:
```bash
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb context "<question>"
```
Then narrow follow-ups:
```bash
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb show <claim_id>
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb evidence <claim_id>
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb edges <claim_id>
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb show-proposal <proposal_id>
```
Raw `docker exec ... psql` is a fallback for operator/debug proof, not the normal Telegram answer path.
## How Leo Updates Knowledge
There are three different update classes. They must not be conflated.
### 1. Runtime continuity updates
These happen inside `.hermes`:
- session files;
- `state.db`;
- local memory files;
- profile caches.
They help Leo remember conversations and operate as a bot. They are not canonical collective truth.
### 2. Proposal/staging updates
These happen in `kb_stage`:
- `kb_stage.kb_proposals`;
- `kb_stage.staged_claims`;
- local profile artifacts under `kb_stage/proposals` and `kb_stage/reports`.
This is where Leo can safely propose a core change for review.
Normal proposal meaning:
```text
pending_review: proposed, not approved, not canonical
approved: reviewer accepted the proposed change, but public.* may still be unchanged
applied: proposal ledger says applied; must still be checked against canonical rows
```
### 3. Canonical DB updates
These happen in `public.*`:
- `public.claims`;
- `public.sources`;
- `public.claim_evidence`;
- `public.claim_edges`;
- `public.strategy_nodes`;
- `public.strategy_node_anchors`;
- related canonical strategy/belief/shared-root tables.
This is what Cory means when he expects the KB to actually change. The proof is a before/after row readback, not just chat language and not just `kb_stage.status='approved'`.
Current guarded apply approach:
1. Identify the approved proposal and its exact intended delta.
2. Normalize it into supported canonical rows.
3. Generate preflight, authorized commit, postflight, and rollback SQL.
4. Rehearse in a disposable clone or rollback transaction.
5. Apply only when authorized for production.
6. Read back exact rows and update the proposal ledger.
7. Confirm the service is stable and no disposable DB/files remain.
## How Leo Updates Itself
Current safe understanding:
- Leo does not silently rewrite its own identity or canonical beliefs from chat.
- Leo can stage a proposal about its identity, strategy, beliefs, or KB graph.
- Human/peer review is required for self-model changes.
- If approved and applied, canonical Postgres rows change first.
- `SOUL.md`, reports, and profile artifacts may then be regenerated or synchronized from the DB so future runtime context reflects the canonical change.
- The current renderer/apply-worker automation is not proven active; direct `SOUL.md` edits can drift from DB truth.
Practical loop:
```text
chat/source signal
-> Leo audits current DB state
-> Leo stages proposal or produces apply packet
-> reviewer approves/edits/rejects
-> guarded apply mutates canonical Postgres rows
-> row-level proof retained
-> SOUL/report/profile sync if the changed rows affect runtime identity
-> Leo re-queries and answers from updated DB state
```
## What Counts As Working For Cory's Complaint
The July 9 complaint was not merely "the bot is offline." The important complaint was that agents were not able to manipulate the knowledge base and the KB looked the same as last night.
Working behavior therefore means:
1. Leo remembers the Telegram conversation and can answer the current thread.
2. Leo can query canonical DB state and tell proposed vs approved vs applied apart.
3. Leo can stage reviewable proposals without mutating canonical truth prematurely.
4. For explicitly approved changes, the system can create/apply canonical rows with exact before/after proof.
5. Leo can explain which surface changed: runtime memory, local profile artifact, `kb_stage`, or `public.*`.
## Current Known Good Proofs
Retained July 9 evidence proves:
- live Telegram memory canary passed;
- open-ended Cory-style Telegram triage passed;
- live Telegram-to-`kb_stage` staged-write canary passed;
- strict canonical `add_edge` apply canary passed;
- rich proposal creation/apply packets are clone/rehearsal-proven for supported subsets;
- Helmer 7 Powers packet and ledger update are clone-proven;
- cross-surface strategy anchor packet is clone-proven;
- production application of broad rich proposal packets has not been run.
## Current Unknowns / Do Not Overclaim
- The exact historical seed path from repo/Forgejo-managed files into the current Postgres DB is not yet proven.
- The current SOUL renderer identity is visible in `SOUL.md` (`Renderer: 0013 Leo V2 Identity Graph`), but no active renderer script/timer/hook is proven deployed in this readback.
- The PDF says restart can re-render SOUL from DB, but the live system readback did not prove a 24-hour scheduled recomposition.
- The decision-matrix schema is described in the database reference PDF, but the current VPS schema does not contain `kb_stage.matrix_voters`, `kb_stage.proposal_votes`, or `kb_stage.proposal_decisions`.
- Forgejo is still present in the deploy/code topology, but it is not proven to be the live KB authority.
- GCP parity remains a separate surface; VPS truth should not be assumed to equal GCP truth until Cloud SQL readback/auth is fixed.
- Current broad production apply for old approved rich proposals remains intentionally not executed.
## Safe Operator Checks
Service liveness:
```bash
systemctl is-active leoclean-gateway.service
systemctl show leoclean-gateway.service -p MainPID -p ActiveState -p SubState -p NRestarts -p User -p WorkingDirectory -p FragmentPath --no-pager
ps -p "$(systemctl show leoclean-gateway.service -p MainPID --value)" -o pid,user,etime,cmd
```
DB liveness:
```bash
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' | grep -E 'teleo-pg|forgejo'
docker exec teleo-pg psql -U postgres -d teleo -c "select schemaname, count(*) from pg_tables where schemaname in ('public','kb_stage') group by schemaname order by schemaname;"
```
KB bridge:
```bash
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb status
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb context "what changed in the KB since last night?"
/home/teleo/.hermes/profiles/leoclean/bin/teleo-kb list-proposals
```
Profile identity:
```bash
sed -n '1,40p' /home/teleo/.hermes/profiles/leoclean/SOUL.md
sed -E 's/([A-Za-z0-9_ -]*(token|key|secret|password|credential)[A-Za-z0-9_ -]*:[[:space:]]*).*/\1<redacted>/Ig' /home/teleo/.hermes/profiles/leoclean/config.yaml | sed -n '1,120p'
```
Do not print `.env`, auth JSON contents, token files, credential files, or raw private keys.
## Mental Model For Future Agents
Use this hierarchy:
```text
1. public.* Postgres rows = canonical applied KB truth
2. kb_stage.* rows = proposed/reviewed/applied ledger and staged material
3. SOUL.md = rendered runtime identity context, not the source DB
4. .hermes state/memory/sessions = runtime continuity, not collective truth
5. teleo-infrastructure repo = code, scripts, skills, reports, apply packets
6. Forgejo = code/deploy provenance unless bootstrap evidence proves more
```
When answering "did Leo update the DB?", always name which level changed.
## Related Artifacts
- Current truth index: `docs/reports/leo-working-state-20260709/current-truth-index.md`
- DB/workspace diagram: `docs/reports/leo-working-state-20260709/leo-db-state-18-db-vs-workspace.svg`
- Claim/body/metadata diagram: `docs/reports/leo-working-state-20260709/leo-db-state-19-claims-body-metadata.svg`
- Forgejo/load/agent loop diagram: `docs/reports/leo-working-state-20260709/leo-db-state-21-forgejo-load-agent-loop.svg`
- Live Telegram proof: `docs/reports/leo-working-state-20260709/telegram-live-canary-current.md`
- Live staged-write proof: `docs/reports/leo-working-state-20260709/telegram-live-db-write-canary-20260709.md`
- Cross-surface anchor proof: `docs/reports/leo-working-state-20260709/cross-surface-resolution-current.md`
- Source PDF used for this update: `/Users/user/Downloads/Telegram Desktop/LivingIP-Master-Build-Guide.pdf`
- Source PDF used for this update: `/Users/user/Downloads/Telegram Desktop/LivingIP-KB-Database-Reference.pdf`

View file

@ -87,6 +87,12 @@ A working Leo, for Cory/m3taversal's current expectation, is a Telegram-facing a
- disposable DB `teleo_cross_surface_rehearsal_20260709` applied the mapped base packet first (`7` claims, `15` sources, `11` edges, `17` evidence rows) - disposable DB `teleo_cross_surface_rehearsal_20260709` applied the mapped base packet first (`7` claims, `15` sources, `11` edges, `17` evidence rows)
- companion packet then updated anchor `47f128a0-36c5-4b60-97d4-48c32fa48bc7` from old claim `d0000000-0000-0000-0000-000000000005` to Claim D `e6ce4e36-15d2-53bc-8b74-dda0efc095c1` at weight `0.85` - companion packet then updated anchor `47f128a0-36c5-4b60-97d4-48c32fa48bc7` from old claim `d0000000-0000-0000-0000-000000000005` to Claim D `e6ce4e36-15d2-53bc-8b74-dda0efc095c1` at weight `0.85`
- cross-surface rollback restored the old anchor, base rollback returned generated rows to `0/0/0/0`, production stayed unchanged, temp files were removed, and service remained active with `MainPID=3252143`, `NRestarts=0` - cross-surface rollback restored the old anchor, base rollback returned generated rows to `0/0/0/0`, production stayed unchanged, temp files were removed, and service remained active with `MainPID=3252143`, `NRestarts=0`
- VPS/Hermes/DB identity and document-linking map is now documented:
- the supplied July 9 master/build and database-reference PDFs confirm the intended architecture is DB-first identity: canonical Postgres identity graph rows render to `SOUL.md`, and evidence depth remains on demand through `teleo-kb`
- direct `SOUL.md` edits are profile/runtime artifact edits, not canonical DB updates; they can drift or be overwritten unless represented in canonical rows first
- `teleo-kb-apply-worker.service` exists but is disabled/inactive and ships inert/report-only unless `KB_APPLY_WORKER_ENABLED=1`; no active `KB_APPLY_RENDER_CMD` hook or scheduled 24-hour SOUL renderer was proven
- current VPS schema does not contain the designed decision-matrix tables `kb_stage.matrix_voters`, `kb_stage.proposal_votes`, or `kb_stage.proposal_decisions`; current approval evidence lives in `kb_stage.kb_proposals`
- live proposal inspection showed pending/approved rows have `source_ref` pointers, but inspected source refs did not directly match `public.sources`; document proposals are real staging rows but still need guarded mapping into canonical sources/evidence/edges
- GCP parity was rechecked and remains blocked on account authentication: - GCP parity was rechecked and remains blocked on account authentication:
- `billy@livingip.xyz` is selected for project `teleo-501523` but token refresh fails non-interactively - `billy@livingip.xyz` is selected for project `teleo-501523` but token refresh fails non-interactively
- `billyattnmarket@gmail.com` and `valentin.meylan68@gmail.com` can refresh tokens but do not have access to `teleo-501523` - `billyattnmarket@gmail.com` and `valentin.meylan68@gmail.com` can refresh tokens but do not have access to `teleo-501523`
@ -110,6 +116,8 @@ A working Leo, for Cory/m3taversal's current expectation, is a Telegram-facing a
- Helmer 7 Powers ledger proof log: `outputs/rich-proposal-creation-plan-20260709/helmer-7powers-20260709/production-apply-packet/ledger-clone-commit-delete-rollback-current.log` - Helmer 7 Powers ledger proof log: `outputs/rich-proposal-creation-plan-20260709/helmer-7powers-20260709/production-apply-packet/ledger-clone-commit-delete-rollback-current.log`
- Cross-surface strategy anchor packet: `outputs/rich-proposal-creation-plan-20260709/cross-surface-resolution-20260709/cross-surface-packet.json` - Cross-surface strategy anchor packet: `outputs/rich-proposal-creation-plan-20260709/cross-surface-resolution-20260709/cross-surface-packet.json`
- Cross-surface strategy anchor clone proof log: `outputs/rich-proposal-creation-plan-20260709/cross-surface-resolution-20260709/cross-surface-clone-rehearsal-current.log` - Cross-surface strategy anchor clone proof log: `outputs/rich-proposal-creation-plan-20260709/cross-surface-resolution-20260709/cross-surface-clone-rehearsal-current.log`
- VPS/Hermes/DB mapping: `outputs/vps-hermes-db-mapping-20260709.md`
- Identity render / decision matrix / document artifact image: `outputs/leo-db-state-22-identity-render-matrix-artifacts.svg`
- Execution plan: `outputs/working-leo-execution-plan-20260709/working-leo-execution-plan-current.md` - Execution plan: `outputs/working-leo-execution-plan-20260709/working-leo-execution-plan-current.md`
- Cory expected outcomes: `outputs/cory-expected-working-leo-outcomes-20260709.md` - Cory expected outcomes: `outputs/cory-expected-working-leo-outcomes-20260709.md`
- Current live proof image: `outputs/leo-db-state-07-live-proof.svg` - Current live proof image: `outputs/leo-db-state-07-live-proof.svg`

View file

@ -98,9 +98,48 @@
"no_overclaim" "no_overclaim"
], ],
"runtime": "disposable_clone_or_sandbox_first" "runtime": "disposable_clone_or_sandbox_first"
},
{
"dimension": "identity_rendering_from_db",
"expected_outcome": "Explain DB-first identity: public personas/strategies/beliefs/shared roots/strategy nodes/anchors feed a rendered SOUL.md runtime artifact. Direct SOUL edits are runtime/profile edits, not canonical DB truth. Approved identity changes require canonical DB apply plus an explicit render/sync; if the renderer hook is absent, SOUL can lag even when DB rows are correct.",
"id": "CS-07",
"message": "If Leo's SOUL.md is rendered from Postgres, how exactly is Leo's identity compiled from the DB? If we patch SOUL.md directly but do not update the DB, does that become canonical? Could a missing renderer or daily recomposition make Leo always miss newly approved identity changes?",
"required_signals": [
"identity_rendering",
"canonical_db",
"row_level_proof",
"no_overclaim"
],
"runtime": "disposable_clone_or_sandbox_first"
},
{
"dimension": "decision_matrix_row_provenance",
"expected_outcome": "Check the live schema before answering. A correct answer says the designed matrix should key on agents.id and proposal IDs, but current VPS schema lacks matrix_voters/proposal_votes/proposal_decisions; therefore approvals are still represented in kb_stage.kb_proposals review/apply columns, and pending rows are not proof of a matrix tally unless those tables exist.",
"id": "CS-08",
"message": "Does the decision matrix currently point back to proposal rows and reviewer votes? Is it the thing that explains why approved proposals are pending, or is it not actually shipped?",
"required_signals": [
"decision_matrix",
"canonical_db",
"fresh_readback",
"no_overclaim"
],
"runtime": "disposable_clone_or_sandbox_first"
},
{
"dimension": "document_artifact_linking",
"expected_outcome": "Separate file artifacts from DB rows. telegram_file_refs/document_evaluations/kb_proposals are real staging rows; raw PDFs/extracted text are files; public.sources is canonical evidence after approval. Pending proposals may have source_ref pointers but still lack direct public.sources linkage or an apply contract, so the fix is row-link audit plus guarded apply, not merely finding files.",
"id": "CS-09",
"message": "Are all these pending proposals because the document artifacts are not pointed at the right DB rows? What is the difference between Telegram file refs, document_evaluations, proposal source_ref, and public.sources?",
"required_signals": [
"document_artifact_linking",
"staging_or_review",
"canonical_db",
"next_action"
],
"runtime": "disposable_clone_or_sandbox_first"
} }
], ],
"generated_at_utc": "2026-07-09T21:25:05.678653+00:00", "generated_at_utc": "2026-07-09T21:55:46.252299+00:00",
"mode": "spec_only", "mode": "spec_only",
"mutates_kb": false, "mutates_kb": false,
"prompts": [ "prompts": [

View file

@ -184,6 +184,56 @@ CORY_STYLE_OUTCOME_SCENARIOS: list[dict[str, Any]] = [
), ),
"required_signals": ["state_semantics", "row_level_proof", "fresh_readback", "artifact", "no_overclaim"], "required_signals": ["state_semantics", "row_level_proof", "fresh_readback", "artifact", "no_overclaim"],
}, },
{
"id": "CS-07",
"dimension": "identity_rendering_from_db",
"runtime": "disposable_clone_or_sandbox_first",
"message": (
"If Leo's SOUL.md is rendered from Postgres, how exactly is Leo's identity compiled from the DB? "
"If we patch SOUL.md directly but do not update the DB, does that become canonical? Could a missing "
"renderer or daily recomposition make Leo always miss newly approved identity changes?"
),
"expected_outcome": (
"Explain DB-first identity: public personas/strategies/beliefs/shared roots/strategy nodes/anchors feed "
"a rendered SOUL.md runtime artifact. Direct SOUL edits are runtime/profile edits, not canonical DB truth. "
"Approved identity changes require canonical DB apply plus an explicit render/sync; if the renderer hook "
"is absent, SOUL can lag even when DB rows are correct."
),
"required_signals": ["identity_rendering", "canonical_db", "row_level_proof", "no_overclaim"],
},
{
"id": "CS-08",
"dimension": "decision_matrix_row_provenance",
"runtime": "disposable_clone_or_sandbox_first",
"message": (
"Does the decision matrix currently point back to proposal rows and reviewer votes? Is it the thing that "
"explains why approved proposals are pending, or is it not actually shipped?"
),
"expected_outcome": (
"Check the live schema before answering. A correct answer says the designed matrix should key on "
"agents.id and proposal IDs, but current VPS schema lacks matrix_voters/proposal_votes/proposal_decisions; "
"therefore approvals are still represented in kb_stage.kb_proposals review/apply columns, and pending rows "
"are not proof of a matrix tally unless those tables exist."
),
"required_signals": ["decision_matrix", "canonical_db", "fresh_readback", "no_overclaim"],
},
{
"id": "CS-09",
"dimension": "document_artifact_linking",
"runtime": "disposable_clone_or_sandbox_first",
"message": (
"Are all these pending proposals because the document artifacts are not pointed at the right DB rows? "
"What is the difference between Telegram file refs, document_evaluations, proposal source_ref, and "
"public.sources?"
),
"expected_outcome": (
"Separate file artifacts from DB rows. telegram_file_refs/document_evaluations/kb_proposals are real "
"staging rows; raw PDFs/extracted text are files; public.sources is canonical evidence after approval. "
"Pending proposals may have source_ref pointers but still lack direct public.sources linkage or an apply "
"contract, so the fix is row-link audit plus guarded apply, not merely finding files."
),
"required_signals": ["document_artifact_linking", "staging_or_review", "canonical_db", "next_action"],
},
] ]
@ -199,7 +249,11 @@ SIGNAL_PATTERNS: dict[str, list[re.Pattern[str]]] = {
], ],
"canonical_db": [ "canonical_db": [
re.compile(r"\bcanonical\b|\bpublic\.[a-z_]+|postgres|database rows?", re.I), re.compile(r"\bcanonical\b|\bpublic\.[a-z_]+|postgres|database rows?", re.I),
re.compile(r"\bclaim_edges|claim_evidence|claims|sources|reasoning_tools|strategy_nodes\b", re.I), re.compile(
r"\bpublic\.\*|claim_edges|claim_evidence|claims|sources|reasoning_tools|"
r"personas|strategies|beliefs|strategy_nodes|strategy_node_anchors\b",
re.I,
),
], ],
"row_level_proof": [ "row_level_proof": [
re.compile(r"\brow[- ]level|before/after|table[- ]level|row ids?|counts?\b", re.I), re.compile(r"\brow[- ]level|before/after|table[- ]level|row ids?|counts?\b", re.I),
@ -211,12 +265,13 @@ SIGNAL_PATTERNS: dict[str, list[re.Pattern[str]]] = {
], ],
"no_overclaim": [ "no_overclaim": [
re.compile( re.compile(
r"\bnot (?:claim|assume|overclaim)|cannot say|do not know|without proof|if .* only\b|" r"\bnot (?:claim|assume|overclaim)|cannot (?:say|claim|overclaim)|do not know|without proof|if .* only\b|"
r"\bonly ground truth\b|\bauthoritative test\b|candidate only|zero canonical effect", r"\bonly ground truth\b|\bauthoritative test\b|candidate only|zero canonical effect",
re.I, re.I,
), ),
re.compile( re.compile(
r"\buntil\b.*\b(readback|proof|query|postflight|canonical)\b|" r"\buntil\b.*\b(readback|proof|query|postflight|canonical)\b|"
r"\bwithout\b.*\b(readback|proof|query|postflight|canonical)\b|"
r"only ground truth.*canonical|canonical row.*authoritative test|readback confirms|zero canonical effect", r"only ground truth.*canonical|canonical row.*authoritative test|readback confirms|zero canonical effect",
re.I, re.I,
), ),
@ -247,6 +302,18 @@ SIGNAL_PATTERNS: dict[str, list[re.Pattern[str]]] = {
"artifact": [ "artifact": [
re.compile(r"\bartifact|receipt|proof|log|proposal|packet|row|readback\b", re.I), re.compile(r"\bartifact|receipt|proof|log|proposal|packet|row|readback\b", re.I),
], ],
"identity_rendering": [
re.compile(r"\bSOUL\.md|soul|identity graph|render(?:ed|er|ing)?|compile|compos", re.I),
re.compile(r"\bDB[- ]first|Postgres|public\.(?:personas|strategies|beliefs|strategy_nodes|strategy_node_anchors)|runtime artifact\b", re.I),
],
"decision_matrix": [
re.compile(r"\bdecision[- ]matrix|matrix_voters|proposal_votes|proposal_decisions|weighted voters?|tally\b", re.I),
re.compile(r"\bnot (?:yet )?shipped|schema lacks|tables? (?:do not|does not|don't) exist|check the schema|kb_stage\.kb_proposals\b", re.I),
],
"document_artifact_linking": [
re.compile(r"\btelegram_file_refs|document_evaluations|source_ref|public\.sources|raw PDFs?|document artifacts?\b", re.I),
re.compile(r"\bfile|rows?|staging|canonical|proposal ledger\b", re.I),
],
} }
BAD_OVERCLAIM_PATTERNS = [ BAD_OVERCLAIM_PATTERNS = [

View file

@ -20,13 +20,16 @@ def test_prompts_are_open_ended_and_not_id_led():
def test_cory_style_scenarios_are_broad_outcome_cases(): def test_cory_style_scenarios_are_broad_outcome_cases():
assert len(bench.CORY_STYLE_OUTCOME_SCENARIOS) >= 6 assert len(bench.CORY_STYLE_OUTCOME_SCENARIOS) >= 9
joined = "\n".join(prompt["message"] for prompt in bench.CORY_STYLE_OUTCOME_SCENARIOS) joined = "\n".join(prompt["message"] for prompt in bench.CORY_STYLE_OUTCOME_SCENARIOS)
assert "00957f6c-9883-4015-95a4-6b09367efb0e" not in joined assert "00957f6c-9883-4015-95a4-6b09367efb0e" not in joined
assert "c167933e-d513-4f43-9335-d5d8aeb259f2" not in joined assert "c167933e-d513-4f43-9335-d5d8aeb259f2" not in joined
assert "proposal ID" not in joined assert "proposal ID" not in joined
assert "partner demo" in joined assert "partner demo" in joined
assert "They're the same state as last night" in joined assert "They're the same state as last night" in joined
assert "SOUL.md" in joined
assert "decision matrix" in joined
assert "document artifacts" in joined
assert {prompt["runtime"] for prompt in bench.CORY_STYLE_OUTCOME_SCENARIOS} == { assert {prompt["runtime"] for prompt in bench.CORY_STYLE_OUTCOME_SCENARIOS} == {
"disposable_clone_or_sandbox_first" "disposable_clone_or_sandbox_first"
} }
@ -103,6 +106,40 @@ def test_score_results_requires_all_prompts():
assert score["pass"] is True assert score["pass"] is True
def test_scores_identity_rendering_answer_as_pass():
prompt = next(p for p in bench.CORY_STYLE_OUTCOME_SCENARIOS if p["id"] == "CS-07")
reply = (
"Leo's identity is DB-first: Postgres public.personas, public.strategies, public.beliefs, "
"public.strategy_nodes, and public.strategy_node_anchors feed a rendered SOUL.md runtime artifact. "
"A direct SOUL.md patch changes the profile/runtime artifact, not canonical DB truth. I would verify row-level "
"Postgres rows first, then run or check the renderer. Until canonical readback and render proof exist, I cannot "
"claim the identity update is canonical."
)
assert bench.score_reply(prompt, reply)["pass"] is True
def test_scores_decision_matrix_schema_answer_as_pass():
prompt = next(p for p in bench.CORY_STYLE_OUTCOME_SCENARIOS if p["id"] == "CS-08")
reply = (
"I would check the schema before claiming the decision-matrix approved anything. The designed decision-matrix "
"would use matrix_voters, proposal_votes, and proposal_decisions with weighted voters and a tally, but if those "
"tables do not exist then it is not yet shipped. Current approval state must be read from kb_stage.kb_proposals "
"review/apply columns and canonical public.* rows; I will not overclaim a matrix result without fresh readback."
)
assert bench.score_reply(prompt, reply)["pass"] is True
def test_scores_document_artifact_linking_answer_as_pass():
prompt = next(p for p in bench.CORY_STYLE_OUTCOME_SCENARIOS if p["id"] == "CS-09")
reply = (
"Telegram file refs and document_evaluations are staging rows, proposal source_ref points at the artifact or "
"source, and public.sources is the canonical evidence table after review. Raw PDFs are files; the proposal "
"ledger is rows. Pending proposals can still exist because they lack direct public.sources linkage or an apply "
"contract. The next action is a row-link audit, then a guarded staging/apply packet."
)
assert bench.score_reply(prompt, reply)["pass"] is True
def test_score_results_can_require_full_cory_style_catalog(): def test_score_results_can_require_full_cory_style_catalog():
broad_reply = ( broad_reply = (
"I will separate proposed, pending_review, approved, applied, and not applied. " "I will separate proposed, pending_review, approved, applied, and not applied. "
@ -111,6 +148,13 @@ def test_score_results_can_require_full_cory_style_catalog():
"for row-level before/after counts, row ids, preflight, postflight, and read back proof. " "for row-level before/after counts, row ids, preflight, postflight, and read back proof. "
"I will not claim the database changed until canonical readback confirms it. " "I will not claim the database changed until canonical readback confirms it. "
"The next action is to stage, review, rehearse in a clone, and apply a guarded packet only when authorized. " "The next action is to stage, review, rehearse in a clone, and apply a guarded packet only when authorized. "
"For identity, DB-first Postgres public.personas, public.strategies, public.beliefs, public.strategy_nodes, "
"and public.strategy_node_anchors feed a rendered SOUL.md runtime artifact; direct SOUL edits are not canonical "
"until row-level DB proof and render proof. For decision-matrix status, I will check the schema for "
"matrix_voters, proposal_votes, proposal_decisions, weighted voters, and tally tables; if tables do not exist, "
"the matrix is not yet shipped and kb_stage.kb_proposals remains the ledger. For document artifacts, "
"telegram_file_refs, document_evaluations, source_ref, public.sources, raw PDFs, proposal ledger rows, staging, "
"and canonical distinction determine whether pointers are real enough to apply. "
"I will check GitHub, repo, /opt/teleo-eval, VPS runtime, service working directory, canonical repo source " "I will check GitHub, repo, /opt/teleo-eval, VPS runtime, service working directory, canonical repo source "
"of truth, mirror deploy checkout, git status, rev-parse, current systemctl service state, and fresh readback " "of truth, mirror deploy checkout, git status, rev-parse, current systemctl service state, and fresh readback "
"before claiming runtime provenance. I will preserve caveats, including deferred self-positioning examples, " "before claiming runtime provenance. I will preserve caveats, including deferred self-positioning examples, "