Paritäts-Gates
Erstelle die Baseline einmal aus capture/ und prüfe dann jeden Build dagegen, bis jedes Gate bestanden ist. Die Gates lesen nur baseline/, niemals die Live-Site, sodass ein Build auch nach dem Abschalten des alten Hosts noch verifiziert werden kann.
Die goldene Regel
Der Standard-Build entspricht der Live-Site, und ein Gate wird niemals abgeschwächt. Kein Flag verwandelt einen Fehler in eine Warnung. Vier weitere, die daraus folgen:
- Ändere niemals
baseline/von Hand. Die eine Ausnahme:keepinbaseline/scripts.json, womit ein Anbieter entfernt wird (setze es auffalseund dokumentiere die Entscheidung). - Ein Unterschied ist ein Eintrag, keine Bearbeitung. Unvermeidbar:
exceptions.json. Eine Verbesserung:proposals.json, nur aktiv mitPROPOSALS=on. Beide sind inreferences/exceptions.md. - Ein Überspringen ist kein Bestehen. Ein Gate, das etwas nicht prüfen konnte, sagt
N übersprungen (Grund)in seiner Zusammenfassungszeile. Melde jedes Überspringen. - Melde ein falsches Gate als Kit-Fehler; ändere niemals das Gate in der Site, noch die Baseline.
Ausführen der Skripte
Eine von convert-site erstellte Site hat die Skripte in scripts/; führe sie vom Site-Root aus über die untenstehenden npm-Skripte aus, Optionen nach --. Außerhalb einer gerüsteten Site führe die unter jedem Schritt gezeigte node-Form vom Site-Root aus, wobei <skill-dir> der absolute Pfad dieses Skill-Ordners in einer Kopie des Kits ist, in der npm install ausgeführt wurde. Jedes Skript gibt --help aus; führe es aus, anstatt den Quellcode zu lesen. Exit 0 bestanden, 1 fehlgeschlagenes Gate oder Drift, 2 Verwendung oder fehlende Eingabe.
1. Baseline (einmalig)
npm run baseline
node <skill-dir>/scripts/build-baseline.mjs --capture capture --out baseline # Fallback
Es benötigt capture/inventory.json, media.json (capture's media.mjs) und templates.json (templates.mjs) und beendet sich mit Exit 2 und nennt den auszuführenden Schritt, wenn eines fehlt. Es schreibt baseline/{routes,seo,redirects,media,forms,scripts,meta,counts}.json und baseline/text/ sowie redirects.csv im Site-Root. Ein Shortlink ohne Ziel wird ausgelassen und auf stderr genannt. Jeder Zwischen-Hop einer erfassten Kette bekommt eine eigene Zeile direkt zum endgültigen Ziel (/old-services → /old-services/ → /services/ ergibt auch /old-services/,/services/, beachte hop of /old-services), es sei denn, dieser Hop ist selbst eine gebaute Route, sodass ein Link zu jeder URL der Kette in einem Hop landet.
Commite baseline/ und redirects.csv zusammen. --check zählt baseline/ gegen counts.json (Exit 1 bei Drift). Die Form jeder Datei ist in references/contracts.md.
2. Weiterleitungen
redirects.csv (from,to,status,source,note) ist die einzige Quelle der Site-Weiterleitungen. source ist crawl, sitemap, shortlink oder seed aus der Erfassung; eine von dir hinzugefügte Zeile ist decision, ihre note benennt die Entscheidungs-ID. Bearbeite niemals die kompilierte Ausgabe von Hand; kompiliere:
npm run redirects:build
node <skill-dir>/scripts/build-redirects.mjs --csv redirects.csv --host vercel --out vercel.json --trailing-slash always # Fallback
--host cloudflare --out public/_redirects für Pages (Astro kopiert es in dist/). Vercel: Der Schlüssel redirects wird ersetzt, jeder andere Schlüssel bleibt erhalten, und trailingSlash wird entfernt und als eigene 308-Slash-Regeln des Compilers nach denen der Site geschrieben, sodass eine ungeslashte Quelle immer noch ein Hop ist. Nur ein Pfad, der auf eine statische Dateierweiterung endet, zählt für diese Regeln als Datei, in beliebiger Groß-/Kleinschreibung: die Web-Typen, die Dokument-, Medien- und Archivtypen, die ein Upload-Ordner enthält (docx, xlsx, csv, mov, wav, heic, gz, ...), und jede Erweiterung, die in dist/ (sonst public/) gefunden wird; führe es daher nach dem Build erneut aus; /upgrade-guide/3.5/ ist eine Seite und behält seinen Slash. Eine gebaute Datei, die die Regeln dennoch umleiten würden, führt dazu, dass das Weiterleitungs-Gate als built file redirected fehlschlägt.
Cloudflare: Eine Abfragezeile (/?p=7) kann nicht von _redirects abgeglichen werden und geht an cloudflare-query-redirects.csv, das als Single Redirect erstellt werden muss (ein „braucht dich“-Eintrag). Eine Abfragezeile, deren Ziel ihr eigener Pfad ist (/?p=2 zu /), ist ein No-Op und wird auf beiden Hosts ausgelassen.
Eine erfasste Zeile (beliebige source außer decision) ist eine Live-URL und enthält keine Parameter: Für Vercel werden jedes : und * darin escaped (/foo:bar/ wird /foo\:bar/ geschrieben, und ebenso /trackshttps://www.example.com/x/, ein defekter Live-Href, dem die Erfassung gefolgt ist); // bleibt erhalten. Nur eine decision-Zeile verwendet :name-Parameter und *-Splats, und selbst dort wird ein : vor einer Ziffer (einem Port) escaped. Vercel lehnt ein bloßes : ab, und ebenso die Simulation der Gates. Eine Quelle ohne gültige Form (kein führendes /, Leerzeichen, ein Steuerzeichen; bei Cloudflare auch ein erfasstes :<name> oder *, das _redirects nicht escapen kann) wird verworfen, auf stderr genannt und als { source, reason } in redirects-skipped.json aufgelistet. Diese Datei liegt neben redirects.csv (Site-Root), niemals unter public/, wird also nicht deployed. Das Weiterleitungs-Gate und verify-live zählen eine aufgeführte Zeile als übersprungen, niemals als bestanden. Wenn der Pfad einfach keine Weiterleitung haben soll, erfasse stattdessen eine „keine Weiterleitung“-Ausnahme (Abschnitt 4): { "kind": "redirect", "path": "<source>", "reason": "...", "action": "none", "approvedBy": "...", "date": "..." }.
3. Verifizieren
npm run build
npm run verify -- --endpoint https://forms.example.com/f/abc --thank-you /thank-you/
node <skill-dir>/scripts/verify/run-all.mjs --endpoint https://forms.example.com/f/abc --thank-you /thank-you/ # Fallback
run-all führt die zehn Gates in alphabetischer Reihenfolge aus, gibt jedem nur die Optionen, die es akzeptiert, und stoppt beim ersten Fehler. Gemeinsame Optionen: --paths (Komma-Liste, * matcht alles), --json, --origin (Links, SEO, Sitemaps: der Host, für den der Build ist), --allow-extra (Routen), --endpoint, --honeypot, --thank-you (Formulare; --endpoint ist erforderlich, wenn die Baseline ein POST-Formular hat), --host, --config (Weiterleitungen, Links), --csv (Weiterleitungen), --media-plan (Medien). Behebe den ersten Fehler, baue neu, führe erneut aus. Ein einzelnes Gate: node <skill-dir>/scripts/verify/<gate>.mjs.
| Gate | Besteht, wenn | Ein Überspringen bedeutet |
|---|---|---|
forms | Jedes Live-Formular ist auf seiner Seite mit denselben Feldnamen in Reihenfolge und Methode; ein POST-Formular-Action ist --endpoint und es trägt --honeypot; ein GET-Formular (ein Suchfeld) behält den Action-Pfad der Live-Site und benötigt weder noch („N search/GET forms compared“); ein POST-Formular, dessen Live-Action auf einer anderen registrierbaren Domain liegt (ein Newsletter-Listen-Host; www, http, Subdomains und WordPress-Handler wie admin-ajax.php oder ?wpcf7 zählen als die Site), wird so belassen, wie es ist, wie ein GET-Formular anhand seiner vollständigen Action-URL verglichen und benötigt kein --endpoint („N forms kept as is (posts to )“) | Kein --thank-you: Die Dankesseite der POST-Formulare wurde nicht geprüft |
headers | Die Host-Konfiguration sendet nosniff, Referrer-Policy, X-Frame-Options oder CSP frame-ancestors auf jedem Pfad, und, wenn nicht indexierbar, X-Robots-Tag: noindex auf jedem Pfad oder (Vercel) das Meta-Robots-noindex auf jeder gebauten Seite; eine Preview-Host-Regel (https://*.pages.dev/*) zählt nur für den Preview-Host; mit PUBLIC_INDEXABLE=true ist noindex auf jedem Pfad verboten | |
links | Jeder interne href und src löst zu einer gebauten Seite oder Datei, einer Weiterleitungsquelle oder Baseline-Medien auf oder landet auf einer gebauten Seite in einem Hop durch die kompilierten Regeln (vercel.json oder dist/_redirects: die Slash-Regeln und jede redirects.csv-Zeile), wie es live weitergeleitet hätte („N links resolved through redirects“); zwei Hops oder ein fehlendes Ziel schlagen fehl; ohne Host-Konfiguration schlägt /about, wo der Build /about/ ausliefert, fehl | |
media | Jede Baseline-Medien-Datei wird vom Build mit denselben Bytes ausgeliefert (--paths wählt eine Datei anhand ihres Pfads oder einer Seite, die darauf verweist): in dist/ im Plan-Modus repo; unter dem prefix des Plans, im Store-Manifest (store) oder noch auf Live (live-temporary); außerhalb des Prefix, in dist/ in jedem Modus. Mit PUBLIC_INDEXABLE=true schlägt live-temporary für jede Datei unter dem Prefix fehl (ein Release-Build darf keine Medien von der Live-Site ausliefern; ein Plan ohne Prefix deckt jede Datei ab) und prüft dennoch die Dateien außerhalb davon in dist/ | Plan-Modus live-temporary bei einem Staging-Build: Dateien unter dem Prefix werden von Live ausgeliefert, nicht geprüft |
redirects | Jede Baseline-Weiterleitung und CSV-Zeile antwortet in einem Hop mit demselben Status, und das Ziel antwortet mit 200 in dist/ (oder ist extern, oder unter einem Prefix in der Baseline meta.json excluded: dann wird nur der erste Hop geprüft); keine Quelle ist auch eine gebaute Datei; keine gebaute Seite oder Datei wird von ihrer eigenen URL weg umgeleitet (built page redirected by rule <rule>; keine Ausnahme deckt es ab, korrigiere die Regel); ein Pfad mit einer „keine Weiterleitung“-Ausnahme (kind: "redirect", action: "none") wird überhaupt nicht umgeleitet | Eine No-Op-Abfragezeile, jede Abfragezeile auf Cloudflare oder eine Quelle ohne gültige Form, die redirects-skipped.json mit einem Grund auflistet (not compiled) |
routes | Jede Seite, jeder Beitrag, jedes Archiv und jeder Feed unter 200 wird gebaut, noindex-Routen sagen immer noch noindex, nichts Zusätzliches wird gebaut (die eigenen Skripte der Erfassung in baseline/js.json und Stylesheets in baseline/css.json unter ihren Live-Pfaden, die Live-Sitemap-Namen in baseline/sitemaps.json und das Launch-Icon-Set sind keine Extras); eine Route, die mit einem anderen Status als 200, 3xx, 404 oder 410 erfasst wurde, schlägt fehl als not captured: <status>, es sei denn, eine routes-Ausnahme überspringt sie oder nennt ihren gebauten Ersatz | Eine routes-Ausnahme mit to: "skip": Diese Route wurde nie erfasst |
scripts | Jeder behaltene Anbieter ist genau auf seinen Live-Seiten mit denselben IDs; ein entfernter auf keiner; kein neuer Anbieter | |
seo | Titel, Beschreibung, Canonical, Robots, Lang, h1, h2, og und JSON-LD @types sind pro Seite gleich; Site-URLs auf dem Ursprung der Site. Sofern nicht PUBLIC_INDEXABLE=true, muss Robots das Staging-noindex, nofollow tragen und der Rest davon muss dem Live-Wert abzüglich dieser beiden entsprechen; ein Release-Build vergleicht Robots exakt | |
sitemaps | Jede Top-Level-Sitemap in dist/ (Astros sitemap-index.xml oder ein Live-Name in baseline/sitemaps.json wie wp-sitemap.xml oder sitemap_index.xml) listet genau die indexierbaren 200-Seiten auf dem Ursprung auf (Prozent-Escapes werden case-blind verglichen: %c3 ist %C3); jede Sitemap:-Zeile in robots.txt ist auf dem Ursprung und nennt eine Datei in dist/, oder ist eine Zeile, die die Live-robots.txt (capture/robots.txt) wortwörtlich trug; jeder Feed ist mit so vielen Einträgen gebaut | |
text | Der sichtbare Text jeder Seite entspricht baseline/text/ (Wort-Diff, 5 Wörter Kontext) |
Eine Erfassung, die mit --exclude erstellt wurde, zeichnet ihre Pfad-Präfixe in baseline/meta.json excluded auf: Das links-Gate prüft keinen Link darunter (wie einen Link zu einem anderen Host, vermerkt als „N links under excluded paths ... not checked“), und das sitemaps-Gate akzeptiert eine Sitemap:-Zeile in robots.txt darunter, wenn die Live-robots.txt sie wortwörtlich trug (die Sitemap einer Multisite-Subsite auf demselben Host).
4. Unterschiede und Entscheidungen
Wenn der Build nicht mit der Live-Site übereinstimmen kann oder soll, lies references/exceptions.md. Kurz gefasst: Ein Eintrag ist { path, field, from, to, reason, approvedBy, date }; from: "" zeichnet einen Wert auf, den der Build hinzufügt, to: "" einen, den er entfernt; eine Ausnahme, die nicht mehr zutrifft oder einen Pfad nennt, den das Gate nicht prüft, lässt das Gate fehlschlagen. Jede Besonderheit auf der Live-Site (eine fehlende H1, ein toter Tag, ein defekter Link) wird standardmäßig reproduziert und erhält eine Entscheidungszeile (ID, Thema, Wahl, Standard, Grund, Kosten bei Fehler), die dies besagt und wie die Korrektur aussehen würde.
Ein Datensatz hat ein kind anstelle eines field: { "kind": "redirect", "path": "<source>", "reason": "...", "action": "none", "approvedBy": "...", "date": "..." } bedeutet „keine Weiterleitung für diesen Pfad, absichtlich“ (eine Live-Weiterleitung, die für einen defekten Href aufgezeichnet wurde, den nichts umleiten sollte). Jeder Schlüssel ist erforderlich: Es entfernt ein Live-Verhalten, wird also wie jede Ausnahme freigegeben. Das Weiterleitungs-Gate erfasst den Pfad und besteht nur, wenn die Regeln ihn nicht umleiten; bei einem Pfad, den das Gate nicht prüft, schlägt es fehl als path not checked; verify-live überspringt ihn mit dem Grund. Jedes andere Gate ignoriert ihn.
5. Staging, Vorschläge und Release-Builds
PUBLIC_INDEXABLE und PROPOSALS ändern, was Astro baut, also setze sie beim Build, nicht nur beim Gate-Durchlauf; ein Gate-Durchlauf bei einem Build, der ohne sie erstellt wurde, prüft die falsche Site. Übergib --origin nur, wenn der Build selbst für diesen Host erstellt wurde; die site eines gerüsteten Builds ist der Live-Ursprung, also bleiben seine Canonicals und Sitemap darauf.
npm run build && npm run verify -- --endpoint ... --thank-you ... # staging
PROPOSALS=on npm run build && npm run verify:proposals -- --endpoint ... --thank-you ... # Vorschläge
PUBLIC_INDEXABLE=true npm run build && npm run verify:release -- --endpoint ... --thank-you ... # Release
Nach einem Staging-Deploy überprüfe es über HTTP gegen die Baseline. Ein Release-Deploy wird auf die gleiche Weise ohne --expect-noindex geprüft:
npm run verify:live -- --base https://my-site.vercel.app --expect-noindex
node <skill-dir>/scripts/verify-live.mjs --base https://my-site.vercel.app --expect-noindex # Fallback
--bypass "$VERCEL_AUTOMATION_BYPASS_SECRET" gilt nur, wenn Staging absichtlich geschützt wurde (der Bypass-Wert aus der Umgebung, niemals in einen Chat eingefügt); ein öffentlicher Staging-Alias benötigt keinen.
Es prüft jede Baseline-Route unter 200 (oder ein --sample), jede Weiterleitung in einem Hop mit der gleichen Art von Status, noindex auf Seiten gdw. --expect-noindex, die Sitemap und 20 Mediendateien per Bytes (oder --media-manifest, dessen url die absolute URL des Stores oder ein Site-Pfad sein kann, der unter <base><path> geprüft wird). Eine in redirects-skipped.json aufgeführte oder durch eine „keine Weiterleitung“-Ausnahme abgedeckte Weiterleitung (--skipped, --exceptions; beide standardmäßig vom Site-Root gelesen) wird übersprungen und mit ihrem Grund genannt. Jede Anfrage timeoutet nach 30 s, ein Fehler dieser Prüfung eher als ein Block. Exit 3 bedeutet, dass es blockiert wurde: warte und führe erneut aus. Exit 3 mit deployment protection: bedeutet, dass Vercel mit seinem Login-Redirect geantwortet hat (302 zu vercel.com/sso-api): verwende den Produktions-Alias des Projekts (standardmäßig öffentlich) anstelle der rohen Deployment-URL; nur wenn Staging absichtlich geschützt war, verwende --bypass.
npm run verify:live -- --base https://my-site.vercel.app --sample 0.1 --bypass "$VERCEL_AUTOMATION_BYPASS_SECRET"
6. Drift zwischen Erfassung und Kit-Updates oder Neu-Erfassungen
baseline/meta.json enthält den Kit-Hash der Erfassung (kitHash) und das Erfassungs-Datum (capturedAt). Das run-all prüft, ob der aktuelle Kit-Hash zu meta.json passt. Ein Unterschied (einschließlich eines Kit-Updates) bedeutet, dass die Baseline mit dem aktuellen Kit neu aufgebaut werden muss: build-baseline --check schlägt fehl. Führe npm run baseline -- --check aus, um zu sehen, ob eine Neu-Erfassung benötigt wird.
Die Gates akzeptieren eine Baseline, die mit einem anderen Kit-Hash aufgebaut wurde, geben aber eine Warnung aus: "baseline built by kit , running kit ". Einige Gates (text, seo, routes) geben zusätzliche Details aus, wenn sich das Format in einer neuen Kit-Version geändert hat.
7. Nach dem Deploy
Nach einem bestandenen Gate-Durchlauf werden baseline/ und redirects.csv und das Kit committet (als Teil der Site, die sie definiert). Ein zukünftiger Entwickler oder ein CI-System klont das Repo und npm run build && npm run verify und erhält denselben grünen Durchlauf.
Dieser Text ist eine Übersetzung der Original-SKILL.md-Datei.