P2503 · Implementation Plan · F-170

Personen / Team Content-Type — Tracer-Bullet-Decomposition in 5 Vertical-Slices

active P2503-97 (Parent-Story) Erstellt: 2026-05-25 · 5 Sub-Tasks (P2503-179 … P2503-183) · alle in „Zu erledigen"
TL;DR: Die Parent-Story P2503-97 (Personen / Team Content-Type) wird in fünf vertikale AFK-Slices decomposed. Slice 1a (Backend-only) → Slice 1b (Frontend-Tracer) → Slice 2 (Optional-Kontakt-Stack) → Slice 3 + Slice 4 parallel (Vacancy-Sidebar bzw. Figma-Polish). Jeder Slice schneidet end-to-end durch Content-Type, View-Display, SDC und Canvas-Component — keine horizontalen Layer-Slices. Decision-Authority: ADR-0046. Fachliche Quelle: PRD vom 2026-05-25. QA-Plan: Story-Hub F-170 §qa-plan.

Slice-Übersicht

Alle Slices sind AFK (Agent-bearbeitbar ohne HITL-Interaktion). Sprache der Sub-Task-Akzeptanzkriterien ist Stakeholder-konform (Memory [[feedback_jira_description_user_story_only]]); Tech-Constraints sind in den Slices als Quality-AKs eingewoben, nicht als eigene Tickets.

# Title Jira-Key Status Blocked by
1a Personen-Inhalts-Typ im Drupal-Admin anlegbar (Pflichtfelder + Validation) P2503-179 Zu erledigen
1b Personen-Card platzierbar und renderbar auf Canvas-Seite (Tracer-Frontend) P2503-180 Zu erledigen P2503-179
2 Optional-Kontakt-Stack E-Mail + LinkedIn mit Conditional-Render P2503-181 Zu erledigen P2503-180
3 Vacancy-Sidebar-Recruiter mit Default-Recruiter aus Karriere-Settings P2503-182 Zu erledigen P2503-181
4 Figma-Compliance + Responsive auf Tablet und Mobile P2503-183 Zu erledigen P2503-181 (kann parallel zu P2503-182 starten)

Slice-Detail

Slice 1a — Personen-Inhalts-Typ im Drupal-Admin (P2503-179)

Vertikaler Cut: Drupal-Content-Type (node.person) inkl. Felder + Validation. Reiner Backend-Slice — kein Frontend-Render, keine SDC, kein Canvas. Outcome: Redakteur:innen können im Admin Personen anlegen und im Content-Listing wiederfinden.

PRD-User-Stories covered: 7 (Personen als Nodes anlegen), 8 (Pflichtfelder unterscheiden), 9 (Optional-Felder verfügbar).

Tech-Constraints (als Quality-AKs eingewoben): Field-Schema entspricht ADR-0046 (Name string, Funktion string, Foto image, Telefon telephone-Modul, E-Mail email, LinkedIn link).

Blocked by: nichts.

Slice 1b — Personen-Card auf Canvas-Seite (P2503-180)

Vertikaler Cut: View-Mode-Display + card-person SDC + CardPerson.jsx Canvas-Code-Component. Volle Vertikale durch alle drei Render-Layer — aber bewusst nur mit den Slice-1a-Pflichtfeldern (Name, Funktion, Foto, Tel). Outcome: Redakteur:in platziert Person-Block im Canvas, sieht sie live auf der Seite.

PRD-User-Stories covered: 3 (klickbarer tel:-Link), 10 (Canvas-Komponente platzierbar), 11 (Live-Vorschau nach Auswahl), 14 (Card-Familien-Konsistenz), 15 (kein Conditional-Schema), 16 (JsonApiClient + SWR), 17 (Kernel-renderable).

Tech-Constraints (als Quality-AKs eingewoben): SDC ist prop-driven (kein Slot, kein bubble-card-frame); Canvas-Component fetcht via projektweitem JsonApiClient + SWR; SDC ist im Kernel-Render-Test verifizierbar (Tag-Marker für PHPUnit-Group `card-person`).

Blocked by: Slice 1a (P2503-179) — braucht den Content-Type für JSON:API-Endpoint.

Slice 2 — Optional-Kontakt-Stack (P2503-181)

Vertikaler Cut: Erweiterung von SDC + View-Display um die optionalen Felder E-Mail und LinkedIn-URL inkl. Conditional-Render-Pattern. Outcome: Person mit voll gepflegten Kontakt-Optionen rendert alle drei Links (Tel + E-Mail + LinkedIn); Person ohne LinkedIn rendert sauber ohne leeren Link.

PRD-User-Stories covered: 2 (Tel/E-Mail/LinkedIn-Auswahl), 5 (no empty LinkedIn-Link), 6 (LinkedIn-Tab opens new browser window), 9 (Optional als Editor-Erfahrung).

Tech-Constraints (als Quality-AKs eingewoben): Conditional-Render in Twig via Existence-Check (keine leeren <a>-Tags); LinkedIn-Anchor trägt target="_blank" + rel="noopener".

Blocked by: Slice 1b (P2503-180) — Erweiterung baut auf das gleiche SDC.

