Files
Orchestrator/bahn/project-audit/knowledge/ingest.py
ankn a5f8fb49ab Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
      Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
      Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)

Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
2026-06-30 20:39:52 +02:00

168 lines
13 KiB
Python

"""
Ingest - Liest vorhandene Analyse-Dateien in die Knowledge-DB ein.
Erstellt Nodes, Edges, Summaries und Facts.
"""
import sys
import os
sys.path.insert(0, os.path.dirname(__file__))
from db import get_db, upsert_node, add_edge, upsert_summary, add_fact, DB_PATH
def ingest_teams(db):
"""Teams und Personen aus der Analyse einlesen."""
teams = [
("team-404", "Team 404", "Portal (UI + Middleware)", {"bug_rate_90d": "33%", "bug_rate_12m": "25%", "trend": "steigend", "issues_90d": 500}),
("team-cib", "Team CIB", "Prozesse und Backend (SV, AV)", {"bug_rate_90d": "20%", "bug_rate_12m": "23%", "trend": "sinkend", "issues_90d": 342}),
("team-zero", "Team Zero", "TAF/TAP Schnittstellen, Stammdaten", {"bug_rate_90d": "15%", "bug_rate_12m": "15%", "trend": "stabil", "issues_90d": 417}),
("team-ops", "OPs Squad", "Infrastruktur (seit PI 39, ersetzt STeam)", {"bug_rate_90d": "31%", "bug_rate_12m": "27%", "trend": "sinkend", "issues_90d": 379}),
("team-devops", "DevOps", "CI/CD, Deployment, Enabler", {"bug_rate_90d": "9%", "bug_rate_12m": "7%", "trend": "stabil", "issues_90d": 289}),
]
for tid, name, summary, props in teams:
upsert_node(db, tid, "team", name, summary, props, "jira-teams-deepdive.md")
# Personen
people = [
# 404
("p-ana-cvitkovic", "Ana Cvitkovic", "team-404", "Business Engineer", {"since": "2021-08", "issues_90d": 78, "bug_rate": "niedrig", "status": "aktiv", "bewertung": "TOP"}),
("p-jasmin-keskin", "Jasmin Keskin", "team-404", "Frontend Dev", {"since": "2021-08", "issues_90d": 45, "bug_rate": "42%", "status": "aktiv"}),
("p-emmanuel-kontcheu", "Emmanuel Kontcheu Tagne", "team-404", "Frontend Dev", {"since": "2021-08", "issues_90d": 42, "bug_rate": "69%", "status": "aktiv", "bewertung": "KRITISCH"}),
("p-diego-dacosta", "Diego Da Costa Souza", "team-404", "Frontend Dev", {"since": "2021-09", "issues_90d": 41, "status": "aktiv"}),
("p-leon-hoerpel", "Leon Hoerpel", "team-404", "Dev", {"issues_90d": 35, "bug_rate": "71%", "status": "aktiv", "bewertung": "KRITISCH"}),
("p-dominik-ruecker", "Dominik Ruecker", "team-404", "Backend Dev", {"issues_90d": 31, "status": "aktiv"}),
("p-annette-halbhuber", "Annette Halbhuber", "team-404", "Lead Dev", {"since": "2021-09", "issues_90d": 26, "bug_rate": "niedrig", "status": "aktiv"}),
("p-simon-reitinger", "Simon Reitinger", "team-404", "Dev", {"since": "2025-11", "issues_90d": 15, "bug_rate": "0%", "status": "aktiv", "bewertung": "exzellent"}),
("p-marcel-hufgard", "Marcel Hufgard", "team-404", "PO", {"since": "2021-12", "issues_90d": 8, "status": "aktiv"}),
("p-luca-caracciolo", "Luca Caracciolo", "team-404", "QA", {"since": "2021-09", "issues_90d": 5, "status": "wenig aktiv"}),
# CIB
("p-bishara-jaser", "Bishara Jaser", "team-cib", "Dev", {"since": "2022-08", "issues_90d": 73, "bug_rate": "niedrig", "done_rate": "93%", "status": "aktiv", "bewertung": "TOP"}),
("p-saurav-kumar", "Saurav Kumar", "team-cib", "Dev", {"since": "2022-01", "issues_90d": 48, "bug_rate": "8%", "done_rate": "94%", "status": "aktiv", "bewertung": "TOP"}),
("p-jonas-koehler", "Jonas Koehler", "team-cib", "Dev", {"issues_90d": 34, "done_rate": "100%", "status": "aktiv", "bewertung": "exzellent"}),
("p-dong-won-han", "Dong-Won Han", "team-cib", "Dev", {"since": "2021-09", "issues_90d": 20, "status": "aktiv"}),
("p-christian-meins", "Christian Meins", "team-cib", "PO", {"since": "2021-10", "issues_90d": 9, "status": "aktiv"}),
("p-jan-lubenow", "Jan Lubenow", "team-devops", "Lead Dev", {"since": "2022-09", "issues_90d": 114, "anteil": "39%", "status": "aktiv", "bewertung": "SPOF"}),
# Zero
("p-steven-meixner", "Steven Meixner", "team-zero", "Dev", {"since": "2022-07", "issues_90d": 91, "status": "aktiv", "bewertung": "TOP/SPOF"}),
("p-bing-shi", "Bing Shi", "team-zero", "Dev", {"since": "2022-04", "issues_90d": 63, "status": "aktiv"}),
("p-frank-lemke", "Frank Lemke", "team-zero", "Dev", {"since": "2022-12", "issues_90d": 49, "status": "aktiv"}),
("p-bernd-klebl", "Bernd Klebl", "team-zero", "PO", {"since": "2021-09", "issues_90d": 16, "status": "aktiv"}),
# Uebergreifend
("p-thorsten-volland", "Thorsten Volland", "uebergreifend", "Architekt", {"status": "aktiv"}),
("p-henrik-scholl", "Henrik Scholl", "team-ops", "Dev (fest)", {"since": "2024-10", "issues_90d": 29, "status": "aktiv"}),
]
for pid, name, team, role, props in people:
props["role"] = role
upsert_node(db, pid, "person", name, f"{role} in {team}", props, "personen-rollen.md")
# Edge nur wenn Team als Node existiert
if team.startswith("team-"):
add_edge(db, pid, team, "belongs_to", {"role": role}, "personen-rollen.md")
def ingest_systems(db):
"""Systeme/Komponenten einlesen."""
systems = [
("sys-portal-ui", "Portal UI", "Angular Frontend fuer EVU-Kunden und Kundenbetreuer", {"tech": "Angular, TypeScript", "team": "team-404"}),
("sys-portal-mw", "Portal Middleware", "Backend fuer Portal, Validierung, Autorisierung", {"tech": "Spring Boot", "team": "team-404"}),
("sys-sv", "Steuerung Vertrieb", "Camunda 8 Workflow-Engine, orchestriert Bestellprozess", {"tech": "Camunda 8, Spring Boot", "team": "team-cib", "smells": 2214}),
("sys-av", "Auftrags-Verwaltung", "Speicherung und Bereitstellung von Auftragsdaten", {"tech": "Spring Boot", "team": "team-cib"}),
("sys-ci", "Common Interface", "TAF/TAP TSI Schnittstelle (SOAP)", {"tech": "Spring Boot, SOAP", "team": "team-zero"}),
("sys-stb", "Stammdaten-Bereitstellung", "Import IM-Stammdaten", {"tech": "Spring Boot", "team": "team-zero"}),
("sys-vdv", "Vertragsdaten-Verteiler", "Kafka-basierte Weiterleitung", {"tech": "Spring Boot, Kafka", "team": "team-zero"}),
("sys-ifp-connector", "IFP-Connector", "Kafka-Adapter zu TPN/IFP", {"tech": "Spring Boot, Kafka", "team": "team-zero"}),
]
for sid, name, summary, props in systems:
upsert_node(db, sid, "system", name, summary, props, "runbook")
if "team" in props:
add_edge(db, props["team"], sid, "owns", source="runbook")
def ingest_summaries(db):
"""Zusammenfassungen der Analyse-Dokumente."""
docs = [
("sum-tech-deepdive", "Technischer Deep Dive",
"23 pom.xml analysiert. Spring Boot 3.5.13 (EOL Juni 2026), Upgrade auf 4.0.5 laeuft aktiv. Java 21 in Services, Parent POM noch 17. SV hat eigenen Parent POM. Camunda 8.8.22 aktuell. tadef-connector 0% Coverage (28K Lines).",
"project-audit/analysis/iteration-02-technical-deepdive.md", "technik,spring-boot,dependencies,sonarqube"),
("sum-team-workflow", "Team und Workflow Analyse",
"6 Teams: Zero, 404, CIB, OPs, BSSUPPORT, FbF. STeam aufgeloest in PI 39, ersetzt durch OPs Squad (2 fest + rotierend). 17+ Umgebungen. 5 Engpaesse. 9 Reorganisations-Empfehlungen. Jan Lubenow = 39% DevOps (SPOF).",
"project-audit/analysis/iteration-03-team-workflow.md", "teams,organisation,spof,ops"),
("sum-velocity", "Velocity 12 Monate",
"4875 Issues, ~400/Monat. Go-Live-Effekt: Bug-Rate 10% -> 29% (Feb Peak) -> 20% (Normalisierung). Team 404 Bug-Rate steigt (33% Maerz, KRITISCH). CIB sinkt (36% -> 9%, Erfolg). Zero stabil (15%).",
"project-audit/analysis/velocity-12m-analyse.md", "velocity,bugs,go-live,teams"),
("sum-jira-teams", "Jira Team-Boards",
"1949 Issues (90d). 404: 500 Issues/165 Bugs (33%). CIB: 342/67 (20%). Zero: 417/64 (15%). OPs: 379/116 (31%). DevOps: 289/27 (9%). Top-Contributor: Ana (404, 78), Bishara (CIB, 73), Steven (Zero, 64), Jan (DevOps, 114).",
"project-audit/analysis/jira-teams-deepdive.md", "jira,teams,bugs,personen"),
("sum-sonarqube", "SonarQube Code-Qualitaet",
"74 Projekte. Team Zero = beste Qualitaet (4.2 Smells/1K, 91.8% Coverage). CIB hoechste Schuld (23 Smells/1K, SV mit 2214 Smells). tadef-connector 0% Coverage. Top-Smells: S1192 (1078 String-Duplikate, 976 in SV), S3776 (55 Cognitive Complexity).",
"project-audit/data/sonarqube/", "sonarqube,qualitaet,smells,coverage"),
("sum-ttt-programm", "TTT-Programm und NEP2",
"Go-Live Dez 2025, Go/No-Go Sep 2025 positiv. pathOS seit ~4 Monaten produktiv. Verlaengerte Hypercare. NEP2 stabil (identisch zu NEP1, andere Priorisierung). 8 Programmrisiken (TTTSOL-42 bis -52). Abrechnung strategisches Thema.",
"project-audit/analysis/ttsi-programm-analyse.md", "ttt,go-live,nep2,hypercare,risiken"),
("sum-roadmap-po", "Produkt-Roadmap (PO-Input)",
"18 neue Themen nicht in Roadmap. Top: Vorpruefung Portal, Aenderungswesen, RouteUpdate, Expertenmodus, Fehlermeldungen-Konzept. BO: 6 strategische Fragen (Support, Monitoring, Axt schaerfen, Enablement, Regeln, Fachlichkeits-Loop).",
"project-audit/analysis/po-roadmap-input.md", "roadmap,po,features,bo"),
("sum-personal", "Personal- und Bug-Analyse",
"Tenure korreliert NICHT mit Bug-Rate bei 404 (Emmanuel 56M/69% Bugs vs Simon 5M/0%). CIB+Zero: Erfahrung+Prozesse wirken. SPOFs: Jan Lubenow (39% DevOps), Steven Meixner (91 Issues). Top 5 Massnahmen: Jan entlasten, Portal-Qualitaet, Steven entlasten, Inaktive klaeren, CIB Best Practices teilen.",
"project-audit/analysis/personal-bug-analyse.md", "personal,bugs,spof,tenure,risiko"),
]
for sid, topic, content, path, tags in docs:
upsert_summary(db, sid, topic, content, path, tags)
def ingest_facts(db):
"""Wichtige Einzelfakten."""
facts = [
("pathOS", "go-live", "Dezember 2025", "confirmed", "ttsi-programm-analyse.md", "2025-12"),
("pathOS", "go-no-go", "September 2025, positiv", "confirmed", "ttsi-programm-analyse.md", "2025-09"),
("pathOS", "status", "Produktiv seit ~5 Monaten, verlaengerte Hypercare + NEP2", "confirmed", None, "2026-04"),
("Spring Boot", "version", "3.5.13 (EOL Juni 2026)", "confirmed", "iteration-02-technical-deepdive.md", "2026-04"),
("Spring Boot", "upgrade-status", "4.0.5 Upgrade laeuft aktiv: Portal fertig, CI/SV/AV in Arbeit", "confirmed", "BO-Input", "2026-04"),
("Camunda", "version", "8.8.22", "confirmed", "iteration-02-technical-deepdive.md", "2026-04"),
("Team 404", "bug-rate-90d", "33% (steigend, KRITISCH)", "confirmed", "velocity-12m-analyse.md", "2026-04"),
("Team CIB", "bug-rate-90d", "20% (sinkend von 36%, Erfolgsgeschichte)", "confirmed", "velocity-12m-analyse.md", "2026-04"),
("Team Zero", "bug-rate-90d", "15% (stabil, beste Qualitaet)", "confirmed", "velocity-12m-analyse.md", "2026-04"),
("Jan Lubenow", "spof-risiko", "39% aller DevOps-Issues, kritischster SPOF", "confirmed", "jira-teams-deepdive.md", "2026-04"),
("Steven Meixner", "spof-risiko", "91 Issues (Zero+OPs), Allrounder aber ueberlastet", "confirmed", "jira-teams-deepdive.md", "2026-04"),
("STeam", "status", "Aufgeloest in PI 39, ersetzt durch OPs Squad", "confirmed", "BO-Input", "2025"),
("NEP2", "status", "Stabil, kein Risiko, identisch zu NEP1", "confirmed", "ttsi-programm-analyse.md", "2026-04"),
("SV (Steuerung Vertrieb)", "smells", "2214 SonarQube Smells (hoechste im Programm)", "confirmed", "sonarqube-export", "2026-04"),
("tadef-connector", "coverage", "0% Test-Coverage bei 28K Lines of Code", "confirmed", "sonarqube-export", "2026-04"),
("Gesamtkapazitaet", "throughput", "~400 Issues/Monat ueber alle Teams", "confirmed", "velocity-12m-analyse.md", "2026-04"),
("GitLab", "projekte-gesamt", "167 (109 aktiv, 32 archiviert)", "confirmed", "gitlab-inventory", "2026-04"),
("Confluence", "seiten-analysiert", "143+ im pathOS Space", "confirmed", "confluence-export", "2026-04"),
]
for subject, predicate, value, confidence, source, date in facts:
add_fact(db, subject, predicate, value, confidence, source, date)
def main():
print("=== Knowledge Graph Ingest ===")
db = get_db()
print(" DB initialisiert:", DB_PATH)
print(" Teams und Personen...")
ingest_teams(db)
print(" Systeme...")
ingest_systems(db)
print(" Zusammenfassungen...")
ingest_summaries(db)
print(" Fakten...")
ingest_facts(db)
db.commit()
# Stats
nodes = db.execute("SELECT COUNT(*) as c FROM nodes").fetchone()["c"]
edges = db.execute("SELECT COUNT(*) as c FROM edges").fetchone()["c"]
summaries = db.execute("SELECT COUNT(*) as c FROM summaries").fetchone()["c"]
facts = db.execute("SELECT COUNT(*) as c FROM facts").fetchone()["c"]
print(f"\n Ergebnis: {nodes} Nodes, {edges} Edges, {summaries} Summaries, {facts} Facts")
print(" FERTIG!")
db.close()
if __name__ == "__main__":
main()