51 KiB
WOMS „Weißes Design“ P10: Aufräumen – Umsetzungsplan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Nach P10 gibt es keine Übergangsschicht mehr. react-icons und @tabler/icons-react sind deinstalliert, die KOMPAT-Regeln, die alten Token-Aliase und alle toten Klassen sind gelöscht, previewEnv.dotColor ist entfernt. Sichtbar ändert sich nichts, das Bundle wird kleiner. Die Umleitung /tickets?woid=N auf /tickets/N bleibt.
Architecture:
- Es wird nur gelöscht, umbenannt oder auf vorhandene Bausteine umgestellt. Die Bilder von
design-p9sind die Referenz, ein Pixelvergleich (vergleich.mjs, gestartet überrun-browser.sh) beweist nach jedem Löschschritt, dass nichts kippt. - Reihenfolge nach Risiko: Pakete,
dotColor, Token-Aliase (reine Umbenennung), KOMPAT, tote Klassen, Inline-Styles und Regelprüfung, Gate und Tag. - Der Wächtertest
tests/unit/hygiene.test.mjshält die Ziele fest (drei Tests, je einer in Task 2, 4 und 5). - Die Ergebnisdatei
docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.mdsammelt die Belege.
Tech Stack: wie P1. Node 24 (readdirSync mit recursive), npm 11, ripgrep 13 ohne PCRE2 (keine PCRE2-Option, keine Lookarounds).
Spec: docs/superpowers/specs/2026-10-04-weisses-design-design.md, Abschnitte „Gestaltungsregeln“, „Design-Tokens“ (Alias-Tabelle), „Übergangsschicht KOMPAT“, „Ticket als eigene Seite / Route und Links“, „Was gleich bleibt“, „Abnahme“ und Zeile P10. Dateidetails im Anhang …-umbaukarte.md, Abschnitt 5 (P10), 2.2, 2.3, 4 (D) und 7. Globale Regeln, Befehlsregeln (env.sh, check.sh, run-browser.sh) und Schnittstellen: 2026-10-05-weisses-design-00-uebersicht.md.
Global Constraints
Jeder Run-Block beginnt mit source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&. Danach gelten $WT (Worktree /home/webklar/apps/ticket.webklar.com/dev-design, Arbeitsverzeichnis), $W (Werkzeug) und $TMPDIR (Scratchpad). Tests und Build laufen nur über "$W/check.sh", Browser-Skripte nur über "$W/shots.sh" oder "$W/run-browser.sh". Suche nur mit rg oder git grep, nie mit dem Shell-grep auf Dateien.
Es gelten die Regeln der Übersicht. Für P10 kommt hinzu:
- Voraussetzung sind die Tags
design-p0bisdesign-p9, alle Diff-Prüfungen vergleichen gegendesign-p9. Erlaubt ist nur Löschen, Umbenennen und Umstellen auf vorhandene Bausteine, keine neuen Funktionen, Klassen, Texte oder Tokens. Ausnahmen: Wächtertest, Ergebnisdatei, das Werkzeug außerhalb des Repos und, nur falls sie fehlt, die Deklarationfont-variant-numeric: tabular-numsan.num,.stat .vund.fin-amount(Task 7 Step 4). Neue Ansichten braucht P10 nicht, das Gate läuft über alle bestehenden. - Nicht angefasst werden zusätzlich: die
?woid=-Umleitung (woidRedirectTargetinlib/ticketListUrl.js,<Navigate replace>inTicketsPage.jsx), der Token-Block der Spec und die Klassen-Hooks aus „Was gleich bleibt“ (data-testid,data-label,data-storage-done,data-hidden-hits). - Klassensuche token-genau mit
(^|[^A-Za-z0-9_-])NAME([^A-Za-z0-9_-]|$).rg -wreicht nicht, weil-als Wortgrenze gilt undcardsonstfin-cardtrifft. git addmit ausdrücklichen Pfaden. Wo ein Schritt viele Dateien ändert, läuft vorhergit diff --name-only, undgit addbekommt genau diese geprüfte Liste.- Entscheidung: Pixelinvariante. Das Aussehen der Bilder von
design-p9gilt, jede Abweichung ist ein Fehler und wird behoben. Ausgenommen sind nur Ansichten mit Rauschen (relative Zeiten wie „vor 5 Minuten“), das ein zweiter Lauf vondesign-p9selbst zeigt. - Entscheidung: Stoppregel für Icons. Liefert
rg "react-icons|@tabler" srceinen Treffer, stammt er aus einem früheren Paket oder aus Commits, die der Rebase vonorigin/testmitbrachte. P10 behebt ihn nach der Ersetzungsregel der Spec (Icon-Knopf wird Textknopf oder Textlink, Zeichen „ד „←“ „→“) in einem eigenen Commit vor Task 2 und nennt ihn in der Ergebnisdatei. - Entscheidung: Die Tokens des Spec-Blocks bleiben, auch ein ungenutztes. Nur die Aliase der Spec-Tabelle fallen,
--sp-1…6bleiben.Buttonbehält die Propsizein der Signatur (Spec „Knöpfe“), Aufrufe mitsize="sm"verschwinden, weil sie nichts bewirken. - Entscheidung: Farbliterale in JSX sind nur in
src/components/Logo.jsx(Markenzeichen,#111und#fffwiepublic/favicon.svg) undsrc/components/serverpuls/chartColors.jserlaubt. Inline-<svg>bleibt nur inLogo.jsxundSparkline.jsx. Der Checkicon-svgnimmtsvg.sp-spark(P9) und.woms-chat .chat-composer *(P0) inchecks.mjsaus, dazu das Gate alles unter.woms-chat(ignore, P6). P10 fügt keine Ausnahme hinzu. - Entscheidung: Beim Umstellen gelten die Regeln „Bausteine benutzen“ der Übersicht und die CSS-Reihenfolge: In jedem
<Dialog as="form">trägt jeder Knopf außer dem Absenden-Knopftype="button", einCardohne Titel und Aktionen rendert keinh2, und Bereichs-CSS (chat.css,serverpuls.css,pages/AdminPage.css) lädt vorglobal.css. Überstimmt eine globale Regel es nach dem Löschen nicht mehr, braucht der Bereichs-Selektor eine höhere Spezifität, nie!important. - Entscheidung: Die Ergebnisdatei hat sieben Abschnitte: 1 Token-Aliase, 2 KOMPAT-Inventur, 3 Tote Klassen, 4 Inline-Styles, 5 Regelprüfung und Invarianten, 6 Bundle, 7 Offene Punkte. Task 4 legt sie mit allen Überschriften an, jeder Task nimmt seinen Abschnitt in seinen Commit auf.
Review Focus
Aus der Übersicht gehört P10 kein Punkt allein. Alle fünf laufen aber als Ansichten im Gate p10 mit (ticket-altdaten*, *-lang*, fehler-*, tasten-*, ticket-viel, tickets-suche) und müssen unverändert bleiben. P10 verantwortet sechs eigene Prüfungen:
- Nichts Sichtbares ändert sich. Pixelvergleich
design-p9gegen P10 über alle Ansichten in allen Viewports (Standard 1440×900 und 390×844, beidlg-*auch 1440×700 und 390×700), keine abweichende Ansicht außerhalb des Rauschens (Task 4, 5, 6 und 8). - Keine noch gebrauchte Regel geht verloren. Jede KOMPAT-Klasse hat eine Inventurzeile mit Nutzerzahl, jeder Restnutzer wird vor dem Löschen umgestellt (Task 5). Kein
var(--…)zeigt ins Leere,undefinedUsedist leer (Task 4). - Die Icon-Pakete fehlen nirgends.
rgmeldet 0 Treffer, der Build ist grün, keinconsole-errorin irgendeiner Ansicht (ein fehlender Import wäre zur Laufzeit einpageerror), das Lock passt zupackage.json(Task 2). - Die
?woid=-Umleitung bleibt. Ansichtalt-linkim Gate, TestwoidRedirectTargetaus P2 grün,TicketsPage.jsxundticketListUrl.jsunverändert (Task 8). - Die Spec-Invarianten halten: alle
data-testid, die Zahl derwindow.confirm, Hooks und Lib-Logik nur wie in den Paketplänen geändert (Task 7 Step 5, Task 8 Review). - Die übergreifenden Gestaltungsregeln gelten: höchstens ein
.btn-primaryje.page-head(Spec-Regel 4, Checkmax-primaryim Gate, Task 1 Step 6 und Task 8) undtabular-numsan Zahlen und Beträgen (Spec-Regel 6,rgin Task 7 Step 4).
Task 1: Ausgangslage, Referenzbilder, Werkzeug
Files (alle unter $W/, kein Commit im Repo):
- Create:
vergleich.mjs,token-check.mjs - Modify:
css-klassen.mjs(Flag--ohne-ausnahmen),checks.mjs(Checkmax-primary),gates.mjs(Gatep10)
Interfaces:
-
Consumes: Tag
design-p9,build.sh,shots.sh,run-browser.sh,check.sh,css-klassen.mjs,farben.mjs,GATES.p9(P0 bis P9). -
Produces:
"$W/run-browser.sh" "$W/vergleich.mjs" <A> <B> [--rauschen <A2>] [--out <Ordner>]→ JSON{ geprueft, anders: [{ view, viewport, diffPixels, bbox }], rauschen: [view], fehlt: [view] }. Exit 1, wennandersoderfehltnicht leer ist. A, B und A2 sind Ausgabeordner vonshots.sh(<w>x<h>/<id>.png, z. B.1440x900/tickets.pngund390x844/tickets.png).node "$W/token-check.mjs" <worktree> [--fix]→ JSON{ legacy: [{ name, ersatz, file, line, art }], undefinedUsed: [{ name, file, line }], mitFallback: [{ name, file, line }], definedUnused: [name] }. Exit 1, wennlegacyoderundefinedUsednicht leer ist.css-klassen.mjs --ohne-ausnahmen: ignoriert die Ausnahmeliste und gibt zusätzlichnurAusnahme: [name]aus, die Klassen, die nur durch die Liste als benutzt gelten.- Check
max-primaryinchecks.mjs: Verstoß{ check: 'max-primary', selector: '.page-head', detail }für jedes sichtbare.page-headmit mehr als einem sichtbaren.btn-primary. GATES.p10nach dem Schema der Übersicht (Step 6).
-
Step 1: Paketstart und Stand prüfen
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git fetch origin && git merge-base --is-ancestor design-p9 HEAD && git rebase origin/test && "$W/check.sh"
git log --oneline origin/test..feature/terminplaner-tp2 -- src package.json package-lock.json tests
git tag --list 'design-p*'; git log --oneline design-p9..origin/test; git status --short
Expected:
-
Erste Zeile:
design-p9ist Vorfahre (sonst Exit 1: stoppen und melden, der Rebase schrieb die Pakete um), der Rebase läuft ohne Konflikt,check.shendet mit Exit 0,# fail 0,# passistN9(notieren). -
Zweite Zeile (Abgleich mit
feature/terminplaner-tp2, P10 berührt fast alle Dateien untersrc): leer. Gibt sie etwas aus, stoppt der Agent und fragt den Eigentümer. Er empfiehlt dabei, TP2 zuerst nachtestzu bringen. -
Tags
design-p0bisdesign-p9,git logundgit statusleer. Kommen fremde Commits mit, werden ihre Dateien in den folgenden Tasks wie alle anderen geprüft. -
Step 2: Voraussetzungen im Werkzeug
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
rg -n "GATES\.p9|p1:" "$W/gates.mjs"; rg -n "ignore" "$W/gates.mjs"; rg -n "sp-spark" "$W/checks.mjs"
ls "$W/check.sh" "$W/run-browser.sh" "$W/css-klassen.mjs" "$W/farben.mjs" "$W/build.sh" "$W/shots.sh"
Expected: Gates p1 und p9, im ignore nur .woms-chat (P6, .ticket-projects strich P5), Ausnahme svg.sp-spark und alle sechs Dateien sind da. Fehlt etwas, wird gestoppt und gemeldet.
- Step 3: Ausgangswerte des Bundles festhalten
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git log design-p0 --format=%B | rg "Ausgangswerte" &&
"$W/check.sh" --nur-build &&
{ find dist -type f \( -name '*.js' -o -name '*.css' -o -name '*.ttf' \) -printf '%s %p\n'; for f in dist/assets/*.js dist/assets/*.css; do echo "$f gzip=$(gzip -9 -c "$f" | wc -c)"; done; wc -l src/styles/*.css src/pages/*.css; } | tee "$W/p10-baseline-p9.txt"
Expected: die P0-Zeile Ausgangswerte: <Testzahl>, JS <x> B, CSS <y> B (Gegenprobe der Umbaukarte: JS 680.818 B, CSS 64.433 B, Lato 96.184 B, 2.079 CSS-Zeilen), Build grün, keine .ttf in dist, alle Zahlen in $W/p10-baseline-p9.txt.
- Step 4: Referenzbilder und Rauschmaß
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p9-ref && "$W/shots.sh" p9-ref "$W/shots/p9-ref" --gate p9 && "$W/shots.sh" p9-ref "$W/shots/p9-ref2" --gate p9 && ls "$W/shots/p9-ref/1440x900" | wc -l
Expected: beide Läufe Exit 0, je Ansicht ein Bild je Viewport (1440x900 und 390x844, bei dlg-* zusätzlich 1440x700 und 390x700). Die Zahl der Ansichten ist die Sollzahl aller späteren Läufe (notieren).
- Step 5:
vergleich.mjsschreiben und prüfen
Umsetzung:
- Das Skript startet Chromium selbst (Ladeweise wie
shots.mjs) und läuft deshalb nur überrun-browser.sh. - Die PNGs werden in Playwright-Chromium (
about:blank) percreateImageBitmapund Canvas dekodiert und pixelweise verglichen. Eine andere Bildgröße istandersund nennt beide Größen.bboxist der kleinste Rahmen um alle abweichenden Pixel. --outbekommt je abweichender Ansicht ein Bild unter<w>x<h>/<id>.png, abweichende Pixel rot.- Eine Ansicht mit Abweichung zwischen A und A2 zählt als
rauschen, außer die Abweichung zwischen A und B reicht über derenbboxhinaus. Dann ist sieanders.
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
cp -r "$W/shots/p9-ref" "$TMPDIR/probe" && cp "$TMPDIR/probe/1440x900/tickets.png" "$TMPDIR/probe/1440x900/kunden.png"
"$W/run-browser.sh" "$W/vergleich.mjs" "$W/shots/p9-ref" "$TMPDIR/probe"; echo "exit $?"
"$W/run-browser.sh" "$W/vergleich.mjs" "$W/shots/p9-ref" "$W/shots/p9-ref2"; echo "exit $?"
Expected: Der erste Aufruf nennt genau kunden bei 1440×900 als anders, Exit 1. Der zweite endet mit Exit 0 oder nennt wenige Rausch-Ansichten. Jede wird einmal angesehen und in $W/p10-rauschen.txt notiert.
- Step 6:
token-check.mjs, Flag, Checkmax-primaryund Gate
Umsetzung von token-check.mjs:
- Es liest
src/**/*.{css,jsx,js}und schreibt nur dort. Definiert ist ein Name durch--name:in CSS oder den Schlüssel'--name'in JSX-Objekten, benutzt durchvar(--name. legacyenthält jede Nutzung und jede Definition eines Alias-Namens der Tabelle in Task 4 (artistnutzungoderdefinition,ersatzder neue Name oder der Wert4pxbzw.none).undefinedUsedsind benutzte, nirgends definierte Namen ohne Rückfallwert, mit Rückfallwert landen sie inmitFallback.--fixschreibt nur dienutzung-Einträge um (var(--alt)undvar(--alt, …)),--sidebar-w-collapsednie.
Dazu kommen:
- das Flag in
css-klassen.mjs, - der Check
max-primaryinchecks.mjs(Spec, Gestaltungsregel 4: höchstens ein.btn-primaryje Seitenkopf), mitdetail<n> .btn-primary, GATES.p10ingates.mjs. P10 hat keine eigenen Ansichten,icon-svggilt deshalb für alle ('*'ist der Präfix-Platzhalter für alle Ansichten, wie in P2), mit demignoreausp9unverändert.step-failed,external-requestundconsole-errorsind wie in jedem Gate aktiv.
const iconSvg = GATES.p9.scoped['icon-svg']
GATES.p10 = {
...GATES.p9,
checks: [...GATES.p9.checks, 'max-primary'],
scoped: { ...GATES.p9.scoped, 'icon-svg': { ...iconSvg, views: ['*'] } },
}
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
mkdir -p "$TMPDIR/tc/src" && printf 'a{color:var(--nope);border:1px solid var(--border)}' > "$TMPDIR/tc/src/x.css"
node "$W/token-check.mjs" "$TMPDIR/tc"; echo "exit $?"
node "$W/token-check.mjs" . | node -e "const j=JSON.parse(require('fs').readFileSync(0));console.log(j.legacy.length, j.undefinedUsed.length)"
node "$W/css-klassen.mjs" . --ohne-ausnahmen | node -e "const j=JSON.parse(require('fs').readFileSync(0));console.log(j.dead.length, j.nurAusnahme.length)"
mkdir -p "$TMPDIR/probe-primary" && printf '<!doctype html><meta charset="utf-8"><title>Probe</title><div class="page-head"><h1>Test</h1><button class="btn btn-primary">A</button><button class="btn btn-primary">B</button></div>' > "$TMPDIR/probe-primary/index.html"
"$W/shots.sh" probe "$TMPDIR/probe-primary-out" --static "$TMPDIR/probe-primary" --only tickets --gate p10; echo "exit $?"
rg -o "max-primary" "$TMPDIR/probe-primary-out/report.json" | wc -l
Expected:
-
Der erste Aufruf endet mit Exit 1,
undefinedUsednennt--nope,legacynennt--bordermitersatz--line. -
Der zweite zeigt eine Zahl über 0 für
legacy(die Alias-Definitionen stehen noch) und 0 fürundefinedUsed. -
Der dritte nennt zwei Zahlen, sie werden notiert.
-
Die Probe mit zwei Primärknöpfen in einem
.page-headendet mit Exit 1, die letzte Zeile nennt eine Zahl über 0 (der Checkmax-primaryschlägt an). -
Step 7: Gate
p10gegendesign-p9
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/shots.sh" p9-ref "$W/shots/p9-ref-p10" --gate p10; echo "exit $?"
Expected: Exit 0 (die Bilder dieses Laufs werden nicht gebraucht). Ein Treffer icon-svg folgt der Stoppregel für Icons. Ein Treffer max-primary ist ein Fehler eines früheren Pakets: Der Agent stoppt und meldet ihn dem Eigentümer, weil der überzählige Knopf das Aussehen ändern würde.
Task 2: Icon-Pakete entfernen
Files:
- Create:
tests/unit/hygiene.test.mjs - Modify:
package.json(Zeilen 6 und 11),package-lock.json
Interfaces:
-
Consumes: nichts. Voraussetzung ist
rg "react-icons|@tabler" src= 0. -
Produces: ein Lock ohne
@tabler/icons-react,@tabler/iconsundreact-icons, dazuhygiene.test.mjsmit den Helfernfiles,read,offenders(re, only), auf denen Task 4 und 5 aufbauen. -
Step 1: Failing Test schreiben
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync, readdirSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
const files = readdirSync(path.join(root, 'src'), { recursive: true })
.filter((f) => /\.(jsx?|css)$/.test(f))
.map((f) => path.join('src', f))
const read = (rel) => readFileSync(path.join(root, rel), 'utf8')
const offenders = (re, only = /./) => files.filter((f) => only.test(f) && re.test(read(f)))
test('Icon-Pakete sind weder Abhängigkeit noch Import', () => {
const pkg = JSON.parse(read('package.json'))
for (const n of ['react-icons', '@tabler/icons-react']) assert.equal(pkg.dependencies[n], undefined, n)
assert.deepEqual(offenders(/react-icons|@tabler/), [])
})
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node --test tests/unit/hygiene.test.mjs
Expected: FAIL (package.json führt beide Pakete).
- Step 2: Beweisen, dass nichts mehr importiert
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "react-icons|@tabler" src
Expected: keine Ausgabe. Bei einem Treffer gilt die Stoppregel der Global Constraints.
- Step 3: Deinstallieren
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && systemd-run --scope -q -p MemoryMax=1500M -p MemorySwapMax=0 npm uninstall react-icons @tabler/icons-react --no-audit --no-fund
Expected: Exit 0.
- Step 4: Lock und Index prüfen
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git status --short; git diff package.json | rg "^[-+] "; rg -c "tabler|react-icons" package.json package-lock.json; git diff --numstat package-lock.json
npm ls react-icons @tabler/icons-react 2>&1 | rg "empty"; npm ci --dry-run --no-audit --no-fund; echo "exit $?"
Expected:
-
git statuszeigt genauM package-lock.json,M package.jsonund?? tests/unit/hygiene.test.mjs, keineD-Zeile (node_modulesist nicht getrackt). -
Der Diff von
package.jsonhat genau zwei--Zeilen,rg -cgibt nichts aus. -
numstatzeigt 0 hinzugefügte Zeilen. Stehen dort wenige, sind es höchstens geänderte Flags ("peer","dev"), und jede+-Zeile wird angesehen. -
npm lsmeldet(empty),npm ci --dry-runendet mit Exit 0. -
Step 5: Tests und Build
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/check.sh"
Expected: Exit 0, # fail 0, # pass = N9 + 1, Build grün.
- Step 6: Commit
git add package.json package-lock.json tests/unit/hygiene.test.mjs
git commit -m "Aufraeumen: react-icons und @tabler/icons-react deinstalliert (src ohne Icon-Importe), Waechtertest" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
Task 3: dotColor und Icon-Kommentare
Files:
- Modify:
src/lib/previewEnv.js(Zeile 1 und Zeilen 15–18 laut Ausgangsstand),tests/unit/previewEnv.test.mjs(Zeile 5 und der TestdotColor, Zeilen 21–29) - Modify:
src/lib/navLinks.js(Zeile 1),tests/unit/navLinks.test.mjs(Zeile 5)
Interfaces:
-
Consumes:
isValidEnvName,buildEnvPayload,isDevPreview,envValueTooLong,MAX_ENV_VARSauspreviewEnv.js, unverändert. -
Produces:
previewEnv.jsohnedotColorundDOT_COLORS. -
Step 1: Beweisen, dass
dotColorunbenutzt ist
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "dotColor|DOT_COLORS" src tests
Expected: Treffer nur in src/lib/previewEnv.js und tests/unit/previewEnv.test.mjs (P5 hat PreviewBlock und ServicesPage umgestellt). Weitere Treffer sind ein Fehler eines früheren Pakets.
- Step 2: Test zuerst anpassen
Der Test dotColor und der Name im loadModule-Destrukturieren entfallen.
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node --test tests/unit/previewEnv.test.mjs
Expected: PASS mit 4 Tests (isValidEnvName, buildEnvPayload, isDevPreview, envValueTooLong).
- Step 3: Funktion löschen
DOT_COLORS und dotColor fallen, der Kopfkommentar heißt „(Variablen, Dev-Erkennung)“.
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node --test tests/unit/previewEnv.test.mjs; rg -n "dotColor|DOT_COLORS|#10b981|#f59e0b|#a0aec0" src tests
Expected: PASS, keine Treffer.
-
Step 4: Icon-Kommentare
-
src/lib/navLinks.jsZeile 1 wird// Eintraege der Sidebar als reine Daten (unter Node testbar); Navbar.jsx rendert sie als Textliste.Der zweite Kommentarsatz zu Unterpunkten undcountbleibt. -
tests/unit/navLinks.test.mjsZeile 5 wird// Sidebar: Eintraege als reine Daten (Navbar.jsx rendert sie als Textliste).
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n -i "(^|[^a-z])icons?([^a-z]|$)" src tests --glob '!*.css' --glob '!hygiene.test.mjs'
Expected: keine Treffer, höchstens Kommentare zum fremden Chat-Baustein in src/components/chat und src/lib/loadChatComposer.js. Jeder andere Treffer wird umformuliert. „favicon“ und der Wächtertest zählen nicht.
- Step 5: Test
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/check.sh" --nur-tests
Expected: Exit 0, # fail 0, # pass = N9 (hygiene +1, dotColor −1).
- Step 6: Commit
git add src/lib/previewEnv.js tests/unit/previewEnv.test.mjs src/lib/navLinks.js tests/unit/navLinks.test.mjs
git commit -m "Aufraeumen: previewEnv.dotColor samt Test entfernt, Icon-Kommentare in navLinks angepasst" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
Task 4: Token-Aliase abbauen
Files:
- Modify:
src/styles/global.css(Alias-Block in:root), alle Dateien untersrc/mit alten Namen (Liste aus Step 3) - Create:
docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md(Überschriften 1 bis 7, Abschnitt 1 gefüllt) - Test:
tests/unit/hygiene.test.mjs(zweiter Test)
Interfaces:
- Consumes:
$W/token-check.mjs(Task 1) und die Alias-Tabelle der Spec:
| Alter Name | Neu |
|---|---|
--surface-1, --surface-3, --surface, --dark-bg, --dark-card-bg |
--bg |
--surface-2, --surface-hover |
--bg-hover |
--border, --gray-700, --admin-line |
--line |
--border-strong, --admin-line-strong |
--line-strong |
--border-accent |
--accent-ring |
--text-muted, --text-faint, --gray-800 |
--text-2 |
--dark-text, --gray-900 |
--text |
--accent-2, --green-secondary |
--accent-hover |
--green-primary |
--accent |
--info, --warn, --ok |
--blue-fg, --orange-fg, --green-fg |
--r-sm, --r-md, --r-lg, --r-pill |
--radius, --radius-lg, --radius-lg, Wert 4px |
--shadow-1, --shadow-2, --shadow-3 |
none, --shadow-btn, --shadow-pop |
--sidebar-w-collapsed |
entfällt, kein Nutzer erlaubt |
-
Produces:
:rootohne Aliase,token-checkmeldetlegacyundundefinedUsedleer. -
Step 1: Failing Test ergänzen
const LEGACY = ['surface-1', 'surface-2', 'surface-3', 'surface-hover', 'surface', 'dark-bg', 'dark-card-bg', 'border', 'border-strong', 'border-accent',
'gray-700', 'gray-800', 'gray-900', 'admin-line', 'admin-line-strong', 'text-muted', 'text-faint', 'dark-text', 'accent-2', 'green-secondary',
'green-primary', 'info', 'warn', 'ok', 'r-sm', 'r-md', 'r-lg', 'r-pill', 'shadow-1', 'shadow-2', 'shadow-3', 'sidebar-w-collapsed']
test('keine alten Token-Namen mehr (Aliase sind gelöscht)', () => {
const re = new RegExp(`(^|[^A-Za-z0-9-])--(${LEGACY.join('|')})([^A-Za-z0-9-]|$)`)
assert.deepEqual(offenders(re), [])
})
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node --test tests/unit/hygiene.test.mjs
Expected: FAIL im neuen Test.
- Step 2: Bestandsaufnahme
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
node "$W/token-check.mjs" . > "$TMPDIR/token-vorher.json"; node -e "const j=JSON.parse(require('fs').readFileSync(process.argv[1]));const c={};for(const e of j.legacy)c[e.name+' '+e.art]=(c[e.name+' '+e.art]||0)+1;console.log(c)" "$TMPDIR/token-vorher.json"
Expected: Zahl der Nutzungen und Definitionen je Alias. Sie kommt in Abschnitt 1 der Ergebnisdatei (Spalten: alter Name, Nutzungen vorher, ersetzt durch).
- Step 3: Nutzungen umbenennen
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node "$W/token-check.mjs" . --fix; git diff --name-only
Expected: Es ändern sich nur .css, .jsx und .js unter src/. Das ist eine reine Umbenennung, der Wert jedes Tokens bleibt gleich.
- Step 4: Alias-Block löschen
In global.css fallen der Alias-Block hinter dem Token-Block samt Kommentar und jede übrige Definition eines Alias-Namens, auch außerhalb von :root.
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node --test tests/unit/hygiene.test.mjs && node "$W/token-check.mjs" . | node -e "const j=JSON.parse(require('fs').readFileSync(0));console.log(j.legacy.length, j.undefinedUsed.length, j.mitFallback.length)"
Expected: PASS und 0 0 plus eine Zahl für mitFallback. Jeder Eintrag dort wird angesehen: Der Rückfallwert fällt, wenn das Token existiert, sonst steht der Eintrag in Abschnitt 7.
- Step 5: Bauen, Gate, Pixelvergleich
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p10 && "$W/shots.sh" p10 "$W/shots/p10-t4" --gate p10 && "$W/run-browser.sh" "$W/vergleich.mjs" "$W/shots/p9-ref" "$W/shots/p10-t4" --rauschen "$W/shots/p9-ref2" --out "$W/shots/p10-t4-diff"
Expected: Gate Exit 0, Vergleich Exit 0. Weicht eine Ansicht ab, hat --fix einen Namen falsch ersetzt oder eine Definition lag in einer Datei, die das Skript nicht liest. Das wird behoben.
- Step 6: Ergebnisdatei und Commit
Die Ergebnisdatei wird mit den Überschriften 1 bis 7 angelegt, Abschnitt 1 bekommt die Tabelle aus Step 2.
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git diff --name-only
git add docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md tests/unit/hygiene.test.mjs <die geprüften Dateien aus der Liste oben>
git commit -m "Aufraeumen: Token-Aliase der Altnamen durch die neuen Tokens ersetzt und geloescht" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
Task 5: KOMPAT-Block entfernen
Files:
- Modify:
src/styles/global.css(Block/* ===== KOMPAT (bis P10) ===== */und der Gliederungskommentar am Dateianfang), Dateien mit Restnutzern (Liste aus Step 3) - Modify: Ergebnisdatei Abschnitt 2
- Test:
tests/unit/hygiene.test.mjs(dritter Test)
Interfaces:
-
Consumes: die Bausteine aus P1 (
.btn,.btn-primary,.btn-quiet,.link,.link-danger,.badge,.field,.input,.select,.textarea,.msg,.muted,.dialog,.overlay,.seg button.on) undDialog,Card,Badge,StatusPill. -
Produces:
global.cssohne KOMPAT. Kein Selektor der Spec-Tabelle „Übergangsschicht KOMPAT“ ist übrig,.pagebleibt als Wurzelklasse der Seiten. -
Step 1: Failing Test ergänzen
test('keine Übergangsschicht und kein !important im CSS', () => {
assert.deepEqual(offenders(/KOMPAT|!important/, /\.css$/), [])
})
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node --test tests/unit/hygiene.test.mjs
Expected: FAIL im neuen Test.
- Step 2: Grenzen und Inventur
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
read A B < <(awk '/KOMPAT \(bis P10\)/{a=NR; next} a && /^\/\* (=====|---)/{print a+1, NR-1; f=1; exit} END{if(a&&!f)print a+1, NR}' src/styles/global.css); echo "KOMPAT $A-$B"
sed -n "${A},${B}p" src/styles/global.css | rg -o "\.[a-z][a-z0-9_-]*" | sort -u | sed 's/^\.//' | while read c; do echo "$(rg -l "(^|[^A-Za-z0-9_-])${c}([^A-Za-z0-9_-]|$)" src --glob '!*.css' | wc -l) $c"; done | sort -n | tee "$TMPDIR/kompat-inventur.txt"
Expected:
-
Der Block endet an der nächsten Kopfzeile
/* =====oder/* ---, sonst am Dateiende. -
Die Inventur hat 0 Nutzer für jede Klasse der Tabelle in Step 3. Bekannte Ausnahmen:
overlay(nursrc/components/ui/Dialog.jsx),row(nur an<tr>) und Klassen, die auch ein neuer Baustein trägt (btn,badge,field,link). Deren Regel wandert nach Step 4 in Block 3. -
Die Liste kommt als Tabelle (Klasse, Nutzer, Entscheidung) in Abschnitt 2 der Ergebnisdatei.
-
Step 3: Restnutzer finden und umstellen
| KOMPAT-Zeile der Spec | Gesuchte Namen | Ersatz |
|---|---|---|
.ui-card* |
ui-card |
Card (ohne Titel und Aktionen rendert es kein h2) oder <section> mit h2.section |
.ui-btn* |
ui-btn, -primary, -ghost, -danger, -sm, Muster ui-btn-${…} |
btn, btn btn-primary, link-danger, Zeilenaktion link |
.form-group, .form-label, .form-control |
dieselben drei | field, Label im .field, input, select, textarea |
.badge-*, .status-*, .priority-* |
badge- und status- mit muted, info, ok, warn, danger, open, working, awaiting, assigned, closed; priority-critical; Muster badge-${…}, status-${…} |
Badge, StatusPill |
.overlay (Altform), .overlay-content, .overlay-close |
overlay-content, overlay-close, overlay außerhalb von Dialog.jsx, fin-dialog (760 px, laut P7 tot) |
Dialog |
.seg button.active |
kein festes Muster: jedes seg in JSX ansehen |
Knopf mit on und aria-pressed |
.bg-red, .text-white, .text-grey, .text-red |
dieselben vier | msg err bzw. muted |
.side-count, .side-logo |
dieselben zwei | schon entfernt: .side-logo in P4, .side-count in P6. Ein Treffer ist ein Rest und wird entfernt |
.btn-dark, .btn-teal |
dazu btn-green |
btn btn-primary |
.card*, .row, .col*, .dropdown* |
card, card-header, card-body, col, col-6, dropdown*, row außerhalb von <tr> |
entfallen |
.spinner |
spinner |
Text „Wird geladen …“ |
.page .page, .page .main-content |
main-content |
entfällt (Step 5) |
| Links in Bestandsklassen | fin-link, credit-cols, area-rows. Die Klasse legal-files bleibt (P8), nur die Regel .legal-files a fällt. |
Klasse link am <a>, sonst die Regel in den Block des Nutzers |
In jedem <Dialog as="form">, das dabei entsteht oder angefasst wird, trägt jeder Knopf außer dem Absenden-Knopf type="button".
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n '(^|[^A-Za-z0-9_-])(ui-(card|btn)|form-(group|label|control)|(badge|status)-(muted|info|ok|warn|danger|open|working|awaiting|assigned|closed)|priority-critical|overlay-(content|close)|fin-dialog|bg-red|text-(white|grey|red)|side-(count|logo)|btn-(dark|teal|green)|spinner|dropdown[a-z-]*|card|card-header|card-body|col|col-6|main-content|fin-link|credit-cols|area-rows)([^A-Za-z0-9_-]|$)' src --glob '!*.css'; rg -n '(badge|status|ui-btn)-\$\{' src; rg -n 'className="[^"]*(^|[^A-Za-z0-9_-])row([^A-Za-z0-9_-]|")' src | rg -v '<tr'
Expected: keine Treffer. Ein Treffer in einem Kommentar wird umformuliert, jeder Code-Treffer nach der Tabelle umgestellt, eine Gruppe je Commit (Meldung „Aufraeumen: Restnutzer von auf umgestellt“).
- Step 4: Regeln, die ein Baustein noch braucht
Entscheidung: Das Aussehen der Bilder von design-p9 gilt. Eine KOMPAT-Regel, deren Selektor auch einen neuen Baustein trifft, wird nicht gelöscht. Ihre Deklarationen gehören dann an den Baustein in Block 3, nur die alten Selektoren fallen. Bekannter Fall ist .overlay, die Hülle von Dialog:
- Ist die KOMPAT-Zeile für die Altform ein eigener Selektor (
overlay-content,:has(…)), fällt sie weg. - Hat sie die Basisregel
.overlayselbst verändert (overflow-y: auto, Abstand 24/16 px), gelten die Werte, die die Bilder vondesign-p9fürDialogzeigen, und bleiben in der Basisregel.
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "^\.(overlay|dialog)\b" src/styles/global.css
Expected: eine Basisregel .overlay mit der Mobilregel bei 860 px, ohne Verweis auf overlay-content.
- Step 5: Block löschen, Verschachtelung statisch beweisen
Der Block samt Marker fällt, der Gliederungskommentar nennt danach vier Blöcke statt fünf.
Entscheidung: .page bleibt als Wurzelklasse jeder Seite. Gelöscht werden nur die Verschachtelungsregel .page .page, .page .main-content und die alte .main-content-Regel.
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
node --test tests/unit/hygiene.test.mjs
rg -n "KOMPAT|main-content" src
rg -n 'className=\{?["`]([^"`]* )?page([ "`}]|$)' src --glob '*.jsx' | rg -v '^src/pages/'
rg -n '<[A-Za-z]+Page\b' src --glob '!App.jsx'
Expected: PASS und drei leere Ausgaben. Es gibt also kein KOMPAT und kein main-content mehr, die Klasse page steht nur in src/pages/*.jsx (der Treffer-Filter erfasst nur Klassenstellen, keine Props wie page in Pager), und nur App.jsx rendert *Page-Komponenten. Eine Seite in einer Seite ist damit ausgeschlossen. Ein Treffer, der nur ein Wort im Kommentar ist, wird umformuliert.
- Step 6: Bauen, Gate, Pixelvergleich
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p10 && "$W/shots.sh" p10 "$W/shots/p10-t5" --gate p10 && "$W/run-browser.sh" "$W/vergleich.mjs" "$W/shots/p9-ref" "$W/shots/p10-t5" --rauschen "$W/shots/p9-ref2" --out "$W/shots/p10-t5-diff"
Expected: Gate Exit 0, Vergleich Exit 0. Auch alle Alt-Dialoge (dlg-*), die .seg-Ansichten (finanzen, serverpuls) und Links bleiben unverändert. Weicht eine Ansicht ab, wird das Diff-Bild angesehen. Es gibt zwei Ursachen:
-
Die gelöschte Regel gehört an die Stelle ihres Bausteins (Step 4).
-
Bereichs-CSS (
chat.css,serverpuls.css,pages/AdminPage.css) lädt vorglobal.cssund wurde bisher von KOMPAT überstimmt. Der Bereichs-Selektor bekommt dann eine höhere Spezifität, nie!important. -
Step 7: Commit
Abschnitt 2 der Ergebnisdatei ist gefüllt.
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git diff --name-only
git add docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md tests/unit/hygiene.test.mjs src/styles/global.css <weitere geprüfte Dateien>
git commit -m "Aufraeumen: KOMPAT-Block, .page-Verschachtelungsregel und Altklassen entfernt" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
Task 6: Tote Klassen und Keyframes
Files:
- Modify:
src/styles/*.css,src/pages/*.css, JSX-Dateien mit Klassen ohne Regel, Ergebnisdatei Abschnitt 3,$W/css-klassen.mjs(Ausnahmeliste) - Delete: CSS-Dateien ohne verbleibende Regel samt Importzeilen
Interfaces:
-
Consumes:
css-klassen.mjsmit--ohne-ausnahmen(Task 1). -
Produces:
deadundundefinedUsedsind leer, die Ausnahmeliste enthält nur Namen mit belegter Konstruktionsstelle. -
Step 1: Liste erzeugen
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
node "$W/css-klassen.mjs" . --ohne-ausnahmen > "$TMPDIR/klassen-p10.json"; node -e "const j=JSON.parse(require('fs').readFileSync(process.argv[1]));for(const k of ['dead','undefinedUsed','nurAusnahme'])console.log(k, j[k].length+':', j[k].join(' '))" "$TMPDIR/klassen-p10.json"
Expected: drei Zeilen mit Namen. dead enthält zunächst auch die Namen aus nurAusnahme.
- Step 2: Gegenprobe und Löschen
Für jeden Namen aus dead, der nicht in nurAusnahme steht:
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "(^|[^A-Za-z0-9_-])NAME([^A-Za-z0-9_-]|$)" src --glob '!*.css'
Expected: keine Treffer. Dann fällt jede Regel mit diesem Namen in der definierenden Datei, in einer Selektorliste nur der Name.
Für jeden Namen aus nurAusnahme bekommt Abschnitt 3 der Ergebnisdatei eine Zeile mit der Stelle, die ihn baut: ein Template-Präfix wie fin-fixed-${, eine Zeichenkette in lib/*.js oder der Fremd-Composer bei chat-*. Ohne Beleg gilt die Klasse als tot und fällt.
- Step 3: Klassen ohne Regel,
size, Keyframes
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
rg -n 'size="sm"' src; rg -n '(^|[^A-Za-z0-9_-])(btn-sm|p-4|status-filter|supporters-editor|timeline)([^A-Za-z0-9_-]|$)' src --glob '!*.css'
rg -o "@keyframes [A-Za-z0-9_-]+" src --glob '*.css' | sed 's/.*@keyframes //' | sort -u | while read k; do rg -q "animation[^;]*(^|[^A-Za-z0-9_-])${k}([^A-Za-z0-9_-]|;)" src --glob '*.css' || echo "TOT $k"; done
Expected: alle drei Ausgaben leer. Treffer der ersten beiden Befehle werden aus dem JSX entfernt (die Klassen haben keine Regel, size bewirkt nichts). Ein toter Keyframe fällt samt Regel. Zu erwarten ist spin, wenn .spin (Notiz aus P8) und .spinner keinen Aufrufer mehr haben.
- Step 4: Leere Dateien, Ausnahmeliste, Schriftordner
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && wc -l src/styles/*.css src/pages/*.css; rg -n "admin-areas" src index.html; ls src/assets 2>&1 | head -1; rg -n -i "assets/fonts|lato" src index.html
Expected:
-
Eine CSS-Datei ohne Regel wird mit
git rmgelöscht, ihreimport-Zeilen verschwinden (rg -l "<Dateiname>" src).admin-areas.csshat P6 schon gelöscht, ein Treffer vonrg -n "admin-areas" src index.htmlist ein Rest und wird entfernt. -
src/assetsexistiert nicht, das letzterghat keine Treffer. -
Die Ausnahmeliste in
$W/css-klassen.mjsenthält nur noch die Namen mit Beleg aus Step 2.badge-*,status-*,ticket-tab-active,ui-btn-*undside-dot-*fallen. -
Step 5: Prüfen
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node "$W/css-klassen.mjs" . | node -e "const j=JSON.parse(require('fs').readFileSync(0));console.log(j.dead.length, j.undefinedUsed.length)" && "$W/check.sh" && "$W/build.sh" "$WT" p10 && "$W/shots.sh" p10 "$W/shots/p10-t6" --gate p10 && "$W/run-browser.sh" "$W/vergleich.mjs" "$W/shots/p9-ref" "$W/shots/p10-t6" --rauschen "$W/shots/p9-ref2" --out "$W/shots/p10-t6-diff"
Expected: 0 0, check.sh Exit 0 mit # fail 0 und # pass = N9 + 2, Gate Exit 0, Vergleich Exit 0.
- Step 6: Commit
Abschnitt 3 der Ergebnisdatei hat die Tabelle: Klasse, definierende Datei, Beleg oder „gelöscht“.
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git status --short
git add docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md <die geprüften Dateien>
git commit -m "Aufraeumen: tote Klassen, Keyframes und leere CSS-Dateien geloescht, Klassen ohne Regel aus dem JSX entfernt" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
Task 7: Inline-Styles, Regelprüfung, Invarianten
Files:
- Modify: JSX-Dateien mit Inline-Styles ohne Laufzeitwert (Ersatz sind vorhandene Klassen, neue kommen nicht dazu), Ergebnisdatei Abschnitte 4, 5 und 7
Interfaces:
-
Consumes:
$W/farben.mjs(P1) und der Abschnitt „Bewusst offen“ indocs/superpowers/plans/2026-10-05-weisses-design-p1-tote-klassen.md. -
Produces: eine begründete Liste aller
style=-Stellen und die Regelprüfung der Spec als belegte Liste. -
Step 1: Inline-Styles nur noch für Laufzeitwerte
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -nU "style=\{\{(\s*[A-Za-z]+:\s*('[^']*'|\"[^\"]*\"|-?[0-9]+(\.[0-9]+)?)\s*,?)+\s*\}\}" src --glob '*.jsx'
Expected: keine Treffer. Das Muster findet jedes Objekt, dessen Werte alle feste Zahlen oder Zeichenketten sind. Jeder Treffer wird durch eine vorhandene Klasse ersetzt.
- Step 2: Rest begründen
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "style=\{" src --glob '*.jsx'
Expected: wenige Zeilen. Abschnitt 4 der Ergebnisdatei bekommt je Zeile Datei:Zeile, Ausdruck und Begründung. Erlaubt sind ein aus Daten oder Messung berechneter Wert (Breite in Prozent, Höhe, Spaltenzahl) und das Durchreichen der style-Prop in Badge.jsx. Feste Abstände, Farben, Schrift, Flex und Größen sind nicht erlaubt, solche Stellen werden umgestellt, und Step 1 beginnt von vorn.
- Step 3: Farben
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n '#[0-9a-fA-F]{3,8}\b|rgba?\(|hsla?\(' src --glob '*.jsx' --glob '*.js'; node "$W/farben.mjs" .
Expected:
-
Der
rgnennt nursrc/components/Logo.jsxundsrc/components/serverpuls/chartColors.js. -
farben.mjslistet kein Literal unter 3:1 auf Weiß, keine dunkle Schrift auf--accentund kein Weiß-Alpha. -
Jede Zeile des Abschnitts „Bewusst offen“ in
p1-tote-klassen.mdist erledigt. Hat sie das Zielpaket P10, wird sie hier behoben und in Abschnitt 5 genannt. -
Step 4: Regelprüfung der Spec
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
rg -n "!important" src # 1
rg -n -e "gradient\(" -e "backdrop-filter" -e "filter: *blur" src --glob '*.css' # 2
rg -n "text-transform" src --glob '*.css' # 3
rg -n "font-weight: *(800|900)" src # 4
rg -n -e "Lato" -e "@font-face" src index.html # 5
rg -n "font-family" src --glob '*.css' # 6
rg -n -e "color-scheme" -e "data-theme" -e "data-accent" src index.html # 7
rg -no -e "@media[^{]*" -e "@container[^{]*" src --glob '*.css' # 8
rg -n "<svg" src --glob '*.jsx' # 9
rg -n -e "Kpi" -e "kpi" src # 10
rg -n -e "<title>" -e 'rel="icon"' index.html # 11
for s in '\.num' '\.stat \.v' '\.fin-amount'; do printf '%s: ' "$s"; rg -l -U "$s([^A-Za-z0-9_{}-][^{}]*)?\{[^}]*tabular-nums" src --glob '*.css' | tr '\n' ' '; echo; done # 12
Expected:
- 1, 4, 5 und 10: leer.
- 2: höchstens eine Zeile, der Chevron von
.select. 3: eine Zeile, die Wochentage.wdim Planboard. - 6: nur
var(--font)und der Monospace-Stapel (ui-monospace). 7: nurcolor-scheme: light. - 8: nur
max-width: 1100pxund860px, bei@container560, 640 und 860 px, dazuprefers-reduced-motion. Zugelassen ist außerdem der eine Blockmax-width: 640pxinsrc/styles/chat.css: Er setzt im Eingabefeld des fremden Portal-Composers wiederfont-size: 16px(gegen das iOS-Zoomen, P6) und ist die WOMS-eigene Überschreibung des Composers. - 9: nur
Logo.jsxundSparkline.jsx. 11:Webklar WOMS 2.0und die Zeile für/favicon.svg. - 12 (Spec-Regel 6, Zahlen und Beträge): drei Zeilen, jede nennt mindestens
src/styles/global.css. Fehlt bei einem Selektor die Datei, trägt seine Regel keinfont-variant-numeric: tabular-nums. P10 ergänzt dann genau diese Deklaration an der bestehenden Regel. Das ist die einzige erlaubte Abweichung von der Pixelinvariante. Die Ansichten, die dadurch im Vergleich von Task 8 abweichen, stehen mit Begründung in Abschnitt 5. - Spec-Regel 4 (höchstens ein schwarzer Knopf je Seitenkopf) prüft kein
rg, sondern der Checkmax-primaryim Gatep10(Task 1 Step 6, Lauf in Task 8 Step 2).
Seitenbreakpoints außerhalb von 860 und 1100 px werden auf diese Werte gezogen (Spec, Regel 7), ausgenommen der 640-px-Block in chat.css. Jede andere Abweichung steht mit Begründung in Abschnitt 7. Befehl, Ausgabe und Urteil jeder Zeile stehen in Abschnitt 5.
- Step 5: Invarianten gegen
design-p0
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
git grep -ho 'data-testid=[^ >]*' design-p0 -- src | sort -u > "$TMPDIR/ti-p0.txt"
rg -oN --no-filename 'data-testid=[^ >]*' src | sort -u > "$TMPDIR/ti-jetzt.txt"
diff "$TMPDIR/ti-p0.txt" "$TMPDIR/ti-jetzt.txt" | rg '^<'
echo "confirm: $(git grep -h 'window\.confirm' design-p0 -- src | wc -l) -> $(rg --no-filename 'window\.confirm' src | wc -l)"
git diff --name-status design-p0..HEAD -- src/hooks src/lib
Expected:
- Das
diffzeigt keine<-Zeile, es ging keinedata-testidverloren. Neue (>) sind erlaubt und werden genannt. - Die Zahl der
window.confirmist gleich. - In
src/hookssteht nurM useWorkorders.jsplus die neuenuseWorkorder.js,useTicketCounts.js,useTicketMinutes.js. Insrc/libstehen nurD sidebar.js, neue Dateien (darunterrowClick.jsaus P2) undMfürticketStatus.js,navLinks.js,previewEnv.js,serverpulsFormat.js,creditFormat.js,offerFormat.js,storageFormat.js,projectList.js,leads.js. Jede andereM- oderD-Zeile ist ein Befund.
Die Ausgaben stehen in Abschnitt 5.
- Step 6: Commit
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/check.sh" --nur-tests && git status --short
Expected: Exit 0, # fail 0, # pass = N9 + 2, nur die erwarteten Änderungen.
git add docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md <die geprüften Dateien aus Step 1 bis 4>
git commit -m "Aufraeumen: Inline-Styles nur noch fuer Laufzeitwerte, Regelpruefung und Invarianten dokumentiert" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
Task 8: Gate P10, Bundle, Review, Tag
- Step 1: Rebase
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && git fetch origin && git merge-base --is-ancestor design-p9 HEAD && git rebase origin/test && "$W/check.sh"
Expected: design-p9 ist Vorfahre, der Rebase läuft ohne Konflikt, Exit 0 mit # fail 0 und # pass = N9 + 2. Gate, Bilder und Review beziehen sich damit auf den Stand, der getaggt wird.
- Step 2: Vollständiger Lauf und Pixelvergleich
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p10 && "$W/shots.sh" p10 "$W/shots/p10" --gate p10 && "$W/run-browser.sh" "$W/vergleich.mjs" "$W/shots/p9-ref" "$W/shots/p10" --rauschen "$W/shots/p9-ref2" --out "$W/shots/p10-diff"
Expected:
-
Das Gate
p10endet mit Exit 0. Über alle Ansichten, auch die der Review-Focus-Punkte 1 bis 5 der Übersicht, gibt es keine Verstöße gegenexternal-request,console-error,dark-surface,low-contrast,overflow-x,icon-svg(außer unter.woms-chat),max-primaryundstep-failed. -
Der Vergleich endet mit Exit 0,
fehltist leer, die Zahl der Ansichten gleicht der Sollzahl aus Task 1 Step 4. Rausch-Ansichten stehen in$W/p10-rauschen.txt. -
Die Ansicht
alt-linkhat keinen Verstoß. Ihr Schritt prüft, dass/tickets?woid=100131&status=doneauf/tickets/100131endet. -
Step 3: Bundle-Größe
Run:
source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh &&
"$W/check.sh" --nur-build &&
{ find dist -type f \( -name '*.js' -o -name '*.css' -o -name '*.ttf' \) -printf '%s %p\n'; for f in dist/assets/*.js dist/assets/*.css; do echo "$f gzip=$(gzip -9 -c "$f" | wc -c)"; done; wc -l src/styles/*.css src/pages/*.css; } | tee "$W/p10-baseline-p10.txt"
Expected:
-
Abschnitt 6 der Ergebnisdatei bekommt eine Tabelle mit den Zeilen JS in Byte, JS gzip, CSS in Byte, CSS gzip, Schrift in Byte, CSS-Zeilen und Testzahl und den Spalten P0,
design-p9, P10. Die P0-Werte stammen aus der Commit-ZeileAusgangswerte(Gegenprobe: Umbaukarte), die P9-Werte aus$W/p10-baseline-p9.txt. -
CSS und CSS-Zeilen sind kleiner als bei
design-p9, JS ist nicht größer. Gegenüber P0 fehlen 96.184 B Schrift. Werte, die gegenüber P0 wachsen, stehen in Abschnitt 7. -
Step 4: Ergebnisdatei abschließen
Abschnitt 7 (Offene Punkte) ist gefüllt, auch wenn er nur „keine“ sagt.
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && git status --short
Expected: nur M docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md.
git add docs/superpowers/plans/2026-10-05-weisses-design-p10-ergebnisse.md
git commit -m "Aufraeumen: Ergebnisdatei mit Bundle-Vergleich und offenen Punkten" -m "Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
- Step 5: Code-Review (sonnet)
Geprüft wird der Diff design-p9..HEAD gegen die Spec-Abschnitte „Übergangsschicht KOMPAT“, „Gestaltungsregeln“ und „Was gleich bleibt“, dazu liest der Prüfer die Ergebnisdatei. Schwerpunkte:
- Der Diff enthält nur Löschungen, Umbenennungen und Umstellungen auf vorhandene Bausteine, keine neuen Texte, Klassen oder Tokens außer dem Wächtertest.
- Zehn Stichproben aus Abschnitt 2 (KOMPAT) und 3 (tote Klassen): Die Klasse hat per
rgkeinen Nutzer, ihre Regel ist weg. package.jsonund Lock haben genau@tabler/icons-react,@tabler/iconsundreact-iconsverloren.git diff design-p9 -- src/pages/TicketsPage.jsx src/lib/ticketListUrl.jsist leer oder enthält nur Kommentare,woidRedirectTargetist erhalten.- Jede Begründung in Abschnitt 4 stimmt, die Invarianten aus Abschnitt 5 sind erfüllt.
Wichtige Befunde werden behoben, danach laufen Step 1 bis 3 erneut. Kleinigkeiten kommen in Abschnitt 7.
- Step 6: Tag und Übergabe
Run: source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/check.sh" && git tag design-p10 && git log --oneline origin/test..design-p10 && git rev-parse design-p10
Expected: Exit 0, Tag gesetzt. Brachte der Rebase in Step 1 neue Commits mit, liefen Gate und Vergleich bereits auf dem rebaseten Stand.
Der Eigentümer bekommt:
-
den Bericht des Pixelvergleichs („0 abweichende Ansichten von “) und die Screenshots aus
$W/shots/p10/1440x900und$W/shots/p10/390x844(Auswahl:login,tickets,ticket,kunde-overview,projekte,finanzen,dlg-rechnung-kunde,serverpuls, ein Alt-Dialog) -
die Bundle-Tabelle aus Abschnitt 6 der Ergebnisdatei
-
den Hinweis, dass sichtbar nichts Neues erscheint, der Link
/tickets?woid=Naus Portal-Mails weiter funktioniert und die offenen Punkte in Abschnitt 7 stehen -
den Hinweis, dass damit alle Pakete ausgeliefert sind und Worktree
dev-designsamt Branchfeature/design-weissdanach entfernt werden können, wenn er das will -
die Push-Zeile
git -C /home/webklar/apps/ticket.webklar.com/dev-design push origin 'design-p10^{commit}:refs/heads/test' -
die Rücknahme
git revert --no-commit design-p9..design-p10(Commit und Push auftestdurch den Eigentümer, gilt nur solange P10 das jüngste Paket ist) -
Step 7: Nach dem Push (erst, wenn der Eigentümer gepusht hat)
-
Im Log von
webklar-ticket-buildsteht „Deployment completed successfully“. Dort läuftnpm installmit dem neuen Lock durch. -
curl -s https://ticket.webklar.com/ | grep -o 'assets/index-[^"]*\.js'entsprichtdist/index.htmldes Tags. -
curl -s -o /dev/null -w '%{http_code}' 'https://ticket.webklar.com/tickets?woid=1'liefert 200 (Seiten-Fallback). -
Ein lesender Sichttest im Chrome des Eigentümers, ohne Schreibaktion: Ein alter Link
/tickets?woid=<N>mit einer echten Nummer landet auf/tickets/<N>. Ticketliste, ein Ticket, das Menü mit dem Serverpuls-Punkt und ein Dialog (öffnen, mit Esc schließen) sehen aus wie vor dem Push, und die Konsole zeigt keinen Fehler.