# WOMS „Weißes Design“ P5: Projekte – 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 P5 steht der Projektbereich im neuen Design. Die Projektliste ist eine Tabelle mit Reitern, beide Projekt-Dialoge laufen über `Dialog`, Zuordnen-Assistent und Services bestehen aus ruhigen Abschnitten. Alle Projekt-Bausteine (am Ticket und beim Kunden) kommen ohne Karten, Icons und Farbliterale aus. Jede heutige Funktion bleibt erreichbar. **Architecture:** - Reine Logik, die heute in `ProjectsPage.jsx` steckt (Projektart, Hosting-Zustand, Aktionen), wandert mit Tests nach `src/lib/projectRow.js`. `src/lib/projectList.js` bekommt den neuen Export `projectTabs`. - Die Töne der Status-Vokabulare (Preview, Analyse, Projektstatus) werden in `src/components/projectTones.js` auf Badge-Töne abgebildet. `previewEnv.js`, `previewView.js` und `analyseView.js` bleiben unverändert. - `global.css` bekommt am Ende den Block „Projekte (P5)“. Die Komponenten benutzen nur Bausteine aus P1. **Tech Stack:** React 18, react-router-dom 6, date-fns 2 (`formatDistance`, Locale `de`, wie schon in `TicketCard`), reines CSS. Tests mit `node --test`, Screenshot-Werkzeug aus P0. **Spec:** `docs/superpowers/specs/2026-10-04-weisses-design-design.md`, Abschnitte „Bausteine“ (Tabelle, Liste, Dialog, Badge, Reiter, Meldungen, Laden), „Ticket als eigene Seite / Route und Links“ (Ticket-Spalte), „Texte“, „Was gleich bleibt“ und Paket P5. Dazu der Anhang `docs/superpowers/specs/2026-10-04-weisses-design-umbaukarte.md` (Abschnitte 3, 4, 5.P5, 7). Globale Regeln und gemeinsame 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, Arbeitsverzeichnis), `$W` (Screenshot-Werkzeug) und `$TMPDIR`. Zeilenangaben beziehen sich auf den Stand `603d08c` und sind nach P1 bis P4 verschoben. Maßgeblich ist der Inhalt. Es gelten die Regeln der Übersicht. Für P5 kommt hinzu: - **Vorbedingung:** Die Tags `design-p1` bis `design-p4` existieren. Task 0 prüft das und rebased auf `origin/test`. - **Dateien dieses Pakets:** `ProjectsPage`, `AssignProjectPage`, `ServicesPage`, `TicketProjects`, `AssignedProjectCard`, `AnalyseRow`, `PreviewBlock`, `PreviewLinkButton`, `GiteaLinkButton`, `CopyableCredential`, dazu `global.css` und `AdminPage.css` (nur `.credential*`). - **Unverändert bleiben:** alle Hooks, `lib/previewEnv.js`, `lib/previewView.js`, `lib/analyseView.js`, `lib/projectAssign.js`, `lib/assignFlow.js`, `lib/servicesView.js`, `lib/projectAdminApi.js` und die Signaturen von `AssignedProjectCard`, `TicketProjects`, `AnalyseRow`, `PreviewBlock`, `CopyableCredential`, `copyText`, `getCustomerPortalPassword`. `lib/projectList.js` bekommt nur einen neuen Export. - **Texte:** wörtlich wie heute (auch die ae/ue-Schreibung wie „Oeffentliche“ oder „angestossen“). Neu sind nur die Texte der Spec-Liste „Texte“ und die mit „Entscheidung:“ markierten Zeilen dieses Plans. - **Status-Vokabulare** (`previewStatus().color`, `analyseStatus().color`, `previewState`, `status`, `provisioningStatus`) werden nicht geändert. Die Tonabbildung liegt in `projectTones.js`. - **Jeder `Button` und jeder Textlink-Knopf (`button.link`) bekommt ein explizites `type`** (`button` oder `submit`), weil P1 keinen Standard setzt. In einem `` trägt jeder Knopf außer dem Absenden-Knopf `type="button"`. - **Zeilenklick:** Klickbare Tabellenzeilen prüfen Klicks mit `isRowActivation(event)` aus `src/lib/rowClick.js` (P2, Task 2). P5 baut keinen eigenen Helfer. - **Abschnittsabstände:** Zwischen aufeinanderfolgenden Abschnitten (`Card`) sorgt `.page section + section` (P1). P5 hat dafür keine eigene Regel. - **Keine `style={{…}}`:** P5 hat keine Laufzeitwerte. Kein Farbliteral, kein `btn-sm`, keine Icon-Importe in den Dateien dieses Pakets. - **`window.confirm` und `window.alert`** bleiben an ihren Stellen. - **Ticketlinks** über `ticketPath` aus `src/lib/ticketRoutes.js` (P2). Die drei Stellen in `AssignProjectPage` (2×) und `ServicesPage` sind seit P2 umgestellt und bleiben es. - **Testzahl:** Stand `design-p4` plus 13 neue Tests (7 in `projectRow`, 2 in `projectList`, 4 in `projectTones`). ## Review Focus Aus der Übersicht gehören vier Punkte zu P5. Die Prüfungen laufen als Ansichten im Gate `p5` (Task 4). - **Punkt 2, lange Inhalte am Handy:** Ansicht `projekte-lang` (Projektname 120 Zeichen, Repo-Pfad 90 Zeichen, Kundenname 60 Zeichen). Dazu `projekte-861` und `projekte-1101` (Menü fest, aber wenig Platz). Erwartet: kein `overflow-x`, die erste Spalte bleibt (gerundet) mindestens 140 px breit. - **Punkt 3, Teilausfall:** Ansicht `fehler-projekte` (Mitarbeiterliste antwortet mit 500). Erwartet: Tabelle und Reiter bedienbar, Mitarbeiter-Auswahl zeigt nur „Alle Mitarbeiter“. - **Punkt 4, nur Tastatur:** - Das ``, sonst ``, dazu `` | | Neue Variable | `.pv-add`: zwei `input.input` (Enter-Handler bleiben) und `Button type="button"` „Hinzufügen“ | | „Variablen speichern“ | `Button` (Standard), `type="button"` | | Wurzel | `
` | - [ ] **Step 2: Prüfen** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p5 && "$W/shots.sh" p5 "$W/shots/p5-t7" --only ticket-projekte --gate p5; echo "exit $?"` Expected: Im Bild steht der geöffnete Preview-Block ohne Knopfrahmen-Reihe, ohne dunklen Log-Kasten. `icon-svg` an der Projektzeile und am Abschnitt (Tasks 9 und 10) darf noch melden. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "btn-sm|#[0-9a-f]{3,6}|style=\{" src/components/PreviewBlock.jsx` Expected: keine Treffer. - [ ] **Step 3: Commit** ```bash git add src/components/PreviewBlock.jsx git commit -m "Projekte: Preview-Block ohne Kleinknoepfe, Statuspunkt als Badge, Log auf hellem Grund" -m "Co-Authored-By: Claude Opus 5.5 " ``` ### Task 8: `AnalyseRow` (Zustimmung als Dialog) **Files:** - Modify: `src/components/AnalyseRow.jsx` (`COLORS` L5 löschen, Markup L58-132 neu) **Interfaces:** - Consumes: `Dialog`, `Button`, `Badge`, `Field` aus `components/ui` (P1), `analyseColorTone` aus `./projectTones`, alle Funktionen aus `lib/analyseView` unverändert (`analyseStatus`, `textformLabel`, `canSubmitTextform`, `channelLabel`, `legalLinks`, `chatTemplate`, `privacyHint`). - Produces: `AnalyseRow({ projectId })` (Signatur unverändert). - [ ] **Step 1: Umbau** Zustände, `apply`, `cancel`, `copyTemplate`, `canSubmit` und alle Wortlaute bleiben. Neu ist das Markup: | Heute | Danach | |---|---| | Zeile „Website-Analyse:“ | `
`: `Website-Analyse:`, dann Status | | Status | `data`: `{status.text}`; `loadError`: ``; sonst `Lädt …`; `status.hint` als `({status.hint})` | | „Einschalten“ (oder `status.enableLabel`) und „Ausschalten“ | ``, `` | | `error` | im Dialog als `

