Files
neural-hunt/TESTING.md
groot 7fb7960608
Some checks failed
release-tag / release-image (push) Failing after 1m14s
RC-2
2026-08-10 06:30:40 +02:00

18 KiB
Raw Blame History

Validation — V2.5.1 Reconnect / Presence / Heartbeat

Regression: regelmäßiger HTTP 409 nach ~90 Sekunden

  1. Browser-Client mit einem aktiven Task verbinden und mindestens 3 Minuten ohne F5 laufen lassen.
  2. Prüfen, dass Auto-Guesses über die frühere 90-Sekunden-Grenze hinweg weiterlaufen.
  3. DevTools → Network → WS beobachten: der Server sendet echte WebSocket-Ping-Control-Frames; Browser-Pongs verlängern die Read-Deadline.
  4. Netzwerk für einige Sekunden trennen und wieder aktivieren. Der Browser muss automatisch reconnecten und ohne F5 weitertippen.
  5. Während eines Task-Wechsels bzw. schnellen Reconnects darf ein verspätetes ReleasePresence der alten Verbindung die neue Presence nicht entfernen. Das wird zusätzlich durch TestPresenceReconnectOldReleaseCannotDeleteNewLease geprüft.
  6. Shell-Client ebenfalls mindestens 3 Minuten laufen lassen, Verbindung kurz unterbrechen und prüfen, dass [ws] wieder verbunden erscheint und Guessing fortgesetzt wird.

Maschinenlesbare 409-Codes:

presence_required
sequence_mismatch
task_config_changed
selection_conflict
task_inactive

V2.5 — Task-Auswahl, Vererbung und Shell-Client

Browser-Landing-Page

  1. Server mit mindestens zwei aktiven Tasks starten (ACTIVE_TASK_COUNT=2).
  2. / in einem neuen Browserprofil öffnen.
  3. Prüfen, dass vor der 3D-Ansicht die Task-Landing-Page erscheint.
  4. Einen Task wählen und prüfen, dass WebSocket/Auto-Guess starten.
  5. TASKS wählen, einen anderen Task anklicken und prüfen, dass keine identity already connected-Meldung entsteht.
  6. Browser neu laden: die serverseitig zuletzt gewählte Task-Karte muss als ausgewählt markiert sein.

Task-spezifisches NFT-Prompt + Admin-Draft

  1. /adminTASK → Task auswählen.
  2. Anzeigename, Beschreibung, NFT-Prompt-Anweisungen und Negative Prompt eintippen, noch nicht speichern.
  3. Mindestens einen Auto-Refresh-Zyklus (>3 s) abwarten und danach F5 drücken.
  4. Prüfen, dass die noch nicht gespeicherten Eingaben weiter im Formular stehen.
  5. TASK-KONFIG SPEICHERN verwenden und anschließend neu laden; nun müssen die Werte vom Server kommen.
  6. Task gewinnen oder über Admin close beenden.
  7. Folge-Task öffnen und prüfen, dass range_bits, task-spezifische Intervalle, Anzeigename, Beschreibung und beide Prompt-Felder identisch geerbt wurden.

Shell-Client interaktiv

go run ./cmd/client -url http://127.0.0.1:8080

Prüfen:

tasks
status
map 25
leaderboard 20
nfts 10
use 2
status

Der Shell-Client muss weiter automatisch Tipps senden. Nach use darf der Server die neue WebSocket-Verbindung nicht wegen der alten Presence ablehnen.

Shell-Client unbeaufsichtigt

go run ./cmd/client \
  -url http://127.0.0.1:8080 \
  -non-interactive \
  -task 1 \
  -max-nodes 250

Mindestens zwei Tippintervalle laufen lassen und im Admin prüfen, dass Guess-/Score-Aktivität vorhanden ist. Dann Ctrl+C; die Presence muss freigegeben werden.

Browser-/Shell-Identity-Portabilität

Im Browser eine Identity exportieren. Danach Browser-Tab schließen, damit die Single-Connection-Lease frei ist:

export NEURALHUNT_IDENTITY_PASSPHRASE='test-passphrase'
go run ./cmd/client \
  -import ./neuralhunt-identity-....json \
  -identity ./tmp-shell-identity.json

