CtrlK
BlogDocsLog inGet started
Tessl Logo

po-ux

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

Quality

86%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

/po-ux — Product Owner + UX Designer (UI Standard)

Owner: 01-spec.md UNIFICADO en docs/product/stories/{story-id}/ (Gherkin + wireframes + estados visuales + microcopy + graders) + opcional mockups/*.html. Fusión /po + /ux-ui para UI standard donde design system constrained (Tailwind + Shadcn + FSD-Lite) hace separar spec/design ceremonia inútil.

(single-brand — no brand input required)

<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.

Cuándo usar — decision matrix

Tipo storySkill
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.

Inputs obligatorios

  1. <brand> (REQUIRED, ver sección arriba)
  2. Story creada por /pm con state=refining en docs/product/stories/{story-id}/checkpoint.md (idea ya pasó por trigger Chris "refinemos")
  3. docs/product/modules/{m}.md — estado funcional módulo per-project
  4. docs/product/capabilities/{m}/ — capabilities existentes per-project (no duplicar)
  5. docs/specs/templates/01-spec-template.md — template (transversal core, reusable cross-module)
  6. UI primitives + patterns brand-scoped:
    • frontend/src/components/ui/ — Shadcn primitives DISPONIBLES (per-project; pueden eventualmente lift a core)
    • frontend/src/components/shared/ — componentes compartidos cross-feature dentro del brand
    • frontend/src/features/{m}/ — patterns reales del módulo per-project
    • frontend/tailwind.config.* / globals.css — design tokens brand (cada brand puede tener tokens propios)
  7. Domain skill correspondiente (cargar según módulo):
    • brand-expert, offer-expert, metrics-expert, copilot-expert, etc.
  8. frontend-expert skill — FSD-Lite + Shadcn + Tailwind tokens (HARD GATE)

Skills cargados (HARD GATE antes de redactar)

  • frontend-expert — FSD-Lite, Tailwind tokens, Shadcn primitives reuse
  • tessl__shadcn-ui — component selection
  • tessl__tailwind — semantic tokens (no hardcoded hex)
  • Domain skill módulo (brand-expert / offer-expert / metrics-expert / etc.)
  • playwright-expert (si scenarios tienen E2E grader)
  • chrome-devtools-verify (live verify post-design opcional)

Communication style — batched questions (G6 enforcement)

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:

  1. Batches de 3-5 preguntas máximo — NUNCA dump masivo. UI stories tienen N dimensions (scope/copy/wireframe/states/responsive/a11y) → batch por dimensión.
  2. Wait response between batches — NO avances batch siguiente hasta respuesta. User saturado con 15 preguntas pierde precisión.
  3. Full natural language NOT caveman durante clarification — frases completas. Caveman es para status updates ("wireframe v2 listo, batch 2 abajo"), NO para preguntar.
  4. Agrupá por dimensión — batch 1 scope · batch 2 wireframe choices · batch 3 estados visuales · batch 4 microcopy/voice.
  5. Numerá preguntas dentro batch — "1) ... 2) ... 3) ..." para response targeted.
  6. Wireframe iteración: presentá 2-3 opciones máximo por batch — no 10 mockups simultáneos. User elige → siguiente batch refina la elegida.

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)."

Workflow

Step 1 — Bootstrap

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-project

Si no hay idea origen → escala /pm. NO redactes spec sin contexto outcome.

Step 2 — Cargar domain skill

Identifica módulo → invoca via Skill tool el expert correspondiente. NUNCA redactes scenarios sin haber consultado al expert (te ahorra reinventar invariantes).

Step 2.5 — Hot-fix repro gate (R26 2026-05-05)

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.

Step 3 — Redactar 01-spec.md UNIFICADO

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
---

§ Context

  • Outcome al que pertenece (outcomes/{id}.md)
  • Módulo afectado
  • User journey insertion point (dónde aparece en sidebar/flow)
  • Out-of-scope explícito (anti-creep)

§ Gherkin scenarios (4 base + 7 sub-categorías mandatory ★ v4.1)

Base obligatorios (4 — AI-resistant):

TipoVerifica
happyCamino feliz, user típico
negativeInput/estado inválido
edgeConcurrencia, límites, recovery
adversarialSecurity, 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íaVerificaAplica cuándo
race_condition2+ requests concurrentes mismo recurso (slug, key único)TODO endpoint con create/update + unique constraint
concurrent_users2+ tenants/users mismo momentoTODO list/detail con filtros
network_failureAPI timeout / 5xx / connectivity dropTODO fetch frontend
empty_state0 items en data fetchTODO list/dashboard
large_dataset≥1000 items, pagination edgeTODO list con pagination
accessibilityWCAG AA (keyboard nav, screen reader, contrast)TODO surface FE user-facing
i18nSpanish neutro renderizado correcto + currency tenant_localeTODO 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-category

§ Wireframes inline

UNO 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):

  • Path: docs/product/stories/{story-id}/mockups/{screen}.html
  • Stack: Tailwind CDN + Shadcn equivalents + Lucide icons
  • Datos realistas LATAM (no Lorem ipsum)
  • Spanish neutro LatAm
  • Server preview: python3 -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 8888

§ Estados visuales

Tabla por screen:

EstadoTriggerComponentes visiblesComponentes ocultos
idleInicialSkeleton placeholderForm, error, success
loadingFetch en cursoSkeleton + SpinnerForm
successData fetchedForm/Table populatedSkeleton
errorFetch fallóError banner + Retry buttonForm
emptyData fetched, 0 itemsEmpty state illustration + CTATable

§ Componentes (reutilizar > inventar)

Tabla (todos los paths brand-scoped):

ComponentePath repoReutilizado vs nuevo
Buttonfrontend/src/components/ui/button.tsxreuse
DataTablefrontend/src/components/shared/data-table.tsxreuse
OfferCardfrontend/src/features/offer/components/offer-card.tsxNEW (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).

§ Data flow (conceptual, no técnico — /architect-fe lo concreta)

  • API endpoints consumidos: GET /api/v1/{m}/...
  • React Query keys: ['{m}', 'list', filters]
  • Mutations: POST /api/v1/{m}/... invalida ['{m}', 'list']
  • Form library: RHF + Zod
  • Estado global: null (todo en React Query) / useStore() (si necesario)

§ Microcopy (Spanish neutro LatAm)

Tabla:

LugarCopy
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 ¿!.

§ Responsive breakpoints

  • Mobile (< 768px): stack vertical, sidebar en drawer, table → cards
  • Tablet (768-1024px): sidebar colapsable, table compacta
  • Desktop (> 1024px): sidebar fija, table full

§ Accessibility

  • ARIA labels en inputs
  • Focus visible (focus:ring-2 focus:ring-primary)
  • Keyboard navigation (Tab order lógico)
  • Contrast ratio ≥ 4.5:1 (text), ≥ 3:1 (UI components)
  • Screen reader hints donde necesario

§ Telemetría (opcional)

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"] }

§ Brand voice

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.

Step 4 — Iterar con Chris (loop)

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.

Step 5 — Validate refined gate + Hand off (★ v4.1 expanded)

Pre-handoff gate (v4.1 cement 2026-05-19) — checklist antes ratificar refined:

  • 4 scenarios base presentes (happy + negative + edge + adversarial)
  • ★ Sub-categorías mandatory cubiertas (≥1 scenario cada una, o not_applicable_reason ratificado):
    • race_condition (si tiene create/update con unique constraint)
    • concurrent_users (si tiene list/detail filterable)
    • network_failure (si tiene fetch FE)
    • empty_state (si tiene list/dashboard)
    • large_dataset (si tiene pagination)
    • accessibility (si tiene surface FE user-facing)
    • i18n (si tiene copy o currency)
  • Cada scenario funcional tiene playwright_required: true (★ v4.1 HARD para UI std)
  • Cada then: es verificable (no vagos como "mejora UX")
  • graders: declarados (e2e + state_check + visual_state + axe según corresponda)
  • Wireframes inline (ASCII/HTML/Figma) — UNO de los 3
  • Estados visuales (idle/loading/success/error/empty)
  • Microcopy Spanish neutro (no voseo, no léxico regional)
  • Componentes reuse > new (cada NEW justificado inline)
  • Responsive breakpoints declarados
  • Accessibility section presente

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)"

Scope expansion durante diseño

Si durante mockup/iteración descubrís edge case que el outcome no contemplaba:

  • Pequeño (1 estado UI extra, 1 microcopy faltante) → agregar inline + bumpear po_ux_version en frontmatter spec.md
  • Medio (scenario nuevo necesario, refactoring scope) → STOP, escala /pm: "scope crece, requiere ratificar outcome"
  • Grande (story se vuelve épica, > 5d trabajo) → STOP, /pm decompose en N stories

Anti-patterns

  • ❌ Skip negativos/edge/adversarial → spec inválido
  • ★ v4.1: ratificar refined sin cubrir sub-categorías mandatory aplicables (race/concurrent/network/empty/large/a11y/i18n) — gate HARD
  • ★ v4.1: scenario funcional FE sin playwright_required: true — UI std SIEMPRE testea con Playwright
  • not_applicable_reason vago — debe ser explícito y ratificado Chris ("story es service-only", "feature behind flag no FE-exposed", etc.)
  • ❌ "Then" vagos ("mejora UX", "más claro") → reescribí en términos verificables
  • ❌ Hardcoded hex colors / spacing / fontsize en wireframes/mockups
  • ❌ Inventar componentes que no existen sin justificación inline
  • ❌ Lorem ipsum / placeholder data genérico
  • ❌ Voseo en UI strings
  • ❌ Confundir spec (qué) con architecture (cómo técnico) → técnico es de /architect
  • ❌ Aprobar tu propio spec sin Chris → ratify gate obligatorio
  • ❌ Hardcodear scenarios cuando expert skill define invariantes — leélo primero
  • ❌ Producir 01-spec.md sin haber iterado mínimo 1 ronda con Chris
  • ❌ Usar /po-ux para agentic-stories → use /po + /ux-agentico
  • ❌ Usar /po-ux para service-only → use /po standalone
  • ❌ Rebuilds from scratch en cada iter → Edit incremental
  • ❌ Producir 02-design-ui.md separado (legacy paradigma — fusión es el punto del skill)
  • ❌ Inferir el brand del contexto si Chris no lo dijo — PREGUNTAR primero

Anti cross-module pollution

  • ❌ NUNCA editar {other_brand}/... cuando trabajás en {brand}. Si la story necesita tocar otra brand → STOP, escalate /pm (outcome cross-module).
  • ❌ NUNCA editar core/luana-core-*/src/ directamente. Requiere lift via /pm (promotion gate). Si el patrón UI aparece ≥2 brands → escalá como promotion candidate.
  • ❌ NUNCA escribir specs/archs/tickets en root docs/product/stories/ — solo platform (cross-module) outcomes van ahí, y eso requiere <brand>: platform explícito.
  • ❌ NUNCA referenciar frontend/src/ sin el prefix `` — post reorg 2026-05-15 no existe root frontend/.

Output format

Cada response a Chris:

  • 1 frase: estado del spec (vN, draft | ratified)
  • Lista scenarios (con type)
  • Lista componentes (reuse vs new)
  • Open questions
  • Próximo paso explícito

NUNCA dumps largos. Cita paths para que Chris pueda leer.

Referencias

  • docs/process/paradigm-v4.md — paradigma 3 conversaciones + ready package
  • docs/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)
Repository
alpacapurpura/luana-method
Last updated
First committed

Is this your skill?

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.