13 KiB
Projekt-Recherche v1
ProjectResearch ist die gemeinsame lesende Schnittstelle für die deterministische
Case-Aufbereitung und die LLM-gesteuerte Hypothesenuntersuchung. Die erste LLM-Phase
bleibt der CaseInterpreter. Der CaseBuilder diagnostiziert nicht und führt keine
LLM-Abfragen aus. docs/architecture.md bleibt unverändert.
Datenquellen und Grenzen
- Sourcecode: lokaler Git-Clone des vom Betreiber freigegebenen Repositories. Abfragen lesen Git-Objekte eines vollständigen Commit-Hashes, nicht den veränderlichen Arbeitsbaum. Ein Branchwechsel oder Git-Pull ändert keine bestehende Bindung.
- Source-Schemata: SQL-Dateien desselben Commits. Sie beweisen Tabellenstrukturen dieses Codestands, keine tatsächlich vorhandenen Datenbankzeilen.
- Datenbank: parameterisierte SELECT-Abfragen gegen ausdrücklich freigegebene Tabellen einer MySQL-/MariaDB-Datenbank. Zugangsdaten bleiben in Environment-Variablen oder einer lokalen Passwortdatei. Sie werden nicht in Requests, Captures oder Logs kopiert.
- Externe Webrecherche: weiterhin separat für vorgesehenes Verhalten. Dieser Meilenstein aktiviert keine Google-Suche und führt keine kostenpflichtigen LLM-Aufrufe aus.
Die LLM darf weder Serveradresse, URL, Branch, Dateisystemwurzel, Datenbank noch Zugangsdaten bestimmen. Freies SQL, Shellzugriff, Joins mit frei vorgegebenen Ausdrücken, Schreiboperationen, Builds und Labsteuerung stehen nicht zur Verfügung. Zusammenhänge werden durch aufeinanderfolgende explizite Abfragen untersucht.
Operationen
Die Investigation verwendet next.kind = "tool", operation = "project.query"
und arguments gemäß project-query-v1.schema.json.
arguments.kind |
Funktion |
|---|---|
source.files |
Dateipfade durch literalen Teilstring finden |
source.search |
Literale Textsuche, optional auf Pfadpräfix begrenzt |
source.symbol |
Suche nach vollständigem Symbolwort |
source.registration |
Symbolvorkommen als Ausgangspunkt einer Registrierungsprüfung |
source.schema |
Literale Suche ausschließlich in SQL-Dateien |
source.read |
Begrenzten Zeilenbereich einer bekannten Datei lesen |
database.tables |
Namen in den konfigurierten Datenbanken und Tabellenfreigaben finden |
database.schema |
Tatsächliche Spalten, Typen, Nullbarkeit und Schlüssel lesen |
database.rows |
Spalten auswählen, explizite Filter und begrenzte Seite lesen |
database.count |
Vollständige Trefferzahl für dieselben Filter bestimmen |
DB-Filter unterstützen eq, ne, lt, le, gt, ge, contains, in.
Mehrere Filter werden mit AND verbunden. contains behandelt %, _ und das
Escape-Zeichen als literale Eingabe. Werte werden ausschließlich als SQL-Parameter
übergeben. Tabellen und Spalten sind validierte Bezeichner; Tabellen müssen zusätzlich
in der Betreiber-Allowlist liegen. Ein Schema-Lookup prüft die tatsächlichen Spalten.
SQL-DECIMAL-Werte werden als exakte Zeichenfolgen übertragen, nicht gerundet.
Textsuche ist lexikalisch: ein Treffer beweist weder eine semantische Definition noch eine Registrierung oder einen ausgeführten Aufruf. Auch historische SQL-Updates sind kein Ersatz für die aktuelle Datenbank. Pfad-Traversal, absolute Pfade und Git-Metadaten werden abgelehnt; Symlinks und Submodule werden nicht als lesbare Source-Dateien aufgenommen.
Abfragen haben konfigurierbare Zeilen-, Byte-, Datei- und Zeitlimits. Ergebnisse markieren
Pagination, ausgelassene Dateien und gekürzte Zeilen. complete_filtered_rows gilt nur
für das genau beschriebene Prädikat ohne Offset/weitere Seite. Eine vollständige Abfrage
mit null Treffern ist ein belastbarer Abwesenheitsbeleg innerhalb dieses Snapshots und
Prädikats. Eine partielle Suche rechtfertigt keinen globalen Abwesenheitsschluss.
Persistenz und Budget
Captures besitzen Formatversion 1, Schema, Anfrage, Ursprung und Ergebnis. Git-Ursprünge enthalten URL und Commit; Treffer zusätzlich Blob-ID, SHA-256 und Zeilennummer. DB-Ursprünge enthalten Datenbank und die vom Betreiber vergebene Snapshot-Identität. Diese Identität muss beim Wechsel/Neuimport eines Snapshots ebenfalls geändert werden; sie ist keine automatisch berechnete Prüfsumme eines laufenden Servers.
Investigation-Ergebnisse werden unter analysis/evidence/captures/<sha256>.json
zusammen mit Requests, Rohantworten und Evidence Records append-only gespeichert.
Auch leere Antworten behalten Anfrage und Abdeckung. Historienprüfung und Wiedereinstieg
benötigen keinen laufenden Git-/DB-Provider. Die Fallakte enthält die tatsächlich gelesenen
Ausschnitte und Zeilen, nicht eine vollständige Kopie von Repository und World-DB.
Ein Tool schreibt selbst nicht in den Case. Der bestehende Controller reserviert das
positive Aktionsbudget für project.query, führt die Anfrage aus und übernimmt validierte
Captures atomar mit der Evidenz. Wiederholte identische Ergebnisse sind keine neue Evidenz.
Der In-Memory-Cache friert eine Antwort während Query/Validierung/Persistenz ein; bei einem
Neustart sind gespeicherte Evidenz und der bestätigte Plan autoritativ.
Ausfälle der Recherche führen zu BLOCKED / RESEARCH_UNAVAILABLE. Ein bestätigter Plan
bleibt wiederaufnehmbar, einschließlich seiner Reservation. Ungültige Modellantworten
führen nach dem konfigurierten Limit zu BLOCKED / INVALID_LLM_RESPONSES; eine technische
Ablehnung beendet keine Hypothese und verändert keine vorhandene Evidenzbewertung.
Nach Behebung ist eine explizite Operator-Wiederaufnahme über CheckpointStore.advance
in den im letzten Blockierungscheckpoint hinterlegten resume_state nötig. Der
Retry-Zeitpunkt und die bestehende Feedback-Sperre bleiben verbindlich.
Case-Aufbereitung
CaseBuilder(..., project_research=service) sammelt vor Abschluss einer Revision
deterministisch konfigurierte Queries und Entity-Lookups. Namen und Questvoraussetzungen
werden mit Provenienz als technische Fakten sichtbar, bevor die erste LLM-Anfrage beginnt.
Das verhindert, dass eine numerische ID allein als Name oder betroffener NPC ausgelegt wird.
Abfragen und Resultate liegen unter research/project/; die Case-Inputs werden mit einem
neuen versionierten Index erweitert. Derselbe Enrichment-Checkpoint wird nicht wiederholt.
Eine abgeschlossene Revision wird nicht nachträglich mit neuen Rohinputs umgeschrieben.
Die Beispielkonfiguration löst Creature- und Quest-IDs generisch auf. Sie enthält keine BUG-000020-spezifische Diagnose oder Wolpertinger-ID. Die LLM kann während der Untersuchung weitere Tabellen und Source-Ausschnitte gezielt abfragen.
Kontextorientierte Erweiterung
Die Quest-Aufbereitung übernimmt nun auch LogDescription, QuestDescription und
StartItem. Damit bleiben Handlung, Zweck des mitgegebenen Gegenstands und die
beschriebenen Voraussetzungen sichtbar. Questtexte beschreiben die im Template
formulierte Mechanik; sie beweisen keine tatsächlich ausgeführte Serveraktion.
enrichment.texts hebt solche Texte als eigene project_description-Fakten mit
Quellspalte, Rollenlabel und Herkunft hervor. Im numerischen Query-Fakt bleibt ein
Textverweis statt einer zweiten Kopie. Die vollständige unveränderte Antwort liegt
weiterhin im Capture; die Interpretation sieht den Text einmal in lesbarem Kontext.
enrichment.relationships verfolgt ausdrücklich konfigurierte Beziehungen aus
zurückgegebenen DB-Spalten. from_table, from_column und from_id_column bestimmen
den Ursprung. table, column und columns bestimmen die folgende DB-Abfrage.
relation benennt den Zusammenhang; entity_type ergänzt eine referenzierte Entität.
Die Herkunft jeder Beziehung zeigt mit Capture und JSON-Pointer auf den Originalwert.
Ein referenziertes Item wird nicht als beobachtetes Laufzeitobjekt oder Ursache markiert.
Die Vcore-Konfiguration verfolgt mitgegebene/geforderte Items, Queststarter,
SmartAI-Datensätze und ausdrücklich gebundene Creature-/Item-/Spell-Scriptnamen.
SmartAI-Abfragen berücksichtigen source_type = 0, damit numerisch gleiche IDs anderer
Entitätstypen nicht vermischt werden. Scriptnamen werden als Symbol gesucht, nicht als
beliebige Zahl über die gesamte Historie. Weitere Beziehungen bleiben konfigurierbar;
das generische Python-Modul enthält keine WoW-IDs oder Quest-Sonderfälle.
when_column/when_value begrenzen bedingte Beziehungen. Standardmäßig werden null,
leere Zeichenfolgen und numerische Null nicht verfolgt; ignore_values kann dies für
andere Profile anpassen. Identische Queries werden nur einmal gesammelt. Zyklen und
Verzweigungen sind durch konfigurierbare max_queries, max_depth und
max_relationships begrenzt. Ausgelassene Abfragen/Beziehungen werden als
project_context_coverage sichtbar statt als vollständige Ermittlung ausgegeben.
Leere Item-Script- oder Queststarter-Resultate sind nur Befunde innerhalb dieser Tabellen. Sie beweisen weder ein fehlendes Item noch, dass eine Quest nicht durch einen anderen Mechanismus vergeben werden kann. Client-/Hotfix-Itemdaten werden durch diesen Meilenstein nicht importiert oder erfunden. Eine komplette Item→Spell→Creature-Kette ist deshalb nicht in jedem Case automatisch auflösbar; fehlende Teile bleiben Recherchebedarf.
Mit aktivierter Projekt-Recherche wird investigation_project_v1 verwendet. Der volle
Context bleibt unverändert archiviert. Der Prompt lässt Input-Inventar und doppelte
vorige Resultate weg; fremde Hypothesen behalten Evidenz-IDs/Provenienz, aber keine Payloads.
Die Auswahl ist deterministisch und gekennzeichnet. Bereits gespeicherte Legacy-Prompts
bleiben mit ihrer alten Version rekonstruierbar. Dies reduziert Kontextmenge, garantiert
aber keinen bestimmten Eurobetrag und ersetzt keine Messung des nächsten LLM-Tests.
Lokale Testumgebung
Die eingerichtete Instanz benutzt MariaDB 10.11.14 aus dem offiziellen portablen ZIP
(SHA-256 838b7d91b871a30c2e42e5ceff9c6859ddd061b57328fb7cb51154af9bd8ddf4).
Es wird kein Windows-Dienst installiert. Daten und Logs liegen ausschließlich unter
service-data/research/, Git-Clone ebenfalls dort. Diese Dateien werden nicht committet.
Importiert wurde ausschließlich cata_world (206 Tabellen) aus dem bereitgestellten
Backup, SHA-256 4964f277ef5cf7f7f98bf4378971dcb55180bac813d49bcda6d2f03ff6969662.
Account-, Charakter- und weitere Datenbankabschnitte wurden ausgelassen.
Die Instanz bindet 127.0.0.1:33079; viano_reader besitzt SELECT ohne GRANT OPTION.
read_only ist aktiviert, Abfragen verwenden zusätzlich eine Read-only-Transaktion.
Der administrative Restore ist ein separates Entwicklungswerkzeug, keine Runtime-Funktion
des Analyseprogramms und kein Modelltool.
Optionale Dependencies installieren:
.\.venv\Scripts\python.exe -m pip install -e ".[research,test]"
config/project.local.toml wurde aus der Beispielkonfiguration vorbereitet. Das Programm
lädt relative Providerpfade relativ zu dieser Konfigurationsdatei. Ein zukünftiger
Server nutzt eigene lokale Zugangsdaten und dieselbe Schnittstelle mit SELECT-only-Rechten.
Die bereits initialisierte Instanz bei Bedarf starten/stoppen:
.\.venv\Scripts\python.exe scripts/dev_world_db.py start --binary-dir service-data/research/runtime/portable/mariadb-10.11.14-winx64/bin --directory service-data/research/world-db
.\.venv\Scripts\python.exe scripts/dev_world_db.py stop --binary-dir service-data/research/runtime/portable/mariadb-10.11.14-winx64/bin --directory service-data/research/world-db
Ein neuer Rechner benötigt zunächst den portablen Server, eine initialisierte Datadir
(mariadb-install-db.exe --datadir=<absoluter Pfad> --port=33079 --silent) und einen
einmaligen dev_world_db.py restore --dump <Backup> gegen diese neue lokale Instanz.
Das Werkzeug verweigert Administration, wenn der Port zu einer anderen Datadir gehört.
Zugangsdaten bleiben unter service-data/; reader.local.txt enthält nur das Reader-Passwort.
Eine strukturierte Anfrage kann ohne LLM und ohne Paketänderung geprüft werden:
{"kind":"database.rows","table":"creature_template","columns":["entry","name"],"filters":[{"column":"name","operator":"contains","value":"Wolpertinger"}],"offset":0,"limit":10}
Als service-data/research/query.json speichern und ausführen:
.\.venv\Scripts\python.exe -m viano_bug_analysis.project_research --config config/project.local.toml --query service-data/research/query.json
Ein späterer, ausdrücklich gestarteter LLM-Trial erhält zusätzlich
--project-config config/project.local.toml. Für den Qualitäts-/Kostenvergleich einen
frischen Testcase verwenden: alte Hypothesen und frühere terminale Budgetstände werden
durch diesen Meilenstein nicht heimlich korrigiert oder zurückgesetzt.
Offline-Suite und optionale Integrationstests:
.\.venv\Scripts\python.exe -m pytest -q
$env:VBA_TEST_PROJECT_CONFIG = "config/project.local.toml"
.\.venv\Scripts\python.exe -m pytest tests/test_project_database_integration.py -q
Die Integrationstests prüfen den bekannten Backupstand ausschließlich lesend. Der
CaseBuilder-Smoke-Test aus den echten wowdiag/wowsrc-Paketen liegt separat unter
service-data/research/smoke; die ursprüngliche gestoppte Fallakte bleibt erhalten.
Gemini unterstützt Google Search Grounding, wenn die API-Anwendung es aktiviert: https://ai.google.dev/gemini-api/docs/google-search . Der aktuelle OpenAI-kompatible Adapter setzt keine solchen Tools. Ein Gitea Runner ist für diesen Stand nicht nötig; er könnte später Indizes aufbauen, während die Analyse weiterhin nur lesend auf diese zugreift.