Erster Baustein von spine/core#13: image/km/ingest_gitea.py liest Issues, Pull Requests und Kommentare je Repo oder Organisation und schreibt je Vorgang eine Markdown-Datei mit Frontmatter (Zustand, Labels, Milestone, Beteiligte, Zeitstempel, Verweise auf andere Vorgänge als Kanten) unter <ablage>/<namespace>/vorgaenge/<owner>/<repo>/<nummer>.md. Inkrementell über since je Repo, idempotent, Stand erst nach vollständigem Durchlauf. Zugang aus OpenBao wie beim Gitea-Helfer, nie in der Ausgabe. Schreibt nichts nach Gitea zurück. Gemessen: 1165 Vorgänge in drei Minuten. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4.9 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 nachupdated). 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
--fullzugleich 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, ein API-Aufruf je Vorgang für die Kommentare |
Die Erstbefüllung kostet einen Aufruf je Vorgang mit Kommentaren; das ist die Last auf der Forge, von der #13 spricht. Sie fällt einmal an. Danach kostet ein Lauf einen Aufruf je Repo plus einen je geändertem Vorgang.
Was noch fehlt (Reihenfolge)
- Bus-Anschluss. Heute ist der Ingest ein Aufruf; er soll von
wake.kmgeweckt werden (spine/core#12: Gitea-Webhook → HTTP→Bus-Adapter → Bus → km) und dann den inkrementellen Lauf machen. Der periodische Abgleich bleibt daneben Pflicht. - Suche über die Ablage. Volltext führend, Vektor ergänzend (spine/core#1).
Der bestehende Indexer
info/ai/scripts/index_docs.pychunkt Markdown mit Frontmatter — die Vorgangsdateien sind dafür gebaut. Welche Datenbank(en) dahinter stehen, ist noch nicht entschieden (Stand 04.09.). - 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. - 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
--namespaceund--classification;git.home→familie/home,git.42i.org→42i/lan. Mit einem km je Instanz (hive/core#61) liegt die Familien-Forge ohnehin in einem anderen Dienst.