Files
km/docs/ingest-gitea.md
T
eltonandClaude Fable 5.1 4986ef0575 Baue den Index als SQLite mit FTS5 und sqlite-vec, dazu die Suche
Entscheidung Andreas 2026-09-04 (spine/core#8): kein Datenbankdienst. Der
Index ist eine abgeleitete Sicht auf die Markdown-Ablage in einer Datei im
Volume, jederzeit neu baubar. image/km/index.py zerlegt die Dateien in
Chunks (Chunking aus info/ai/scripts/index_docs.py übernommen), hält
Volltext in FTS5 und Vektoren aus bge-m3 in sqlite-vec, inkrementell über
SHA-256 je Datei. image/km/search.py sucht Volltext führend, Vektor
ergänzend, mit Filtern vor dem Ranking (0 Treffer statt gesperrt).

Ingest: Kommentare bei der Erstbefüllung repo-weit statt je Vorgang —
die erste Fassung hing bei live/live nach 371 Vorgängen; jetzt 2175 in zwei
Minuten. Gemessen: Volltext über 61.000 Chunks in 3 s, Vektoren 0,31 s je
Chunk auf der CPU-Box. Kein Bytecode mehr im Repo.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 18:04:35 +02:00

5.1 KiB

Gitea-Ingest — Tickets und Kommentare in die Ablage

Umsetzung von spine/core#13. Code: image/km/ingest_gitea.py. Stand: Prototyp, läuft am Baum, noch nicht als Dienst.

Was er tut

Er liest Issues, Pull Requests und deren Kommentare aus einer Gitea-Instanz und legt je Vorgang eine Markdown-Datei in der km-Ablage ab:

<ablage>/<namespace>/vorgaenge/<owner>/<repo>/<nummer>.md

Die Datei ist das, was km über den Vorgang weiß — lesbar ohne den Dienst, in SilverBullet blätterbar, für die Suche indexierbar. Sie besteht aus:

Teil Inhalt
Frontmatter Forge, Namespace, Klassifikation, Repo, Nummer, Art (issue/pull), Titel, Zustand, Autor, Beteiligte, Labels, Milestone, Zuweisung, erstellt/aktualisiert/geschlossen, URL, Verweise
Stand-Block der tldr-Block aus dem Ticketkopf, wenn vorhanden, vor dem Body
Body der Ticket-Text
Kommentare alle, in Reihenfolge, mit Autor und Zeit; „(bearbeitet)" wenn nachträglich geändert

Verweise sind das, was über eine Volltextsuche hinausgeht: jedes owner/repo#N, jedes nackte #N (im eigenen Repo) und jede Ticket-URL in Body oder Kommentaren wird zu einem Eintrag verweise: im Frontmatter — also zu einer Kante, nicht einer Zeichenkette. Aufzählungen wie 42i/intern#193 / #198 werden dem qualifizierten Repo zugeordnet, nicht dem eigenen.

Wie er läuft

# Erstbefüllung oder Abgleich einzelner Repos
AGENT_PERSONA=elton image/km/ingest_gitea.py --ablage /srv/km/ablage \
  --repo spine/core --repo 42i/intern --repo live/live

# alle Repos einer Organisation
image/km/ingest_gitea.py --ablage /srv/km/ablage --org spine --org hive

# zweite Forge, eigener Namespace
KM_GITEA_URL=https://git.home KM_NAMESPACE=familie KM_CLASSIFICATION=home \
  image/km/ingest_gitea.py --ablage /srv/km/ablage --org ahmann
  • Inkrementell. Je Repo merkt er sich in einer Standdatei (<ablage>/../km-ingest-state.json, außerhalb der Ablage) den Zeitpunkt des letzten vollständigen Durchlaufs und fragt Gitea nur nach seither geänderten Vorgängen (since, Gitea filtert nach updated). Ein geänderter Vorgang wird komplett neu geschrieben — ein umgeschriebener Body ist eine Änderung des Stands, kein Anhang.
  • Idempotent. Dieselbe Eingabe ergibt dieselbe Datei; unveränderte Dateien werden nicht angefasst. Damit ist --full zugleich der Abgleich aus spine/core#17: wiederholbar, mit belegbarem „zuletzt geprüft um".
  • Abbruch ohne Lücke. Der Stand wird erst nach vollständigem Durchlauf eines Repos gesetzt. Bricht ein Lauf ab, holt der nächste dieselben Vorgänge noch einmal — wiederholen ist billig, Lücken sind es nicht.
  • Zugang kommt aus OpenBao (secret get <persona> git username|password), wie beim Gitea-Helfer der Agenten. Nichts davon erscheint in Ausgabe, Kommandozeile oder Datei. Der Ingest schreibt nichts nach Gitea (die Festlegung aus #13: Vorgänge bleiben in der Forge, km liest).

Gemessen am 2026-09-04

Repo Vorgänge Dauer Anmerkung
spine/core 20 6 s Erstbefüllung
spine/core 0 gesehen 0,3 s inkrementell, nichts geändert
42i/intern 1165 ~3 min Erstbefüllung, noch ein API-Aufruf je Vorgang für die Kommentare
live/live 2175 ~2 min Erstbefüllung mit repo-weitem Kommentar-Endpunkt (ein Aufruf je 50 Kommentare)
elf Repos (live, intern, spine/, hive/) 2241 94 s ein Lauf

Die erste Fassung holte die Kommentare je Vorgang und blieb bei live/live nach 371 Vorgängen an einer offenen Verbindung hängen. Seitdem gilt: bei der Erstbefüllung kommen die Kommentare repo-weit (/issues/comments, älteste zuerst), inkrementell je geändertem Vorgang. Dazu ein Verbindungs-Timeout und Fortschritt je 100 Vorgänge auf stderr.

Was noch fehlt (Reihenfolge)

  1. Bus-Anschluss. Heute ist der Ingest ein Aufruf; er soll von wake.km geweckt werden (spine/core#12: Gitea-Webhook → HTTP→Bus-Adapter → Bus → km) und dann den inkrementellen Lauf machen. Der periodische Abgleich bleibt daneben Pflicht.
  2. Suche über die Ablage. Gebaut: SQLite mit FTS5 und sqlite-vec, siehe index-suche.md.
  3. Verknüpfung mit Doku und Memory. Die verweise: sind erst Kanten zwischen Vorgängen. Kanten zu Doku-Seiten (ein Ticket, das eine Seite betrifft) und die Konsistenzprüfung gegen abgelegte Festlegungen kommen mit der prüfenden Schreibfunktion.
  4. Commit und Push der Ablage nach dem Lauf, wie wissens_mcp/repo.py (Serialisierung, Rebase bei abgelehntem Push). Beim Prototyp am Baum läuft das noch von Hand.

Offen aus #13, hier vorgeschlagen

  • Historientiefe: Erstbefüllung vollständig, weil sie ohnehin nur einmal anfällt und drei Minuten je tausend Vorgänge kostet. Ein Stichtag spart nichts Nennenswertes.
  • Zwei Forges: getrennt über --namespace und --classification; git.homefamilie/home, git.42i.org42i/lan. Mit einem km je Instanz (hive/core#61) liegt die Familien-Forge ohnehin in einem anderen Dienst.