` ganz oben im Dialog-Inhalt, sonst unter der Zeile | - Entscheidung: Der Dialogtitel ist „Website-Analyse“ (das Wort der Zeile, ohne Doppelpunkt). Ein Titel muss sein, ein neuer Wortlaut ist nicht nötig. - Entscheidung: Die Ausschalten-Rückfrage bleibt inline, nur die Zustimmung ist ein Dialog (wie in der Spec). - Entscheidung: Die Reihenfolge im Fuß folgt dem Prototyp (Abbrechen links vom Hauptknopf). - [ ] **Step 2: Prüfen** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p5 && "$W/shots.sh" p5 "$W/shots/p5-t8" --only analyse-zustimmung --gate p5; echo "exit $?"` Expected: Der Dialog hat keinen Verstoß. `icon-svg` darf noch an `AssignedProjectCard` und `TicketProjects` melden (Tasks 9 und 10). Bei 390 px liegt der Dialog unten als Sheet, „Einschalten“ ist erreichbar. Esc schließt, bei `busy` nicht. Der Text im Kästchen ist unverändert (Stichprobe: Diff gegen `textformLabel`). - [ ] **Step 3: Commit** ```bash git add src/components/AnalyseRow.jsx git commit -m "Projekte: Website-Analyse-Zeile ohne Farbliterale, Zustimmung als Dialog (Wortlaut unveraendert)" -m "Co-Authored-By: Claude Opus 5.5 " ``` ### Task 9: `AssignedProjectCard` **Files:** - Modify: `src/components/AssignedProjectCard.jsx` (Icon-Imports und `STATUS_COLORS`/`StatusBadge` L2-35 ersetzen, Markup L81-176 neu) **Interfaces:** - Consumes: `Button`, `Badge` aus `components/ui`, `statusValueTone` aus `./projectTones`, `PreviewLinkButton`, `GiteaLinkButton`, `PreviewBlock`, `AnalyseRow`, Klassen `.proj-*`, `.row-actions`, `.link`, `.msg`. - Produces: `AssignedProjectCard({ project, onUnassign, showActions = false, customerName = '', onChanged = () => {} })` (Signatur unverändert). Aufrufer sind `TicketProjects` und der Projekte-Reiter der Kundenseite (P4). - [ ] **Step 1: Umbau** Handler (`openPreviewInput`, `handleEnablePreview`, `handleBackfill`) und Zustände bleiben. | Heute | Danach | |---|---| | Karte mit blauem Rahmen | `

