Files
VianoBugAnalysis/docs/project-research-v1.md
T

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.