Portfolio-Website verifizieren
Status: Launch, Diagnose, Bereinigung und ein erster Satz von Abläufen sind live erprobt (2026-10-02, getestet 82ec737, chrome-devtools-axi, echtes WebGL2 auf Apple M3 Pro). Die Abdeckung ist partiell: Die Zeile Letzter Live-Nachweis: in jeder features/*.md-Datei gibt genau an, was ausgeführt wurde und was nicht. Ein Feature, dessen Zeile none lautet, wurde nie getrieben. Nichts hier ist „verifiziert“, nur weil diese Datei es beschreibt.
Nur manueller Trigger (Benutzerregel, 2026-10-02): Dieser Skill und PStack laufen nur, wenn der Benutzer explizit um Verifikation bittet. Ein Commit, Push, PR oder das Aktivieren eines Modus startet sie nicht, und nichts hier darf in einen Git-Hook, ein Paket-Lebenszyklus-Skript, einen CI-Job oder einen Zeitplan eingebunden werden. Die Frontmatter setzt disable-model-invocation: true, sodass der Agent sie nie selbstständig aufgreift. Starten Sie sie von Hand: Claude Code /verify; Codex $verify, wenn Codex .agents/skills/verify entdeckt; jeder andere Agent: Lesen Sie diese Datei und führen Sie die folgenden Schritte explizit aus. Audit der automatischen Auslöser am 2026-10-02, keiner startet einen Browser: .husky/pre-commit (lint-staged, Konfig .lintstagedrc: eslint und prettier auf gestageten Dateien), .husky/commit-msg (commitlint), package.json prepare (husky), .github/workflows/ci.yml (type-check, lint, fmt:check, vitest, build, budget). test:e2e und visual-baseline sind nur manuelle Skripte. Die core.hooksPath dieses Checkouts zeigt auf ein Verzeichnis außerhalb des Repos, nicht auf .husky.
Die Browsernutzung ist nur für einen expliziten Verifikationsdurchlauf autorisiert (der Durchlauf vom 2026-10-02 wurde vom Kapitän autorisiert und ersetzte die vorherige Browser-Sperre). Die Drive-Rezepte sind als Benutzeraktionen und beobachtbare Ergebnisse geschrieben, sodass sie mit chrome-devtools-axi oder jeder anderen Browser-Fähigkeit ausgeführt werden können.
Jedes offene Problem, jede Hypothese und jede Lücke im Live-Nachweis befindet sich in einem zentralen Ledger: docs/verification/verification-issues.md. Feature-Dateien verlinken darauf und wiederholen es nicht. Lesen Sie features/README.md für die Karte, bevor Sie etwas treiben.
Wie die Oberfläche aussieht
Eine Next.js 16 App (App Router, proxy.ts, statisches Vorab-Rendering, React Compiler). Elf Live-Editionen teilen sich ein Inhaltsmodell und einen Routensatz; die Edition des Besuchers bestimmt das Aussehen. Der Proxy schreibt /<path> nach /f/<edition>/<path> um; / zeigt den Auswähler (/flavors), bis das Cookie hr_flavor eine Live-Edition-ID enthält. NEXT_PUBLIC_FLAVOR=<id> fixiert einen Build auf eine Edition. Die Editionsliste ist flavors/registry.ts. Die Routenliste pro Edition ist content/site.ts pages plus /owner, /projects/<slug>, /lab/<slug>, /ask/<slug>, /ask/page/<n>, /md/*-Mirrors, /llms.txt, /sitemap.xml, /robots.txt.
Dies ist ein Next.js mit bahnbrechenden Änderungen. Bevor Sie App-Code berühren, lesen Sie die passende Anleitung in node_modules/next/dist/docs/ (die AGENTS.md des Repos sagt dies).
Vorhandenes Testgerüst (wiederverwenden, nicht duplizieren)
playwright.config.ts und e2e/*.spec.ts decken bereits den meisten Shell-Betrieb ab. Ein Verifikationsdurchlauf treibt die Live-Site für das, was sie nicht beweisen, und zitiert sie für das, was sie beweisen. Kopieren Sie niemals eine e2e-Assertion in eine Feature-Datei als zweite Suite.
| Vorhandene Abdeckung | Wo | Was es beweist |
|---|---|---|
| Build-Ausgabe ist vorgerendert | e2e/static-routes.spec.ts (Projekt build) | keine öffentliche Route wird pro Anfrage gerendert, keine zeitbasierte Revalidierung |
| Minimale maßgeschneiderte Suite | home, navigation, ask, lab, motion, preferences, print, disclosure, command-menu, link-preview, markdown-Specs, Projekte desktop und mobile | Minimal nur (Cookie hr_flavor=minimal) |
| Maßgeschneiderte Suite für Drawing Set | e2e/drawing-set.spec.ts, Projekte desktop-drawing-set, mobile-drawing-set | Blattindex, Befehlsmenü, Customize-Persistenz, /now-Log, kein Überlauf bei 768 |
| Geteilte Shell für die anderen neun | editions.spec.ts, a11y.spec.ts, command-dialog.spec.ts, Projekte desktop-<id> und mobile-<id> | jede Route 200 mit einer h1, Edition 404, Befehlsmenü, Customize-Design, Header-Design-Umschalter, axe in Hell und Dunkel mit reduzierter Bewegung, Befehlsdialog-Rad und Tastatur-Verträge |
Diese Suiten laufen mit bun run test:e2e und starten ihr eigenes bun run build && bun run start -p 3020 (reuseExistingServer: true außerhalb von CI, sodass ein bereits auf 3020 laufender Prozess stillschweigend wiederverwendet wird). Sie sind Browser-Automatisierung: führen Sie sie nur auf Anfrage aus, mit einem Worker, und stellen Sie sicher, dass 3020 frei ist. Sie wurden am 2026-10-02 nicht ausgeführt. Ihr Bestehen oder Nichtbestehen ist kein Beweis für etwas, das diese Karte als Lücke markiert (siehe das Ledger).
Nicht-Browser-Tore, die existieren: bun run lint, bun run type-check, bun run test (vitest), bun run fmt:check, bun run check:identity, bun run budget (nach einem Build). Ihre Ausführung ist erlaubt und sagt nichts über das UI-Verhalten aus.
Start
Ein Server pro Aufgabe, auf einem aufgabenspezifischen Port, gestartet aus einem Produktions-Build, weil die e2e-Konfiguration und static-routes.spec.ts dies voraussetzen (next dev ist nicht Teil dieses Plans).
.agents/skills/verify/scripts/doctor.sh # Umgebungs- und Baum-Hygiene, kein Server nötig
.agents/skills/verify/scripts/serve.sh start 3071 # Build, Start, warten auf Bereitschaft, PID-Datei schreiben
.agents/skills/verify/scripts/doctor.sh 3071 # jetzt auch die laufende Instanz prüfen
serve.sh start macht genau dies: Weigert sich, wenn der Port belegt ist, führt bun run build und bun run start -p <port> aus, wobei alle Sanity-, Ask- und Flavor-Variablen nicht gesetzt sind (damit die Site den gebündelten Fallback-Inhalt rendert und keine CMS-Aufrufe tätigt), zeichnet die Server-PID in $RUN_DIR/server.pid auf und wartet, bis GET /flavors mit 200 antwortet. Ports 3000 und 3020 werden abgelehnt (3020 gehört zur Playwright-Konfiguration). Ein Build überschreibt .next; starten Sie nicht zwei Läufe in einem Checkout.
Bereit bedeutet alles von: serve.sh hat ready ausgegeben, GET /flavors ist 200, und GET / mit dem Cookie hr_flavor=minimal ist 200 und enthält ein <h1>. Treiben Sie nichts, das nicht alle drei erfüllt.
Abbau: .agents/skills/verify/scripts/serve.sh stop 3071 (siehe Bereinigung).
Diagnose
.agents/skills/verify/scripts/doctor.sh [port] ist schreibgeschützt. Es antwortet „Ist diese Instanz es wert, getrieben zu werden, und ist sie sicher“. Es schlägt fehl (exit 1), wenn einer dieser Punkte zutrifft:
- Eine
.env,.env.local,.env.development*,.env.production*-Datei existiert im Repository-Stammverzeichnis (Next würde Sanity- oder Ask-Geheimnisse laden und der Drive könnte in einen echten Datensatz schreiben). - Eines von
NEXT_PUBLIC_SANITY_PROJECT_ID,SANITY_API_READ_TOKEN,SANITY_API_WRITE_TOKEN,SANITY_REVALIDATE_SECRET,ASK_COOKIE_SECRET,ASK_OWNER_PASSPHRASE,NEXT_PUBLIC_FLAVORist in der aufrufenden Shell gesetzt. HEADist nicht der Commit, den der Lauf behauptet, oder der Baum ist schmutzig (es gibt beides aus).- Mit einem Port: Der Port gehört nicht der PID in
$RUN_DIR/server.pid,/flavorsist nicht 200,/api/visitsist nicht 503 (es muss 503 sein: so beweist der Fallback-Build, dass der Besucherzähler nicht in ein CMS schreiben kann), oder/mithr_flavor=minimalhat kein<h1>.
Führen Sie es zuerst aus, wenn etwas seltsam erscheint.
Voraussetzungen, die ein Lauf angeben muss
- Inhalt: gebündelter Fallback (
content/fallback/), die Standardeinstellung. Ein Lauf gegen ein konfiguriertes Sanity-Projekt ist ein anderer Lauf mit Eigentümergenehmigung, einem einmaligen Datensatz und einem schreibgeschützten Token; siehe features/cms-prerequisites.md. Kein Lauf darf in ein CMS schreiben, Eigentümerinhalte ändern, bereitstellen oder Anmeldeinformationen berühren. - Viewports: Desktop 1440x900 und Telefon (Playwrights „Pixel 7“-Profil: Touch, grober Zeiger, kein Hover), die beiden, die die e2e-Konfiguration verwendet. Hell und Dunkel. Bewegung an und
prefers-reduced-motion: reduce. - Speicher: Starten Sie jeden Editionsdurchlauf mit einem leeren Profil und nur dem Cookie
hr_flavor=<id>(was die e2estorageStatetut). Verwenden Sie niemals eine gemeinsame authentifizierte Browser-Sitzung. - Szenen-Stufe: Die Szenen-Stufe folgt WebGL2,
Save-Data,prefers-reduced-data,deviceMemoryund Zeiger (lib/scene/tier.ts). Zeichnen Sie die Browser-Stufensignale mit jedem Szenen-Nachweis auf. Ein kopfloser Browser ohne GPU beweist T0 und das Poster, nicht die 3D-Darstellung.
Fahren
Browser: chrome-devtools-axi mit eigener Sitzung, eigenem Port und isoliertem Profil; niemals automatisch mit dem Chrome des Benutzers verbinden. Bewährte Einrichtung (2026-10-02):
export CHROME_DEVTOOLS_AXI_SESSION=<einzigartiger-Aufgabenname> CHROME_DEVTOOLS_AXI_PORT=<freier Port> CHROME_DEVTOOLS_AXI_AUTO_CONNECT=0
export CHROME_DEVTOOLS_AXI_MCP_PATH="$(npm prefix -g)/lib/node_modules/chrome-devtools-mcp/build/src/bin/chrome-devtools-mcp.js" # vermeidet den npx-Bootstrap
export CHROME_DEVTOOLS_AXI_HEADED=1 CHROME_DEVTOOLS_AXI_CHROME_ARGS="--enable-gpu --ignore-gpu-blocklist" # echtes WebGL2; headless beweist nur das Poster
chrome-devtools-axi emulate --viewport "1440x900x2" # Desktop; "412x915x2.625,mobile,touch" für das Pixel 7 Profil
chrome-devtools-axi emulate --color-scheme dark|light
# reduzierte Bewegung: Bridge neu starten (`chrome-devtools-axi stop`) mit --force-prefers-reduced-motion, an CHROME_ARGS angehängt
chrome-devtools-axi run <<'EOF' ... EOF # skriptgesteuerte Durchläufe; Bridge am Ende stoppen
Tool-Notizen vom Lauf: In run-Skripten wirft page.wait(ms) „fn is not a function“, also schlafen Sie mit await new Promise(r=>setTimeout(r,ms)); process.env ist dort nicht verfügbar, setzen Sie Werte in den Skripttext ein; hr_flavor kann nicht aus document.cookie gelöscht werden, also wählen Sie eine Edition durch Öffnen von /?flavor=<id>; emulate hat kein Flag für reduzierte Bewegung; ein Zeigerklick auf Press‘ visuell verstecktes Paper-Radio war zeitüberschreitend (Tastatur PfeilRechts funktionierte, WEB-H8); der zshz-Hook dieser Shell gibt bei cd einen Wert ungleich Null zurück, also verwenden Sie absolute Pfade. Jede Feature-Datei unter features/ listet die Aktionen, stabilen Handle und beobachtbaren Endzustand auf. Handles in der Reihenfolge der Präferenz: ARIA-Rolle und zugänglicher Name, Routenpfad, html[data-theme], html[data-motion], html[data-scene], [data-scene-poster], der hr.*.prefs-localStorage-Key pro Edition (e2e/support/site.ts prefsKeyFor). Keine Koordinaten.
Beweisstandards:
- Üben Sie die echte Route und das echte Steuerelement aus, nicht einen Store-Setter. Bevorzugen Sie das sichtbare Steuerelement gegenüber
localStorage-Bearbeitungen; verwenden Sie Speicher nur, um einen Startzustand einzurichten, den die Feature-Datei benennt. - Erfassen Sie die Aktion und den Zustand danach: einen ARIA-Snapshot und einen Screenshot für die Benutzeroberfläche, den Antwortstatus und die Header für HTTP-Prüfungen, die Konsole und das Protokoll fehlgeschlagener Anfragen für jeden Durchlauf.
- Ein erfolgreicher Unit-Test oder e2e-Test ist kein Beweis für einen nicht ausgeführten Ablauf. Markieren Sie das Feature
Letzter Live-Nachweis:erst, nachdem der echte Ablauf gelaufen ist, mit Datum, Commit und Beweispfad. - Melden Sie einen nicht erreichbaren Pfad mit dem versuchten Schritt und der nicht erfüllten Vorbedingung. Melden Sie keinen übersprungenen Einstiegspunkt als über einen anderen verifiziert.
Beweise
Verzeichnis: $EVIDENCE_DIR, Standard $HOME/.verify-evidence/website/<run-id>/, wobei <run-id> gleich <UTC-Zeitstempel>-<kurzes HEAD> ist. Layout: doctor.txt, server.log (kopiert von $RUN_DIR), dann <feature-id>/<step>.aria.txt, <step>.png, console.txt, network.txt. Nach einem Durchlauf fügen Sie eine Zeile zur Letzter Live-Nachweis:-Zeile der Feature-Datei hinzu (Datum, Commit, Beweispfad) und eine Zeile zum Ledger. Kopieren Sie $RUN_DIR/server.log in das Beweisverzeichnis, bevor Sie stop ausführen, da stop $RUN_DIR entfernt. Beweise überdauern die Bereinigung und werden von diesem Skill niemals gelöscht.
Bereinigung
.agents/skills/verify/scripts/serve.sh stop <port> tötet nur die PID in $RUN_DIR/server.pid (und die von ihr gestarteten Kindprozesse), entfernt dann $RUN_DIR. Es tötet niemals nach Prozessnamen und berührt niemals einen Prozess, den es nicht gestartet hat. Es lässt .next (ein Build-Artefakt, das der Checkout bereits ignoriert) und $EVIDENCE_DIR in Ruhe. Wenn die PID-Datei fehlt, meldet es dies und tötet nichts. Führen Sie es nach einem fehlgeschlagenen Lauf vor einem Wiederholungsversuch aus, damit kein Port belegt bleibt.
$RUN_DIR ist ${TMPDIR:-/tmp}/website-verify-<port>; es enthält nur die PID-Datei und das Serverprotokoll.
Helfer
scripts/doctor.sh [port]: Die obige schreibgeschützte Prüfung. Exit 0 gesund, 1 nicht fahrwürdig.scripts/serve.sh start <port>undscripts/serve.sh stop <port>: Start und Abbau wie oben.
Beide sind ausführbar und verwenden nur bash, curl, lsof, git und bun.