flowchart TD
data["PDAI-1: Collections und _register"]
lemma["ai-lemma-index: Indexierung, Register der Einzeldinge"]
fr["Famulus-Referenz (DuckLake): fr:-Adressen, Zitat, Herkunft; MCP famulus-reference 5135 (mac-studio)"]
harvest["Ernte: /oai, /jsonld, /iiif, /peers"]
proof["famulus-proof: Beweis, Evidenz, FQL, Entfaltung, Evidenzraum"]
nb["famulus-notebook: Oberflaeche, Server 5118"]
lek["ai-lektorat: Lektor 5114"]
orch["ai-agent-orchestrator: Partituren, famulus-Ops"]
query["ai-query: Anfrageaufloesung 5113"]
lemma --> data
fr --> data
fr --> lemma
harvest --> fr
proof --> fr
proof --> lemma
nb --> proof
lek --> proof
orch --> proof
query --> lemma
Landkarte der Workspaces
Was Famulus Proof und Famulus Notebook brauchen, und wo jede Aufgabe genau einmal gelöst ist
Indexierung und die Identität der Einzeldinge gehören nach ai-lemma-index, jede Begründung nach famulus-proof, und famulus-notebook ist nur die Oberfläche; was heute an zwei oder mehr Stellen gelöst ist, bekommt genau einen Zielort.
Die Schichten
Jede Schicht importiert nur nach unten. Ein Paket, das eine Aufgabe einer unteren Schicht selbst noch einmal löst, ist eine Doublette.
Die Famulus-Referenz liegt zwischen den Collections und famulus-proof. Sie überführt jede Collection und die Kopien ihrer Sidecars in ein Sammlungsschema eines DuckLake (pdai-collections/_lake/famulus.ducklake) und gibt jedem Item eine fr:-Adresse. Geschrieben wird der DuckLake nur auf mac-studio; famulus-proof liest ihn schreibgeschützt (Lake-Modus, FAMULUS_LAKE=1). Der MCP-Server famulus-reference (Port 5135, mac-studio) bietet die Werkzeuge fr_* und die Ernte-Endpunkte:
| Endpunkt | liefert |
|---|---|
GET\|POST /oai |
OAI-PMH 2.0 (oai_dc, oai_datacite); ein Set je Collection |
GET /jsonld/<coll> |
schema.org Dataset und DCAT |
GET /iiif/<coll>/<doc>/manifest.json |
IIIF Presentation 3, Canvases auf dem Bilddienst der Institution |
GET /peers |
Register der föderierten Famulus-Referenzen |
GET /health |
Zustand des Servers |
Einzelheiten stehen unter Famulus-Referenz.
Workspaces
| Workspace | Paket | Aufgabe |
|---|---|---|
pdai/famulus-reference |
famulus_reference |
DuckLake der Collections, Schema famulus-reference/1, fr:-Adressen, Zitate, MCP-Server 5135, Ernte (OAI-PMH, JSON-LD, IIIF), Wartung |
pdai/index/ai-lemma-index |
ai_lemma_index |
Stanza-Korpus, Lemmaindex, NER, Gazetteer, Vektoren, LWgrammar-Speicher, FQL-Sidecar, Register der Einzeldinge |
development/famulus-proof |
famulus_proof |
Grundresolution, Evidenzbasis, FQL-Engine und Argument, Zielentfaltung, Evidenzraum |
development/famulus-notebook |
famulus_notebook |
Notebook-Server, Viewer, Quarto-Site, Runner |
development/ai-agent-orchestrator |
orchestrator |
Partituren, Conductor, Laufzeit famulus: |
publication/ai-lektorat |
ai_lektorat |
Lektor, satzweise sachliche Validität |
pdai/agents/ai-query |
ai_query |
Anfrageauflösung, Grounding, Register-Ernte |
LWgrammar |
lwgrammar_reference |
Terminologie und Regeln (MCP) |
scholarly/projects/ai-karman-manager |
Skripte | Kármán-Briefdatenbank aus den Brief-XML |
pdai/collections/<name>/scripts |
Skripte | Collection-Builder (Pirckheimer, Kepleriana, …) |
Doubletten und ihr Zielort
Stand vor dem Umbau (3. Oktober 2026), gemessen an den Quellen.
Identität von Personen, Orten, Institutionen, Zeiten
Sieben Erzeuger entscheiden heute mit sieben Regeln, wer wer ist:
| Erzeuger | Regel |
|---|---|
ai-karman-manager/scripts/build_content_db.py · EntityRegistry |
gleicher Name nach casefold = gleiche Person |
ai-karman-manager/scripts/build_place_country.py |
Land pro Schreibweise |
pdai/collections/pirckheimer/scripts/build_entities.py, build_referents.py, build_register.py |
Lexikon, Jaro-Winkler ≥ 0,92 |
ai-query/scripts/build_pirckheimer_letters.py, build_euler_iva_letters.py |
Anzeigename als Schlüssel |
pdai/collections/kepleriana-munich-2024/scripts/build_db.py |
ASCII-Slug |
ai_lemma_index/sidecar/fql_build.py · stage_persons |
LLM-Merge, nur eulerOO-IVA |
ai_lemma_index/sidecar/fql_build.py · stage_mentions |
exakter Abgleich der Oberfläche |
Die Folge im Kármán-Nachlass: Theodore von Kármán hat rund 40 Registereinträge, Prandtl 8, Pasadena 6, Göttingen 4; „L. Prandtl“ und „Albert Einstein“ in den Texten hängen an keinem.
Zielort: ai_lemma_index.register. Builder liefern Formen, das Register entscheidet und projiziert zurück; entity_registry, person_registry, agent_context.json und letter_parties lesen nur noch die Projektion.
Weitere Doubletten
| Aufgabe | heute | Zielort |
|---|---|---|
| Namensfaltung | fql/bind.py:norm, validity/pdai.py:norm, entity_registry.norm_text, collection_memory._fold, grounding._fold, fql_build.norm |
ai_lemma_index.register.falten |
| Datumsnormalisierung EDTF | ai_query/register/edtf.py, ai_lektorat/.../validity/terms.edtf |
ai_lemma_index.register.zeit |
| Was eine Collection beantworten kann | famulus_notebook/fql/capabilities.py, famulus_validity/evidence.py, ai-query/build_grounding_index |
famulus_proof.evidenz |
| DuckDB-Verbindung zum Sidecar | fql/engine.py:connect, validity/evidence.py:connect |
famulus_proof.evidenz |
| Zielentfaltung | famulus-validity (eigenes Paket) |
famulus_proof.entfaltung |
| Evidenzraum | entfaltung/channels.py (Varianten, längstes Wort, Teilstring) und evidenzraum/baum.py (am 15. Oktober entfernt); die Partitur famulus_evidenzraum_agent am 18. Oktober zurückgezogen |
famulus_proof.evidenzraum: die Entfaltung ruft constraint-raum und liest die fundlage (evidenzraum/fundlage.py) |
| FQL-Engine und Argument | famulus_notebook/fql |
famulus_proof.fql |
| Argument-Shims ohne Aufrufer | fql/argument/{critical,derive,gather,goal,validate}.py |
gelöscht |
| LLM-Client der Indexierung | fql_build.LLM |
ai_lemma_index.llm (Register und Sidecar) |
Der Importzyklus famulus-notebook → famulus-validity → famulus_notebook.fql entfällt, weil beide Teile in famulus-proof liegen.
Stand nach dem Umbau (3. Oktober 2026, abends)
ai-lemma-index nach Belangen
Das Sammelpaket stanzadoc/ (26 Module) ist aufgelöst; jedes Modul liegt bei seinem Belang, alle Importe in allen Workspaces sind umgeschrieben (Skript scripts/reorg_2026_10_03.py, Syntaxbaum, kein Kompatibilitätsmodul):
| Unterpaket | Module |
|---|---|
stanza/ |
segment, pagedoc, ingest, batch, pipeline, mathmask, config, contract |
corpus/ |
corpus_build, corpus_engine, corpus_audit, corpus_cli, federation, query_plan |
lemma/ |
lemma_pilot |
ner/ |
gazetteer_store (Person, ohne Modell). GLiNER2.5 ist seit dem 8. Oktober 2026 aus der Pipeline |
vector/ |
chroma_build, chroma_store |
lwgrammar/ |
lwgrammar_compile, lwgrammar_store |
sidecar/ |
fql_build |
collection/ |
complete, audit, gate_harness, bib_build |
register/ |
Einzeldinge: falten, bloecke, formen, entscheiden, aufbau, projektion, nennungen, binden, zeit, store, cli |
llm.py |
der eine LLM-Client der Indexierung (Ollama, Gemini über REST), Cache in DuckDB |
Die Module des ursprünglichen Lemma-Indexers (aggregate, perpage, search, fastsearch, …) liegen weiter auf oberster Ebene. Die schweren Abhängigkeiten sind Extras ([nlp], [vector], [cloud]); famulus-proof und der Lektor installieren nur die Basis.
famulus-proof als eine Begründungsbibliothek
| Unterpaket | vorher |
|---|---|
resolution, derive |
famulus-proof (unverändert) |
entfaltung/ |
Paket famulus-validity (entfernt) |
fql/ |
famulus_notebook.fql |
lernen/ |
famulus_notebook.learn.{artifacts, store, patch} |
ablage, heim |
Datei-Helfer des Notebook-Logs; collections_root (dreifach vorhanden) |
evidenzraum/ |
neu |
Der Importzyklus Notebook ↔︎ Validity ist aufgelöst. famulus-notebook behält Oberfläche, Server, Runner und die Lernkampagne (learn/loop, gate, model).
Am 4. Oktober 2026 ist die zweite Evidenzraum-Implementierung entfernt. entfaltung/channels.py bindet nicht mehr über Varianten-Strings und Teilstring; die Phase evidenzraum der Zielentfaltung ist die Partitur famulus/evidenz/raum. Die Lesart prüft die Identität an den Nachnamenschlüsseln des Registers. Der Raum selbst trägt ein Zertifikat famulus-raum/1.
Am 8. Oktober 2026 kam die Filterung von Evidenzräumen dazu (Partitur famulus/evidenz/constraint), neben dem Entscheidungsbaum. Sie liegt ganz in famulus_proof.evidenzraum:
| Modul | Aufgabe |
|---|---|
objekte |
Evidenzobjekte, ihre Ids, Trägerart, Verbindung zur Evidenzdatenbank, das Gate gate:fx, der Körper |
bau |
Bau von fx_* aus Sidecar, Stanza, Hauptdatenbank oder Seiten-XML |
schemakarte |
Schemabaum der Karte (auch aus einer Vorlage, karten/_vorlagen/), Prüfung gegen DTD und DuckDB |
fastindex |
Klassifikation der Werte auf Schlüssel (Register, EDTF, Lemma, LWgrammar) |
attributbaum |
Suchbaum, Minimalität, Widerspruch, Merge, Fragebaum |
kontext |
Kontextbaum aus Sitzung und Gedächtnis der Collection |
theorie |
Suchbaum zu einer DuckDB-Anweisung |
verfeinerung |
Bewertung der Menge, Rückfrage |
sitzung |
Treffermenge einer Sitzung als Polars-LazyFrame: Verfeinerung und Facetten im Speicher |
Am 15. Oktober 2026 kam der Satzrecord dazu (famulus_proof.satzrecord): ein Sidecar {coll}_satz.duckdb mit den vollen Seiten-, Absatz- und Satzdatensätzen und den beim Bau berechneten Schlüsseln (sr_attr). Die Filterung liest diese Schlüssel; die Zeichenkettenvergleiche des Entscheidungsbaums (evidenzraum/baum.py) sind entfernt. Am 18. Oktober wurde die Zielentfaltung an den Filter gebunden: rules/enfolding.yaml ruft constraint-raum, dann fundlage (evidenzraum/fundlage.py: Bindung, Kanalplan, Kandidaten mit Gebrauchslesart), dann die Normalisierung mit Anfrageformen (rules/formen.yaml); der Planer rechnet mit Budget (rules/unfold.yaml), die Lesart liest regelgeleitet mit Cache (entfaltung/lesartcache.py), der Verfasser ist eine Leiter von Gründen (rules/verfasser.yaml), das Urteil ist graduiert (validiert-mit-rest, rules/kritische_fragen.yaml).
Die Tabellen fx_* baut evidenzraum/bau.py (scripts/build_fq_index.py) im Sidecar einer Korrespondenz, für eine Collection ohne Sidecar (Wäfler) in einer eigenen Datenbank; sie lösen den flachen Briefindex fq_index ab. Neun Collections haben eine Karte mit Schemabaum: Kármán, Hevelius, Euler IVA, Pirckheimer, Wäfler primär und sekundär, Kepler primär und sekundär, Copernicus primär.
Noch nicht zusammengeführt
| Aufgabe | wo noch doppelt | Grund |
|---|---|---|
| Identität im Pirckheimer-Erweiterungslayer | pdai/collections/pirckheimer/scripts/build_entities.py, build_referents.py, build_register.py (Lexikon + Jaro-Winkler, Tabellen ext_*) |
eigene Abfrageschicht mit eigener Dokumentation; der Hauptstrang pirckheimer.duckdb liest schon das Register |
| Datumsintervalle im Lektor | ai_lektorat/viewer/validity/bank.edtf_interval, terms.edtf |
Ziel ai_lemma_index.register.zeit.intervall / normalisiere existiert; Umstellung des Lektors steht aus |
| Datumsparser Pirckheimer | pirckheimer/scripts/build_dates.py |
collection-eigene Konfiguration; Ziel register.zeit.parse_date_text |
| Namensfaltung in ai-query | entity_registry.norm_text, collection_memory._fold, grounding._fold, fql/bind.norm |
Ziel register.falten.falte |
| Personenbindung ai-query | sqldirect/grounding.py liest person_registry, das jetzt aus der Projektion gebaut wird |
Bindung selbst noch nicht über register.binden |
| FQL-Binder für nicht projizierte Sidecars | fql/bind._person_candidates (Varianten-Strings) |
nur noch Rückfall, solange eine Collection nicht aus dem Register projiziert ist |
ai-query behält Anfrageauflösung und Grounding, liest Personen aber aus dem Register. Der Lektor behält die satzspezifische Klauselbank; Datums- und Namensfunktionen nimmt er aus den Zielorten. Die fünf LLM-Clients der Anwendungen (Lektor, ai-query, Notebook-Assistent) dienen verschiedenen Modellrouten und werden nicht zusammengelegt.