` | | Name, `(subdomain)`, Repo mit `FaCodeBranch` | `.proj-head > .proj-main`: ``, ``, `
{repoFullName}
` | | Vorschau-, Gitea-Knopf, Lösen-Knopf | `.row-actions` mit `PreviewLinkButton`, `GiteaLinkButton` und ``. Er erscheint unter derselben Bedingung (`showActions && onUnassign`). | | `StatusBadge` mit Punkt | `.proj-meta`: `Status: {value}`, ebenso „Provisioning:“. Ohne Wert nichts. | | `AnalyseRow` | unverändert eingebunden (`project.subdomain`) | | „Preview ▴/▾“ (`btn btn-sm`) | `` | | Meldungen | `

` je `previewMessage`, `pushMessage` | - [ ] **Step 2: Prüfen** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p5 && "$W/shots.sh" p5 "$W/shots/p5-t9" --only ticket-projekte,kunde-projects --gate p5; echo "exit $?"` Expected: `kunde-projects` besteht. `ticket-projekte` darf noch `icon-svg` am Abschnitt melden (Task 10). Die Projektzeile am Ticket zeigt Name, Repo, drei Textlinks, Status-Badges und die Analyse-Zeile ohne Kasten. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "react-icons|btn-sm|#[0-9a-f]{3,6}|style=\{" src/components/AssignedProjectCard.jsx` Expected: keine Treffer. - [ ] **Step 3: Commit** ```bash git add src/components/AssignedProjectCard.jsx git commit -m "Projekte: Projektzeile am Ticket und beim Kunden ohne Kasten, Aktionen als Textlinks" -m "Co-Authored-By: Claude Opus 5.5 " ``` ### Task 10: `TicketProjects` **Files:** - Modify: `src/components/TicketProjects.jsx` (Import L2 löschen, Markup L158-228 neu) **Interfaces:** - Consumes: `Card`, `Button`, `Dialog` aus `components/ui`, `AssignedProjectCard`, Klassen `.ticket-projects-assign`, `.row-buttons`, `.msg`. - Produces: `TicketProjects({ ticket })` (Signatur unverändert, P2 bindet sie auf der Ticketseite ein). `data-testid="project-kind"` bleibt. - [ ] **Step 1: Umbau** Alle Zustände und Handler (`run`, `assign`, `assignPlain`, `assignWithKind`, `unassign`, `create`) bleiben. | Heute | Danach | |---|---| | `ui-card pad` mit `