Die Client-ID muss mit der Browser-ID übereinstimmen.

Umgekehrt:

export NEURALHUNT_IDENTITY_PASSPHRASE='test-passphrase'
go run ./cmd/client \
  -identity ./tmp-shell-identity.json \
  -export ./tmp-browser-import.json

Diese Datei anschließend über Import in einem Browserprofil laden; die Client-ID muss identisch bleiben.

Automatische Tests

Zusätzlich zu den bisherigen Tests:

go test ./cmd/client

enthält PBKDF2-Testvektor sowie Raw-/verschlüsselten Identity-Roundtrip. internal/data/successor_test.go prüft mit einem echten SQLite-Treiber die Task-Vererbung, Idempotenz des Nachfolgers und das atomare Migrieren der Client-Auswahl.

In dieser Erstellungsumgebung erfolgreich ausgeführt:

node --check internal/webui/dist/app.js

gofmt -w cmd/client/*.go internal/data/store.go internal/server/server.go internal/artifact/worker.go

# kompletter Source-Compile mit lokalen API-Stubs für die drei nicht ladbaren Module
go test -run '^$' ./...

# echte Shell-Client-Krypto-/Identity-Tests; nur der WebSocket-Import ist dabei gestubbt
go test ./cmd/client

Zusätzlich wurde eine V2.4-artige SQLite-Datenbank mit Python/SQLite angelegt und die Upgrade-Reihenfolge aus OpenSQLite() reproduziert. Dabei wurden die fünf neuen Task-Spalten, client_task_selection und der erst nach parent_task_id angelegte tasks_parent_unique_idx erfolgreich erzeugt. Das ist relevant, weil der Index bei Bestandsdatenbanken nicht vor dem ALTER TABLE angelegt werden darf.

Ergebnis dieser ausführbaren Prüfungen: erfolgreich.

Statisch geprüft / implementiert

  • UI ist weiterhin vollständig unter internal/webui/dist/ eingebettet; kein npm/Vite-Build nötig.
  • /leaderboard ist eine SPA-Route und besitzt einen öffentlichen Live-WebSocket.
  • Mobile Mode ist für Client, Leaderboard und Admin implementiert; Admin bietet mobile MAP/TASKS/CONTROL-Navigation.
  • Das Leaderboard lädt Gewinner-Artefakte ausschließlich über /api/public/artifacts/{task}/preview.
  • Die öffentlichen Leaderboard-Daten enthalten NFT-Anzahl und letzte Wasserzeichen-Preview, aber keine Original-Artifact-URI.
  • Der frühere öffentliche /artifacts/*-File-Server ist entfernt; Original und Manifest benötigen ein Admin-JWT.
  • Raster-Previews werden serverseitig mit einem eingebrannten Bitmap-Wasserzeichen neu als PNG codiert; SVG-Previews erhalten eine wiederholte Wasserzeichenebene.
  • TARGET FIELD bildet Score monoton und direkt auf den Orbitalradius ab; Kameratiefe kann die wahrgenommene Nähe nicht mehr umkehren.
  • Score-Ringe: 0 / 25 / 50 / 75 / 90 / 95 / 99+; Vorder- und Rückhälfte werden zur Tiefenwahrnehmung unterschiedlich gerendert.
  • Pseudozufällige Client-zu-Client-Synapsen sind vollständig entfernt.
  • SIGNALWEGE verbinden ausschließlich Top-Kandidaten/eigenen Client mit dem Task-Core; Score-Verbesserungen erzeugen nur entlang dieses realen Pfads Signalimpulse.
  • Client lädt bei task_changed Range Bits, Seed, Revision, Intervalle und Punkte neu.
  • Client-Autosubmit verwendet keinen statischen setInterval mehr, sondern die jeweils aktuelle Task-Konfiguration.
  • Task-Aktionen werden in task_actions persistiert, jede Sekunde geprüft und mit Status/Audit gespeichert.
  • Alte SQLite-Datenbanken erhalten die neuen tasks-Spalten per ALTER TABLE-Migration.
  • set_range_bits unterstützt preserve und reroll.
  • Task-spezifische Tippintervalle überschreiben globale Runtime-Defaults.
  • OpenAI-, ComfyUI- und A1111-Provider speichern nur lokal erzeugte Ergebnisbytes + Manifest; kein S3 notwendig.
  • OpenAI-Provider validiert für gpt-image-2 die dokumentierten Dimensionsgrenzen, bevor ein Request gesendet wird.
  • Provider-Secrets/URLs werden nicht über die Runtime-Settings-API exponiert.
  • ComfyUI unterstützt Workflow-Platzhalter für Prompt/Negative Prompt/Seed/Größe/Steps/Modell.
  • A1111 unterstützt optional Basic Auth und Checkpoint-Override pro Request.

In dieser Umgebung nicht vollständig ausführbar

go test ./... und go mod tidy können hier nicht abgeschlossen werden, weil ausgehender DNS/Netzwerkzugriff auf proxy.golang.org gesperrt ist. Der Versuch scheitert beim Download dieser bereits im go.mod referenzierten Module:

modernc.org/sqlite
github.com/go-chi/chi/v5
github.com/gorilla/websocket

Dadurch konnten internal/data, internal/server, internal/ws und das komplette Binary hier nicht gegen frisch heruntergeladene Dependencies gebaut werden. Die direkt von ihnen unabhängigen geänderten Go-Packages wurden kompiliert/getestet.

Docker ist in der Erstellungsumgebung ebenfalls nicht verfügbar.

Empfohlene Tests auf deinem Rechner

go mod tidy
go test ./...
go run ./cmd/server

Dann:

  1. / öffnen und prüfen, dass TARGET FIELD standardmäßig aktiv ist. Einen Score-90-, Score-95- und Score-99-Punkt vergleichen: 99 muss unabhängig von Orbit/Neigung sichtbar auf dem kleinsten Ring liegen.
  2. ORBIT laufen lassen und die Ansicht ziehen: Die Reihenfolge der Ringradien darf sich durch Kamerabewegung nicht umkehren.
  3. SIGNALWEGE einschalten: Es dürfen keine Client→Client-Kanten erscheinen; nur ausgewählte Client→Task-Pfade sind erlaubt.
  4. Zwei unabhängige Browserprofile auf 127.0.0.1 verbinden.
  5. /leaderboard in einem dritten Tab öffnen; Punktänderungen sollen ohne manuelles Reload erscheinen.
  6. Im Admin-Bereich einen aktiven Task auswählen und pause sofort ausführen. Clients müssen PAUSE anzeigen und keine Tipps senden.
  7. resume ausführen; Autosubmit muss mit dem aktuellen Client-Intervall weiterlaufen.
  8. set_range_bits im Modus preserve erhöhen; Client muss neue Bitzahl ohne Reload verwenden.
  9. set_range_bits im Modus reroll ausführen; Punkte/Scores müssen auf 0 zurückfallen und neuer Seed/Revision aktiv werden.
  10. Eine Range-Bit-Änderung fünf Minuten in die Zukunft planen und anschließend abbrechen; Status cancelled prüfen.
  11. Zwei geplante Aktionen hintereinander setzen, z. B. 24 Bit und später 32 Bit, und Ausführung/Audit prüfen.
  12. Einen kleinen Zahlenraum verwenden, einen Task lösen und lokales SVG + Manifest prüfen.
  13. /leaderboard öffnen: das Gewinner-Artefakt muss in Galerie und Ranking nur als Wasserzeichen-Vorschau erscheinen.
  14. Direkter Aufruf der früheren /artifacts/...-URI muss 404 liefern; Original/Manifest aus dem Admin-Dashboard müssen weiterhin nach Authentifizierung öffnen.
  15. Browser auf <850 px setzen oder MOBILE aktivieren: Client-Details müssen einklappbar sein; im Admin müssen MAP/TASKS/CONTROL einzeln erreichbar sein.

OpenAI Provider

ARTIFACT_PROVIDER=openai
ARTIFACT_MODEL=gpt-image-2
OPENAI_API_KEY=...
ARTIFACT_WIDTH=1024
ARTIFACT_HEIGHT=1024
ARTIFACT_QUALITY=medium

Task lösen bzw. bei einem abgeschlossenen Task NFT-Bild neu erzeugen ausführen. Erwartet:

/data/artifacts/artifact_<id>/image.png
/data/artifacts/artifact_<id>/manifest.json

ComfyUI Provider

ComfyUI starten, API-Workflow exportieren und im Workflow mindestens {{PROMPT}} sowie optional die anderen Platzhalter verwenden. Danach:

ARTIFACT_PROVIDER=comfyui
COMFYUI_URL=http://127.0.0.1:8188
COMFYUI_WORKFLOW_PATH=/path/workflow-api.json
ARTIFACT_MODEL=checkpoint.safetensors

AUTOMATIC1111 Provider

A1111 mit --api starten:

ARTIFACT_PROVIDER=a1111
A1111_URL=http://127.0.0.1:7860
ARTIFACT_MODEL=checkpoint.safetensors

Bei --api-auth user:pass zusätzlich A1111_USER und A1111_PASSWORD setzen.

Regressionen aus früheren Fixes

  • Auth challenge/login toleriert optionale JWK-Metadaten (alg, use, kid etc.).
  • Mehrere Challenges derselben Identität überschreiben einander nicht.
  • Eine Browser-ID darf weiterhin nur eine aktive Client-WebSocket-Verbindung besitzen.
  • Leere Listen werden als [], nicht als null, an die UI geliefert.
  • Client-Punkt wird direkt beim WebSocket-Connect erzeugt.

Additional v2 checks

  • SQLite schema parsed successfully with Python sqlite3, including task_actions and the live task override columns.
  • The legacy migrations/001_init.sql mirror was synchronized with internal/data/schema.sql so manual schema inspection does not show an obsolete layout.
  • Responsive CSS keeps the Admin Task Actions / Artifact control plane visible on common laptop widths (8511280px).

V2.1 package-integrity regression

The V2 archive was missing internal/data/, which caused an old store.go to survive when users extracted over a previous checkout. That produced compile errors such as missing Task.GuessMinIntervalSec, Task.Paused, LiveLeaderboard, and TaskAction. V2.1 explicitly includes:

  • internal/data/store.go
  • internal/data/schema.sql
  • the matching V2 internal/server/server.go

Always test from a clean extraction directory.

V2.2 zusätzliche Validierung

  • node --check internal/webui/dist/app.js erfolgreich.
  • go test ./... wurde zusätzlich gegen lokale Compile-Stubs für chi, gorilla/websocket und modernc.org/sqlite ausgeführt, um alle Neural-Hunt-Packages inklusive internal/server/watermark_test.go ohne Netzwerkzugriff zu kompilieren.
  • watermark_test.go prüft Traversal-Abwehr, SVG-Wasserzeichen und Raster-Wasserzeichen.
  • Die erweiterten Leaderboard-/Artifact-SQL-Abfragen wurden gegen das reale schema.sql mit Python sqlite3 ausgeführt.

V2.4 Scale smoke test

node --check internal/webui/dist/app.js
go test ./internal/runtime ./internal/ws ./internal/server ./cmd/loadtest

# Server in Terminal 1
go run ./cmd/server

# Start small, then increase.
go run ./cmd/loadtest -url http://127.0.0.1:8080 -clients 250 -ramp 10s -duration 1m -max-nodes 100
go run ./cmd/loadtest -url http://127.0.0.1:8080 -clients 1000 -ramp 30s -duration 2m -max-nodes 100

Im Admin unter /admin sollten dabei Guess/s, Improve/s, SQLite W/s, WS Frames/s, WS MB/s, Drops/s, Goroutines und Heap MB live aktualisiert werden. Bei einem stabilen Test sollten Drops/s nahe 0 bleiben. Ein niedriger SQLite W/s relativ zu Guess/s bestätigt, dass verlierende Tipps den DB-Hotpath nicht mehr belasten.

V2.5.2 Admin form stability regression

The periodic 3-second admin telemetry refresh must never rebuild #settingfields. Only explicit task/tab changes or completed admin actions may refresh the control plane.

Manual regression:

  1. Open /admin and select ARTIFACT.
  2. Open the Provider or Quality native select and leave it open for more than 6 seconds.
  3. The dropdown must remain open while Overview/Performance counters continue updating.
  4. Type into Prompt-Zusatz for more than 6 seconds; caret position and textarea scroll position must not jump.
  5. Switch tabs and back; the draft value must still be restored.

Static/syntax checks used for this release:

node --check internal/webui/dist/app.js
go test ./internal/webui ./internal/core ./internal/auth ./internal/artifact ./internal/settings

RIFT Medium + OpenAI usage/cost telemetry

  • Start with ARTIFACT_PRESET=raccoon_full_art_v1 and no explicit ARTIFACT_QUALITY: the effective quality must be medium.
  • Generate one RIFT winner artifact and verify that the OpenAI request sends quality=medium.
  • Verify that artifact_api_usage receives one artifact row per successful winner-image API call and a character_anchor row when the canonical anchor is created. A successful call is logged even if the provider omits its optional usage block; in that case token counts remain zero and estimated_cost_usd is NULL.
  • When OpenAI returns usage data, verify that input_tokens, text/image input split, output_tokens, total_tokens, estimated_cost_usd, and pricing_basis are persisted and mirrored in the artifact manifest/provider metadata.
  • In Admin → Artifact, verify KOSTEN HEUTE, Ø KOSTEN PRO KARTE, KOSTEN PRO 1.000 KARTEN, and the recent-call table. Anchor cost belongs to today's total but must not affect the per-card average.
  • Verify GET /api/admin/artifact/usage?day_start_ms=<local-midnight-ms> returns the same aggregates.

RIFT V2.8 — per-task style references + manual anchor

  • In Admin → ARTIFACT, with OPENAI_API_KEY configured and no existing _collection/character_anchor.png, click RIFT-ANCHOR JETZT ERZEUGEN. Verify exactly one OpenAI image-generation request is made, the file is stored at data/artifacts/_collection/character_anchor.png, the usage row has kind=character_anchor, and the UI changes to LOCKED without an overwrite button.
  • Verify a second direct POST /api/admin/artifact/character-anchor returns HTTP 409 while the anchor exists.
  • In Admin → TASK ACTIONS upload a JPEG/PNG style reference. Verify it is stored content-addressed under data/artifacts/_styles/, tasks.nft_style_reference receives only the basename, and the admin preview shows the uploaded image.
  • Verify the public Task landing card displays /api/public/tasks/<id>/style-reference and marks a custom task as TASK STYLE; tasks without an upload display the bundled default reference.
  • Complete a task and verify its successor inherits nft_style_reference.
  • Generate a RIFT winner card and inspect the multipart OpenAI edit request: image[] must contain two files in this order: character_anchor.png, then the task style reference. Provider metadata should contain reference_mode=character-plus-task-style, the character-anchor hash and the style-reference hash.
  • Use AUF DEFAULT ZURÜCK and verify the task DB reference is empty and generation falls back to internal/artifact/assets/style_reference.jpg without deleting shared content-addressed style files.

V3.1 — Admin cleanup for stale non-winner profiles

  • In Admin → RUNTIME set e.g. 30 Tage and click PRÜFEN. Verify the preview reports only clients whose clients.last_seen is older than the cutoff, that are not currently connected, and that have never appeared as tasks.winner_client_id.
  • Keep an old client connected via WebSocket: it must be reported as aktuell verbunden geschützt and never be deleted.
  • Create an old winner identity: it must be reported as Gewinner geschützt and never be deleted, regardless of age.
  • Confirm deletion and verify the client row is removed together with cascading task_points, client_unlocks, and client_task_selection rows.
  • Verify a recent non-winner remains untouched.
  • Verify WebSocket connect and disconnect update clients.last_seen, so a long-running session starts its inactivity window at disconnect rather than at its original login.
  • The API rejects cleanup windows shorter than one hour.

Relevant automated tests: internal/data/profile_cleanup_test.go and internal/server/profile_cleanup_test.go.