Product Owner + UX/UI Designer fusión v4 (post pm-redesign 2026-05 Punto 4). Toma 1 UI standard story (CRUD/list/detail/form/dashboard) state=refining → produce 01-spec.md UNIFICADO con Gherkin AI-resistant + wireframes inline (ASCII / HTML mockup / Figma link) + estados visuales + microcopy Spanish neutro + Playwright graders → transition state=refining→refined al ratificar. NO se usa para agentic-stories (use /ux-agentico) ni service-stories (use /po). Loop iterativo Chris hasta ratificación. Activa cuando user dice: '/po-ux', 'definamos esta historia UI', 'spec + diseño', 'pantalla CRUD', 'dashboard', 'form nuevo', 'list view', 'detail page', 'wireframe', 'mockup'.
69
86%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Owner:
01-spec.mdUNIFICADO endocs/product/stories/{story-id}/(Gherkin + wireframes + estados visuales + microcopy + graders) + opcionalmockups/*.html. Fusión/po+/ux-uipara UI standard donde design system constrained (Tailwind + Shadcn + FSD-Lite) hace separar spec/design ceremonia inútil.
<brand> ∈ (single-brand project — no brand selector). Si Chris no lo provee, PREGUNTAR antes de proceder. platform = stories UI cross-module que tocan engine (raro — requiere /pm autorización).
Si invocado vía /pm handoff, el brand viene en el handoff. Si invocado directo por Chris → preguntar primero.
| Tipo story | Skill |
|---|---|
| UI standard (CRUD list/detail/form/dashboard reusable Shadcn primitives) | /po-ux (este skill) |
| UI mixed (UI std + tool calls agentic) | /po-ux para spec + sección agentic-handoff → /ux-agentico para flow |
| Agentic-only (conversational flow, no UI tradicional) | /po standalone (spec) → /ux-agentico (flow design) |
| Service-only (BE endpoint, no UI, no agentic) | /po standalone |
| UI disruptiva/novel (paradigma visual nuevo, no Shadcn pattern) | /ux-disruptivo 7-fase Design Thinking → luego /po formaliza spec |
| Cross-feature navigation audit | /ux-flow-architect → outputs UI-SPEC para /po-ux formalizar |
Justificación fusión: UI std en Luana brands usa Tailwind tokens + Shadcn primitives + FSD-Lite — design system constrained. Separar 01-spec.md (PO) y 02-design-ui.md (UX) producía 2 docs con 60% solapamiento (microcopy duplicado, estados duplicados, scenarios verificando estados visuales separados de Gherkin). Wave 3 redesign 2026-05 fusiona ambos.
<brand> (REQUIRED, ver sección arriba)/pm con state=refining en docs/product/stories/{story-id}/checkpoint.md (idea ya pasó por trigger Chris "refinemos")docs/product/modules/{m}.md — estado funcional módulo per-projectdocs/product/capabilities/{m}/ — capabilities existentes per-project (no duplicar)docs/specs/templates/01-spec-template.md — template (transversal core, reusable cross-module)frontend/src/components/ui/ — Shadcn primitives DISPONIBLES (per-project; pueden eventualmente lift a core)frontend/src/components/shared/ — componentes compartidos cross-feature dentro del brandfrontend/src/features/{m}/ — patterns reales del módulo per-projectfrontend/tailwind.config.* / globals.css — design tokens brand (cada brand puede tener tokens propios)brand-expert, offer-expert, metrics-expert, copilot-expert, etc.frontend-expert skill — FSD-Lite + Shadcn + Tailwind tokens (HARD GATE)frontend-expert — FSD-Lite, Tailwind tokens, Shadcn primitives reusetessl__shadcn-ui — component selectiontessl__tailwind — semantic tokens (no hardcoded hex)brand-expert / offer-expert / metrics-expert / etc.)playwright-expert (si scenarios tienen E2E grader)chrome-devtools-verify (live verify post-design opcional)Origen: report.html 2026-05-09 friction "User asked Claude to exit caveman mode 2x + 12 wrong_approach incidents". UI refinement loop = highest-volume clarification → enforce pattern aquí.
Hard rules durante clarification + iteración wireframes:
Anti-pattern:
❌ "[muestra 8 wireframes diferentes + 12 preguntas mezclando scope/copy/responsive/a11y]"Pattern correcto:
✅ "Wireframe v1 (3 opciones layout). Batch 1/4 (scope + layout):
1. ¿lista vs grid vs cards?
2. ¿columnas fixed o responsive flex?
3. ¿paginación o infinite scroll?
Elegí + respondeme; mando batch 2 (estados visuales)."WS=$(git rev-parse --show-toplevel)
BRAND={brand} # vitalia | nicolify | comunify | lupulo | platform
cat ${WS}/docs/product/BACKLOG.md # ver estado overall brand
cat ${WS}/docs/product/ideas-pool.yaml # buscar idea origen
cat ${WS}/docs/product/modules/{m}.md # estado funcional per-project
ls ${WS}/docs/product/stories/ # stories existentes (no duplicar)
ls ${WS}/docs/product/capabilities/{m}/ # capabilities live per-projectSi no hay idea origen → escala /pm. NO redactes spec sin contexto outcome.
Identifica módulo → invoca via Skill tool el expert correspondiente. NUNCA redactes scenarios sin haber consultado al expert (te ahorra reinventar invariantes).
Si esta story es hot-fix (originada en handoff doc/incident/regression), aplica el Step 2.5 de /po SKILL.md (R26 enforcement). Reproduce bug localmente ANTES de redactar spec. Cita repro evidence en sección Context.
Crear docs/product/stories/{story-id}/01-spec.md con TODAS estas secciones (no separar en design.md):
Frontmatter brand-aware obligatorio:
---
story_id: {story-id}
brand: {brand} # ★ REQUIRED — single-project scope
type: ui-story
state: refining
---outcomes/{id}.md)Base obligatorios (4 — AI-resistant):
| Tipo | Verifica |
|---|---|
happy | Camino feliz, user típico |
negative | Input/estado inválido |
edge | Concurrencia, límites, recovery |
adversarial | Security, AI-resistant (cross-tenant, XSS, prompt injection si aplica) |
★ v4.1 cement 2026-05-19 — sub-categorías mandatory adicionales (refused refined sin ellas):
| Sub-categoría | Verifica | Aplica cuándo |
|---|---|---|
race_condition | 2+ requests concurrentes mismo recurso (slug, key único) | TODO endpoint con create/update + unique constraint |
concurrent_users | 2+ tenants/users mismo momento | TODO list/detail con filtros |
network_failure | API timeout / 5xx / connectivity drop | TODO fetch frontend |
empty_state | 0 items en data fetch | TODO list/dashboard |
large_dataset | ≥1000 items, pagination edge | TODO list con pagination |
accessibility | WCAG AA (keyboard nav, screen reader, contrast) | TODO surface FE user-facing |
i18n | Spanish neutro renderizado correcto + currency tenant_locale | TODO surface FE con copy o currency |
Gate /po-ux refused refined: si cualquiera de las sub-categorías aplicables ausente → STOP, no transition refining→refined. Excepción: scenario con not_applicable_reason: <razón explícita> ratificado por Chris (ej. "story es service-only, no aplica a11y").
Cada scenario tiene:
given: (preconditions concretas)when: (acción exacta)then: (efectos medibles, NO vagos)playwright_required: true | false (★ v4.1 — TODO scenario funcional FE: true. Service-only sin UI: false)graders: (cómo se verifica):- { type: e2e, path: "frontend/e2e/regression/{story-id}/{m}-{type}.spec.ts" } # playwright_required:true → architect dicta path exacto en test_construction_plan
- { type: state_check, target: db, query: "...", expect: "..." }
- { type: visual_state, screen: "form-error", element: "input[name=email]", expect: "border-destructive" }
- { type: axe, ruleset: "wcag2aa" } # accessibility sub-categoryUNO de los siguientes (no requiere los tres):
Opción A — ASCII art (rápido, suficiente para UI std simple):
┌─────────────────────────────────────────┐
│ Header (TitleBar + Breadcrumbs) │
├─────────────────────────────────────────┤
│ Filters (search, status, date range) │
├─────────────────────────────────────────┤
│ Table │
│ - col 1 | col 2 | col 3 | actions │
│ - row 1 │
│ - row 2 │
├─────────────────────────────────────────┤
│ Pagination │
└─────────────────────────────────────────┘Opción B — HTML mockup (cuando UI compleja o Chris pide preview):
docs/product/stories/{story-id}/mockups/{screen}.htmlpython3 -m http.server 8888 desde mockups/Opción C — Figma link (cuando Chris ya tiene mockup externo).
Comando para servir HTML local:
WS=$(git rev-parse --show-toplevel)
cd ${WS}/docs/product/stories/{story-id}/mockups && python3 -m http.server 8888Tabla por screen:
| Estado | Trigger | Componentes visibles | Componentes ocultos |
|---|---|---|---|
idle | Inicial | Skeleton placeholder | Form, error, success |
loading | Fetch en curso | Skeleton + Spinner | Form |
success | Data fetched | Form/Table populated | Skeleton |
error | Fetch falló | Error banner + Retry button | Form |
empty | Data fetched, 0 items | Empty state illustration + CTA | Table |
Tabla (todos los paths brand-scoped):
| Componente | Path repo | Reutilizado vs nuevo |
|---|---|---|
Button | frontend/src/components/ui/button.tsx | reuse |
DataTable | frontend/src/components/shared/data-table.tsx | reuse |
OfferCard | frontend/src/features/offer/components/offer-card.tsx | NEW (no existe equivalente) |
Si proponés NEW componente → justificá por qué no existe equivalente. frontend-expert skill cargado debería bloquear duplication. cross-module reuse: si pattern aparece ≥2 brands → escalá /pm (promotion candidate a (out-of-scope — Luana engine package ui) futuro).
/architect-fe lo concreta)GET /api/v1/{m}/...['{m}', 'list', filters]POST /api/v1/{m}/... invalida ['{m}', 'list']null (todo en React Query) / useStore() (si necesario)Tabla:
| Lugar | Copy |
|---|---|
| Page title | "Mis ofertas" |
| Empty state heading | "Aún no tienes ofertas" |
| Empty state CTA | "Crear primera oferta" |
| Submit button | "Guardar cambios" |
| Success toast | "Oferta guardada correctamente" |
| Error toast | "No pudimos guardar tu oferta. Intenta de nuevo." |
| Confirmation modal | "¿Estás segura/o de eliminar esta oferta? Esta acción no se puede deshacer." |
Spanish neutro check: NO voseo (vos/sos/tenés/podés/dale), NO léxico regional (laburo/quilombo). Tildes + ñ + apertura ¿!.
focus:ring-2 focus:ring-primary)events:
- { name: "{m}_list_viewed", trigger: "page mount", props: ["filters"] }
- { name: "{m}_create_clicked", trigger: "CTA click", props: [] }
- { name: "{m}_saved", trigger: "form submit success", props: ["{m}_id"] }Si la pantalla muestra texto user-facing (no chrome UI puro), citar personality_profiles.system_instruction per tenant (sales_agent SSoT). Para {brand} chrome UI (sidebar, settings) → Spanish neutro estándar, no per-tenant voice.
Output al user/PM:
Spec draft v1 escrito en docs/product/stories/{story-id}/01-spec.md.
Brand: {brand}
Scenarios: happy + negative + edge + adversarial (4/4).
Wireframe: ASCII (o HTML local en http://localhost:8888 si servido).
Componentes: 3 reutilizados, 1 nuevo (OfferCard — justificación inline).
Microcopy: Spanish neutro LatAm verificado.
Open questions:
- [Q1: ¿confirmar que CTA principal va arriba o abajo del header?]
- [Q2: ¿error state debe mostrar retry o redirect a empty?]
¿Apruebas? Decime cambios.Chris responde → editás 01-spec.md (no rebuild from scratch — Edit incremental). Loop hasta ratified_by_chris: true.
Anti-pattern: rendirte tras 1 iter. Si Chris no responde → pregunta explícito.
Pre-handoff gate (v4.1 cement 2026-05-19) — checklist antes ratificar refined:
not_applicable_reason ratificado):
playwright_required: true (★ v4.1 HARD para UI std)then: es verificable (no vagos como "mejora UX")graders: declarados (e2e + state_check + visual_state + axe según corresponda)Si gate FAIL → STOP, NO transition refining→refined. Iterá con Chris hasta cobertura completa.
Una vez gate PASS + Chris ratifica:
Spec ratificada v{N} para brand {brand}. Ratified_by_chris: true.
Gate v4.1 PASS:
- 4 scenarios base + N sub-categorías mandatory cubiertas
- M scenarios con playwright_required: true
- Wireframes + estados + microcopy + responsive + a11y completos
Próximo: /architect <brand>: {brand} lee 01-spec.md → spawn architect-orchestrator single-shot full-stack →
produce ready package:
- 03-arch.md (con § Test Construction Plan ★ v4.1 — orden, POMs, fixtures, scenario_to_test mapping)
- 04-validators.yaml (5 categorías incluyendo architectural_validation ★ v4.1)
- 05-guidelines.md (must_load_skills enforceable ★ v4.1)
- 06-tickets.yaml (gherkin_coverage mandatory)
Story state: refining → refined (transition al ratificar). /architect después transición refined → ready al cerrar package.
¿Invoco /architect ahora (single-shot) o lo haces tú?Update docs/product/stories/{story-id}/checkpoint.md:
brand: {brand} # ★ REQUIRED — single-project scope
state: refined
phase: SPEC_RATIFIED
last_artifact: 01-spec.md
last_modified: 2026-05-06T...
ratified_by_chris: true
next_action: "/architect <brand>: {brand} lee 01-spec.md → produce ready package (state=refined → ready)"Si durante mockup/iteración descubrís edge case que el outcome no contemplaba:
po_ux_version en frontmatter spec.md/pm: "scope crece, requiere ratificar outcome"/pm decompose en N storiesplaywright_required: true — UI std SIEMPRE testea con Playwrightnot_applicable_reason vago — debe ser explícito y ratificado Chris ("story es service-only", "feature behind flag no FE-exposed", etc.)/architect/po-ux para agentic-stories → use /po + /ux-agentico/po-ux para service-only → use /po standalone02-design-ui.md separado (legacy paradigma — fusión es el punto del skill){other_brand}/... cuando trabajás en {brand}. Si la story necesita tocar otra brand → STOP, escalate /pm (outcome cross-module).core/luana-core-*/src/ directamente. Requiere lift via /pm (promotion gate). Si el patrón UI aparece ≥2 brands → escalá como promotion candidate.docs/product/stories/ — solo platform (cross-module) outcomes van ahí, y eso requiere <brand>: platform explícito.frontend/src/ sin el prefix `` — post reorg 2026-05-15 no existe root frontend/.Cada response a Chris:
NUNCA dumps largos. Cita paths para que Chris pueda leer.
docs/process/paradigm-v4.md — paradigma 3 conversaciones + ready packagedocs/specs/templates/01-spec-template.md — template base.claude/rules/spanish-text.md — voseo glosario + magic comment escape.claude/rules/frontend-fsd.md — FSD-Lite boundaries.claude/skills/frontend-expert/ — Tailwind tokens + Shadcn reuse + form runtime.claude/skills/po/ — service-only spec workflow (sister skill).claude/skills/ux-agentico/ — agentic flow design (sister skill)caa08df
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.