` | `` | | „Suche neue Repos …“ | `

` | | `importHint`, `error` | `

` | | „Noch kein Projekt an diesem Ticket.“ | `

` | | Art-Zeile und Karte je Projekt | `` und `AssignedProjectCard` (Props wie heute) | | Auswahl „Projekt zuweisen“ | `.ticket-projects-assign`: ``, „Subdomain“ als `Field` mit dem `hint`. „Abschließen“ als `Button variant="primary"`, beim Laden „Speichert …“. | - Entscheidung: Die Auswahl ist nicht nur an Hintergrund und Häkchen erkennbar. Die gewählte Zeile trägt `aria-pressed="true"`, den Hintergrund `--bg-hover` und das Badge „Ausgewählt“ (`Ausgewählt` am Zeilenende). Das Wort ist neu und von der Spec verlangt („Auswahl auch als Text markiert“). - Entscheidung: Die Zusammenfassung bleibt eine Liste mit dem Wortlaut von heute (kein `.kv`, damit die Doppelpunkte und Sätze unverändert bleiben). - Entscheidung: Der Brotkrumen-Link führt immer auf `/projects`. - [ ] **Step 4: Prüfen** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p5 && "$W/shots.sh" p5 "$W/shots/p5-t12" --only zuordnen,zuordnen-kunde,zuordnen-ticket,zuordnen-fertig --gate p5` Expected: PASS. Bei 390 px läuft nichts über den Rand, die gewählte Zeile zeigt „Ausgewählt“. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "ticketPath" src/pages/AssignProjectPage.jsx` Expected: weiter 2 Treffer. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "react-icons|style=\{|surface-2|text-red" src/pages/AssignProjectPage.jsx` Expected: keine Treffer. - [ ] **Step 5: Commit** ```bash git add src/pages/AssignProjectPage.jsx git commit -m "Projekte: Zuordnen-Assistent mit Abschnitten, Brotkrumen und im Text markierter Auswahl" -m "Co-Authored-By: Claude Opus 5.5 " ``` ### Task 13: `ServicesPage` **Files:** - Modify: `src/pages/ServicesPage.jsx` (Importe L2-4 anpassen, Markup L30-84 neu) **Interfaces:** - Consumes: `PageHeader`, `Card`, `Button`, `Badge` aus `components/ui`, `previewStateTone` aus `components/projectTones`, `servicesCards` unverändert, `ticketPath` (P2, bleibt wie umgestellt), Klassen `.list-row`, `.cell-title`, `.cell-sub`, `.link`, `.msg`. - Produces: Seite `/services`. - [ ] **Step 1: Umbau** - Laden: `

Wird geladen …
`. - Fehler: `

` und `Button type="button"` „Erneut versuchen“, ohne Kasten. - Das Kachelraster entfällt. Jede Art ist ein untereinander stehender Abschnitt ``. - Beschreibung als `

