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>
103 lines
4.9 KiB
Markdown
103 lines
4.9 KiB
Markdown
# Gitea-Ingest — Tickets und Kommentare in die Ablage
|
|
|
|
Umsetzung von [spine/core#13](https://git.42i.org/spine/core/issues/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
|
|
|
|
```bash
|
|
# 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, 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)
|
|
|
|
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.** Volltext führend, Vektor ergänzend (spine/core#1).
|
|
Der bestehende Indexer `info/ai/scripts/index_docs.py` chunkt Markdown mit
|
|
Frontmatter — die Vorgangsdateien sind dafür gebaut. Welche Datenbank(en)
|
|
dahinter stehen, ist noch nicht entschieden (Stand 04.09.).
|
|
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.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.
|