126 plikow (md, yaml, sh, py) odwolywalo sie do sciezek sprzed migracji.
15 markdown-linkow [..](..) -> policzona sciezka WZGLEDNA wobec pliku
odsylajacego (wczesniej czesc z nich byla repo-root-relative i nie
rozwiazywala sie z katalogu, w ktorym lezala)
200 odwolan tekstowych (backticki, proza, yaml, importy w kodzie)
-> nowa sciezka repo-root-relative, zgodnie z konwencja repo
5 linkow rodzenstwa (gole nazwy plikow, np. "](DEPLOY.md)") — dzialaly
tylko w starym katalogu; przeliczone recznie
Objete m.in.: CLAUDE.md (scripts/onboard/README.md -> kb/runbooks/
node-onboarding-tool.md, docs/backlog.md -> kb/phases/backlog.md),
README.md, .claude/skills/, 20 session logow, kod jobow.
Ostatnie 5 odwolan pochodzi z tresci wciagnietej rebasem z origin/master
(session log 2026-07-31, override node-agenta na SOLARII, dwie pozycje
backlogu) — wskazywaly na docs/incidents/, docs/kb/modules/ i
services/narty27/README.md sprzed migracji.
Dodany wzajemny link miedzy kb/services/control-plane.md (stub kodu)
a kb/subsystems/control-plane.md (opis, deprecated) — dwa dokumenty o tym
samym systemie, latwe do pomylenia.
Weryfikacja na 790 plikach: 0 odwolan do starych sciezek,
0 martwych linkow markdown. Lint OKF: 190/190 plikow ZGODNE.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.6 KiB
| okf | type | visibility | status | updated | links |
|---|---|---|---|---|---|
| 0.1 | session-log | private | active | 2026-06-17 |
Sesja 2026-06-17 — KB foundations (etap 1 maili)
Cel
Zbudowanie fundamentu filaru maili: pgvector spine na SOLARIA, zamrożona koperta, pakiet domeny kb-mail, testy. Bez live ingestu, bez bulk Gmaila, bez indexera — sam fundament pod kolejne etapy.
Architektura KB — ustalona w tej sesji (docs)
4 warstwy × 4 filary + rdzeń
[ 4. Agent interdyscyplinarny ] NL query + analityka (LLM) ← wspólne
[ 3. Join + Enrich ] entity resolution · graf · OwnTracks ← wspólne
[ 2. Preprocess + Index ] → pgvector / → SQL ← per filar
[ 1. Ingest ] Maile Dokumenty Zdjęcia Transakcje ← per filar
OwnTracks = klucz czasoprzestrzenny w warstwie 3, nie osobny filar (ciągła funkcja czas→miejsce).
Decyzje zamknięte
- Spine: Postgres + pgvector (nie Qdrant) na SOLARIA
- Embed: bge-m3 (multilingual, długi kontekst, lepszy pod polski)
- Maile: dwa żywe źródła — Fastmail (JMAP, primary) + Gmail (IMAP; konto zostaje jako śmieciowe/2FA)
- Bulk historyczny Gmail (jednorazowy) — etap 2
- Reguła: archiwizuj wszystko, indeksuj selektywnie (filtr na wejściu do indeksu, nie archiwum)
- Załączniki: II tura (MVP = czysty tekst + nagłówki)
- Warstwa 3 startuje jako cienki graf encji; federacja przy zapytaniu — później
- Dokumenty: Nextcloud (drive, WebDAV) + Paperless-ngx (skany/faktury/OCR)
- Koperta: zamrożona addytywna —
id / source / ts(UTC) / geo / raw_ref / entities[]
Decyzje otwarte
- Transakcje (filar #4): OPEN ISSUE — agregator PSD2 (GoCardless / Tink) dla mBank + Revolut, ale zgoda SCA wygasa co 90 dni → brak pełnego bezobsługowego sync; fallback: CSV/MT940. Do decyzji przy starcie filaru #4.
Etap 1 — ZBUDOWANY
services/kb-postgres
- Obraz:
pgvector/pgvector:pg16 - SOLARIA, port 5433 (5432 zarezerwowany na potencjalny lokalny postgres)
- Named volume:
kb_postgres_data - Init SQL (
init/001_envelope.sql):CREATE EXTENSION vector+ tabelaenvelope - Per-host override:
hosts/solaria/runtime/kb-postgres/docker-compose.override.yml—mem_limit: 4g inventory/topology.yaml+hosts/solaria/services.yaml— wpisy dodane
Zamrożona koperta (001_envelope.sql + Envelope dataclass)
CREATE TABLE envelope (
id TEXT PRIMARY KEY,
source TEXT NOT NULL, -- fastmail | gmail | ...
ts TIMESTAMPTZ NOT NULL,
geo JSONB, -- null dla maili; warstwa 3 uzupełnia
raw_ref TEXT NOT NULL, -- ścieżka do .eml w archiwum
entities JSONB NOT NULL DEFAULT '[]'
);
Envelope dataclass waliduje ts.tzinfo is not None w __post_init__.
packages/kb-mail — nowa konwencja shared lib
Lokalizacja: packages/<lib>/ (nie services/) — biblioteki reużywalne przez joby.
Instalacja w Dockerfile: COPY packages/kb-mail/ /packages/kb-mail/ && pip install /packages/kb-mail/.
| Moduł | Co robi |
|---|---|
envelope.py |
@dataclass Envelope, walidacja tz-aware ts |
db.py |
insert_envelope (ON CONFLICT DO NOTHING) + get_envelope (asyncpg) |
archive.py |
save_eml — append-only, asyncio.to_thread na write, FileExistsError na duplikat |
structlog JSON w każdym module (structlog.get_logger(__name__)); konfiguracja po stronie konsumenta (biblioteka nie konfiguruje structlog).
Testy
- 15 unit testów (nie-integration): model, archiwum, sanity SQL — wszystkie zielone bez DB
- 5 integration testów (
@pytest.mark.integration): round-trip DB, duplikat, geo, entities — wymagająKB_TEST_DSN conftest.py: fixturedb_conn= asyncpg connection + BEGIN/ROLLBACK na każdy test
Poprawki spójności (code-review sesji)
- README deploy: pierwotna wersja miała
docker compose --env-file /opt/homelab/config/…— pomijała override file i miała złą ścieżkę. Naprawiono: README dokumentuje trzy ścieżki (standardowa przezdeploy.sh solaria, first-time setup.envobok compose file, manual z dwoma-f), zgodnie zdeploy-node.shL65–72. - .gitignore: reguła
*.env(L3) już łapieservices/kb-postgres/.env— potwierdzonogit check-ignore. Nic nie dodano.
Higiena git
- Cała praca w worktree
task/kb-foundations— master czysty przez cały czas - 2 commity na branchu po zakończeniu sesji
Commits
31c64d5 feat(kb-mail): fundament — pgvector spine, koperta, archiwum, pakiet domeny
<docs-commit> docs(kb): etap 1 fundament done + session log 2026-06-17
Files changed (etap 1)
services/kb-postgres/docker-compose.yml
services/kb-postgres/service.yaml
services/kb-postgres/env.example
services/kb-postgres/healthcheck.sh
services/kb-postgres/init/001_envelope.sql
kb/services/kb-postgres.md
hosts/solaria/runtime/kb-postgres/docker-compose.override.yml
hosts/solaria/services.yaml
inventory/topology.yaml
packages/kb-mail/pyproject.toml
packages/kb-mail/src/kb_mail/{__init__,envelope,db,archive}.py
packages/kb-mail/tests/{conftest,test_envelope,test_archive,test_db,test_migration}.py
kb/subsystems/kb-overview.md (etap 1 done, konwencja packages/)
CLAUDE.md (sekcja Shared Python Libraries)
docs/sessions/2026-06-17-kb-foundations.md
Następny krok
Etap 2: jednorazowy bulk importer Gmail — mbox/Takeout → archiwum.
Wejście: plik .mbox lub katalog Maildir z eksportu Google Takeout.
Wyjście: .eml w archiwum + wiersze envelope w DB.
Jako one-shot job (nie serwis), reużywa packages/kb-mail.