`. Funktions-Badges bleiben `` mit dem Text `label · statusLabel` in einer Zeile (`.pv-row`). - Projektzeilen sind `.list-row` (kein Link, `div`): links `.cell-title` mit Projektname, dem Badge „Analyse an“ (nur bei `features.analyse === 'active'`) und davor dem Preview-Badge, darunter `.cell-sub` (`Kunde · Preview` oder „Intern“, wie heute). Rechts `Link className="link"` „Ticket #{woid}“ und in der Karte „Art fehlt“ `Link className="link" to={\`/projects/zuordnen/${p.id}\`}` „Zuordnen“. - „Noch keine Projekte.“ als `

`. - Preview-Badge: `Preview: {p.previewState}`. - Der Import von `dotColor`, `FaSpinner`, `useNavigate` und der Aufruf `navigate` entfallen. - Entscheidung: Das Badge trägt den Text `Preview: {Zustand}`. Das ist der Wortlaut, den der Punkt heute als Titel und für Screenreader hat. Die Wörter des Anhangs („Online“, „Wird gebaut“, „Fehler“, „Aus“) stehen nicht in der Spec-Liste „Texte“ und kommen deshalb nicht hinein. - Entscheidung: „Zuordnen“ ist ein echter Link statt eines schwarzen Knopfes. Es ist eine Zeilenaktion, und das Ziel ist dasselbe. - [ ] **Step 2: Prüfen** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p5 && "$W/shots.sh" p5 "$W/shots/p5-t13" --only services --gate p5` Expected: PASS. Bei 390 px laufen Zeilen mit langem Namen nicht über den Rand. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "ticketPath" src/pages/ServicesPage.jsx` Expected: weiter 1 Treffer. - [ ] **Step 3: Commit** ```bash git add src/pages/ServicesPage.jsx git commit -m "Projekte: Services als untereinander stehende Abschnitte mit Zeilen, Preview-Zustand als Badge" -m "Co-Authored-By: Claude Opus 5.5 " ``` ### Task 14: Gate P5, Review, Tag - [ ] **Step 1: Rebase** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && git fetch origin && git rebase origin/test && "$W/check.sh"` Expected: Exit 0 und `# fail 0`. `# pass` ist die Zahl aus Task 0 plus 13 (liegen neue Commits auf `test`, kann sie höher sein). Die Bundle-Größen aus der Ausgabe werden notiert. - [ ] **Step 2: Vollständiger Gate-Lauf** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/build.sh" "$WT" p5 && "$W/shots.sh" p5 "$W/shots/p5" --gate p5` Expected: - Exit 0. Das Gate `p5` gilt für alle Ansichten (`views: '*'`), also auch für die aus P0 bis P4. So zeigt der Lauf, dass P5 sonst nichts verschlechtert hat. - Keine Verstöße gegen `external-request`, `console-error`, `step-failed`, `dark-surface`, `low-contrast` und `overflow-x`. - `icon-svg` ist für alle Ansichten im Umfang des Gates (P2 bis P5, ohne `ignore`) sauber. - [ ] **Step 3: Code-Hygiene und Klassenabgleich** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "react-icons|@tabler|btn-sm|style=\{|#[0-9a-fA-F]{3,6}\b|text-grey|text-red|bg-red|ui-btn|ui-card|form-control|badge-(ok|info|warn|muted|danger)|isInteractiveTarget" src/pages/ProjectsPage.jsx src/pages/AssignProjectPage.jsx src/pages/ServicesPage.jsx src/components/TicketProjects.jsx src/components/AssignedProjectCard.jsx src/components/AnalyseRow.jsx src/components/PreviewBlock.jsx src/components/PreviewLinkButton.jsx src/components/GiteaLinkButton.jsx src/components/CopyableCredential.jsx` Expected: keine Treffer. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "btn-sm" src` Expected: keine Treffer. Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && rg -n "dotColor" src` Expected: nur noch `src/lib/previewEnv.js` (P10 löscht es samt Test). Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && node "$W/css-klassen.mjs" "$WT" > "$TMPDIR/klassen.json" && node -e "const j=JSON.parse(require('fs').readFileSync(process.argv[1]));const mine=/^(projects-table|row-actions|pv-|proj-|dialog-form|pick-|summary|ticket-projects-assign)/;for (const k of ['undefinedUsed','dead']) console.log(k, j[k].filter((c)=>mine.test(c)).join(' '))" "$TMPDIR/klassen.json"` Expected: Hinter `undefinedUsed` und hinter `dead` steht kein Name. Keine Klasse des P5-Blocks ist unbenutzt oder ohne Regel (`projects-table`, `row-actions`, `pv-*`, `proj-*`, `dialog-form`, `pick-*`, `summary`, `ticket-projects-assign`). - [ ] **Step 4: Bundle-Größe** Die Werte aus der `check.sh`-Ausgabe von Step 1 werden mit `design-p4` verglichen. JS ist kleiner, weil `ProjectsPage`, `AssignedProjectCard`, `GiteaLinkButton` und weitere keine Icon-Importe mehr haben. - [ ] **Step 5: Code-Review (sonnet)** Geprüft wird der Diff `design-p4..HEAD` gegen die Spec-Abschnitte „Bausteine“, „Ticket als eigene Seite / Route und Links“, „Texte“, „Was gleich bleibt“ und Paket P5, dazu der Review Focus oben. Besonders: - Jede Steuerung aus den Tabellen der Tasks 7 bis 13 ist erreichbar. - Es gibt keinen Textunterschied außer den Spec-Texten und den „Entscheidung“-Zeilen (Stichprobe: `git diff design-p4..HEAD -- src/pages src/components` auf geänderte Texte lesen). - Alle `window.confirm`, `busyRef`-artigen Sperren (`assignBusyId`, `hostBusyId`, `refreshBusyId`, `archiveBusy`) und `data-testid`/`data-hidden-hits` sind erhalten. Wichtige Befunde werden behoben, Kleinigkeiten notiert. Danach kommt der Rebase aus Step 1 noch einmal und Step 2 als Kurzlauf mit `--only projekte,services,ticket-projekte`. - [ ] **Step 6: Tag und Übergabe** Run: `source /root/reports/ticketsystem-design-2026-10-04/werkzeug/env.sh && "$W/check.sh" && git tag design-p5 && git log --oneline origin/test..design-p5 && git rev-parse design-p5` Der Eigentümer bekommt: - die Screenshots aus `$W/shots/p5/1440x900` und `$W/shots/p5/390x844` (Auswahl: `projekte`, `projekte-lang`, `projekte-861`, `dlg-projekt-neu`, `dlg-projekt-bearbeiten`, `zuordnen-kunde`, `zuordnen-fertig`, `services`, `analyse-zustimmung`, `ticket-projekte`) - die Liste der „Entscheidung“-Zeilen dieses Plans, vor allem: neues Wort „Ausgewählt“, Preview-Badge `Preview: {Zustand}` in den Services, gestapelte Zeilen der Projekttabelle unter 860 px, Dialogtitel „Website-Analyse“ - den Hinweis, dass „Zuordnen“ in den Services jetzt ein Textlink ist - für P8: Von `.credential*` bleiben `.credential`, `.credential-value`, `.credential-value.is-masked`, `.credential-empty`, `.credential .link` - die Push-Zeile `git -C /home/webklar/apps/ticket.webklar.com/dev-design push origin 'design-p5^{commit}:refs/heads/test'` - die Rücknahme `git revert --no-commit design-p4..design-p5`, Commit auf `test` und Push durch den Eigentümer (nur solange P5 das jüngste Paket ist) - [ ] **Step 7: Nach dem Push (erst, wenn der Eigentümer gepusht hat)** - Im Log von `webklar-ticket-build` steht „Deployment completed successfully“. - `curl -s https://ticket.webklar.com/ | grep -o 'assets/index-[^"]*\.js'` entspricht `dist/index.html` des Tags. - Ein lesender Sichttest im Chrome des Eigentümers: `/projects` (Reiter, eine Zeile mit „Aktualisieren“ oder „Hosten“) und die Projekte eines Tickets. Nichts anklicken, was speichert.