Slice 3 — Vacancy-Sidebar-Recruiter (P2503-182)

Vertikaler Cut: config_pages.career_settings erhält neues Entity-Reference-Field field_default_recruiter auf node.person; Vacancy-Detail-Page-Template integriert die CardPerson-Canvas-Component an Sidebar-Position; Editor pflegt den Default-Recruiter zentral. Outcome: Heute hartcodierter Personio-Recruiter-Block wird durch zentral pflegbare Personen-Card abgelöst (Beispiel: Laura Gerardi).

PRD-User-Stories covered: 1 (Karriere-Interessent sieht Recruiter), 4 (Team-Karten-Pattern), 12 (Editor setzt Default-Recruiter), 13 (HR-Stakeholder-Ablösung des hartcodierten Blocks).

Tech-Constraints (als Quality-AKs eingewoben): ADR-0026 (Vacancy-Editorial-Ausschluss) wird respektiert — der Recruiter sitzt NICHT als Field auf node.vacancy, sondern als Site-globaler Default; granulare Vacancy↔Person-Verknüpfung bleibt Folge-Story.

Blocked by: Slice 2 (P2503-181) — braucht das vollständig gerenderbare SDC (Tel + E-Mail + LinkedIn) für realistische Recruiter-Card.

Slice 4 — Figma-Compliance + Responsive (P2503-183)

Vertikaler Cut: CSS-Polish auf card-person.css + Viewport-Tests bei 1280 px / 768 px / 375 px + Visual-Diff gegen Figma 62110-27008. Outcome: Card ist auf allen Viewports lesbar, matched Figma-Vorlage bei Desktop, Kontakt-Extension dokumentiert.

PRD-User-Stories covered: 13 (visual layout, responsive).

Tech-Constraints (als Quality-AKs eingewoben): Touch-Target-Größe ≥ 44×44 px für alle Kontakt-Links auf Mobile; Visual-Diff via solcom-figma-reviewer mit Score ≥ 90 %.

Blocked by: Slice 2 (P2503-181) — alle Felder müssen renderbar sein, bevor Visual-Compliance verifiziert werden kann. Kann parallel zu Slice 3 (P2503-182) laufen.

Dependency-Graph

P2503-179 (1a, Backend-CT)
   │
   ▼
P2503-180 (1b, Tracer-Frontend)
   │
   ▼
P2503-181 (2, Optional-Stack)
   │
   ├──► P2503-182 (3, Vacancy-Sidebar)   ──┐
   └──► P2503-183 (4, Figma + Responsive)  │  (parallel pickup nach Slice 2)
                                            │
                                            ▼
                                       F-170 done
      

Lineare Sequenz 1a → 1b → 2; danach 3 + 4 parallel. Insgesamt 4 Lane-Steps (Slice 3 und 4 zählen als eine Lane).

Quality-Gates pro Slice

  • Code-Review — PHPCS + PHPStan via lokales DDEV (Memory [[feedback_ci_quality_only_on_pr_merge]]: Azure-DevOps CI läuft erst auf PR-Open, nicht auf Direkt-Pushes).
  • Test-Coverage — pro Slice ein Test, der das beobachtbare Verhalten verifiziert (Kernel für SDC + JSX-Component-Test mit Mock-Fetch + Functional-Browser für End-to-End Field-Display + Config-Import-Kernel für Slice 3). PRD-Sektion #testing ist die Quelle.
  • QA-Plan — pro AK ein Click-Pfad im Story-Hub-#qa-plan-Block. Stories ohne QA-Plan werden vom Ralph-Loop übersprungen (ADR-0037).
  • Browser-Verify — pro UI-Slice Pflicht-Verify via agent-browser-Skill (Memory [[feedback_always_browser_verify]]). Slice 1a ist reiner Backend-Slice, daher Admin-UI-Verify per Drush + Admin-Login.
  • Figma-Diff — Slice 4 (P2503-183) verlangt Side-by-Side Figma-PNG ↔ Live-Screenshot, kein CSS-Computed-Style-Check (Memory [[feedback_visual_verify_side_by_side]]).

Referenzen

  • PRD vom 2026-05-25 — fachliche Quelle, 17 User-Stories, Modul-Schnitte, Testing-Decisions.
  • Story-Hub F-170 — 7 Akzeptanzkriterien in Stakeholder-Sprache, QA-Plan, Build-Workflow-Skill-Kette, Grilling-Log.
  • ADR-0046 — Topologie-Entscheidung (Content-Type + SDC-Sibling + Canvas-Component).
  • ADR-0009 — Prop-driven Card-Pattern (Quelle für SDC-Form).
  • ADR-0026 — Vacancy-Editorial-Exclusion (Constraint für Slice 3).
  • ADR-0004 — Conditional-Schema-Anti-Pattern (Constraint für SDC-Design in Slice 1b).
  • ADR-0037 — Ralph-Loop-Architektur, QA-Plan-Pflicht.
  • Jira-Sub-Tasks: P2503-179, P2503-180, P2503-181, P2503-182, P2503-183.