Expert en arquitectura completa Offer Studio (post-refactor field-contract-platform). Cubre fields/secciones/expertise/presets/relaciones/descripciones. Habla lenguaje de negocio. Use cuando user pide modificar/agregar/fusionar/eliminar offers, expertise (ExpertBusinessType), presets, secciones, fields, descripciones, conditional questions, flags, variant structures, relaciones (upsell/downsell/lead-magnet), o quiere entender cómo Nicolify maneja offers a cualquier nivel. Triggers: 'modificar oferta', 'cambiar preset', 'fusionar offers', 'combinar expertise', 'nuevo tipo de negocio', 'cambiar descripción', 'agregar campo a oferta', 'sección nueva', 'lead magnet', 'upsell', 'downsell', 'archetype', 'value level', 'ladder', 'offer ladder', 'tipo de oferta', 'ofertas latam', 'expertise', 'qué le pregunto al cliente'.
75
92%
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
User pide cambio offer → habla español neutro LATAM, tono experto negocio (microempresario LATAM), NO caveman. Caveman solo aplica al body de este SKILL.md (eficiencia tokens). Cuando dudes producto-side, preguntá antes de codear. Cuando dudes copy/descripción para microempresario, buscá web 2026 best practices según expertise (ej. "high-ticket coaching copy 2026", "lead magnet ecommerce 2026 LATAM").
L0 Pydantic Offer (offer/domain/offer.py) estructural · qué se persiste
L1 FieldContract (shared/domain/field_contract.py) semántico · cross-module
L2 SectionKey + SECTION_CATALOG (21 secciones) agrupación UX
L3 OfferArchetype (5 internal) fulfillment model
L4 OfferFormat (composite per archetype × EBT) refinamiento
L5 OfferValueLevel (5: lead_magnet/trial/core/premium/enterprise) pricing tier
L6 OfferLadderHints (per EBT × ValueLevel) ejemplo+precio típico
L7 OfferTypePreset (84 presets · facade archetype) UX user-vocabulary
L8 ConditionalQuestion (7) + on_yes_sections/flags preset refinement
L9 PresetFlag (6: SUPPORTS_CAPACITY, REQUIRES_START_DATE, DELIVERY_HYBRID, IS_LEAD_MAGNET, RECURRING_BILLING, HIGH_TICKET) downstream signal
L10 VariantStructure (4: PERIOD/SCOPE/TIER/PACK) editions
L11 ExpertBusinessType (9 EBTs · vive en tenant_profile BC) target marketDAG completo en .claude/rules/offer-catalogs.md. Lectura obligatoria primer turno.
| Capa | File |
|---|---|
| L0 | backend/src/modules/offer/domain/offer.py (Offer aggregate root) |
| L0 | backend/src/modules/offer/domain/details.py (specific_details polymorphic) |
| L0 | backend/src/modules/offer/domain/assets.py (deliverables/instructors/etc) |
| L0 | backend/src/modules/offer/domain/launch_edition.py (variant editions) |
| L1 | backend/src/modules/offer/domain/field_contract.py (OFFER_SECTION_MAP + OFFER_FIELD_OVERRIDES + derive) |
| L1 | shared/domain/field_contract.py (platform: walker, override merge, registry) |
| L2 | offer/domain/section_catalog.py (SectionKey enum + SECTION_CATALOG dict) |
| L3 | offer/domain/archetype_catalog.py (5 archetypes + sections per archetype) |
| L4 | offer/domain/format_catalog.py (composite, suitable_for[EBT]=0..1) |
| L5 | offer/domain/value_level_catalog.py |
| L6 | offer/domain/offer_ladder_hints.py (tuple key (EBT, ValueLevel) → hint) |
| L7 | offer/domain/offer_type_preset_catalog.py (84 presets) |
| L7 | offer/api/offer_type_presets.py (_CATALOG_VERSION) |
| L8 | QUESTION_REGISTRY en preset_catalog.py top |
| L9 | PresetFlag enum en preset_catalog.py |
| L10 | offer/domain/variant_structure_catalog.py (pure base, no FK out) |
| L11 | shared/domain/expert_business_type.py (9 EBTs + metadata) |
| L11 | shared/links/ports/tenant_profile.py (get_tenant_business_types) — NUNCA importar tenant_profile directo |
profesional_salud consultorio salud, cita
consultor_profesional servicio especializado B2B
coach_mentor programas transformación 1:1 / grupo
academia_infoproductor cursos / membresías / cohortes online
anfitrion_productor eventos / experiencias presenciales
agencia_freelance servicios productizados / proyectos
marca_ecommerce productos físicos / digitales D2C
negocio_local establecimiento físico
software_saas producto suscripción + tiersMulti-select. Tenants reales blendean 2-3.
SERVICIO one-shot delivery, custom scope
PROGRAMA cohort/transformación, fechas + curriculum
MEMBRESIA acceso recurrente, billing cycle
EXPERIENCIA evento puntual, fecha + lugar + capacity
PRODUCTO bien/digital, una venta cierra cicloUX NUNCA muestra archetype. User ve preset.
LEAD_MAGNET gratis · email opt-in · lead capture
TRIPWIRE < tenant-baseline · ramp warmer
CORE oferta principal · revenue base
PREMIUM > 3× core · alta conversión bajo volumen
ENTERPRISE custom B2B · nego 1:1is_lead_magnet derivado del value_level (NUNCA checkbox lateral).
Universales (9):
IDENTITY, STRATEGY, PSYCHOLOGY, PROMISE, VALUE_STACK,
INSTRUCTORS, KNOWLEDGE, CLOSING, GALLERY
Archetype-specific (7):
PRODUCT_DETAILS, SUBSCRIPTION_DETAILS, EVENT_DETAILS, PRICING,
PROGRAM_DETAILS, SERVICE_DETAILS, RESOURCES
LATAM mass-market (5):
FAQ, TESTIMONIALS, PORTFOLIO, LOCATION, PLATFORM_DETAILSEliminadas: METHODOLOGY, CREDENTIALS (duplicaban brand).
3 secciones referencian módulos externos:
LOCATION → scheduling/event-types via scheduling_event_type_idPRICING → accepted_payment_providers via connectionsINSTRUCTORS → brand-studio/team via instructors[]→ Skill offer-type-preset-expert (peer skill). Usa esa para presets puros. Si trabaja también field-level, ambas. Pasos canon:
OFFER_TYPE_PRESET_CATALOG en offer_type_preset_catalog.py._CATALOG_VERSION en offer/api/offer_type_presets.py.tests/architecture/test_offer_type_preset_catalog_completeness.py.docs/domains/offer/offer-type-preset-catalog.md.sales_agent.knowledge_builder + landing_service._select_landing_archetype_from_preset + PresetBadge.tsx.shared/links/ports/offer.get_offer_type_preset(id). Catalog reactive.Decisión PRODUCTO. Antes:
Si user persiste fusión:
expert_business_type.py enum + tests.business_type= al EBT consolidador.tenant_profile.business_types (script + Alembic data migration).frontend/src/features/tenant-profile/types/tenant-profile.ts (string-literal union mirror).Riesgo alto: tenants con offers persisted en preset_id cuyo preset asume EBT viejo se quiebran. Pregunta primero: ¿hay tenants en prod con ese EBT?
Cross-cutting. Sigue .claude/rules/offer-catalogs.md → "Extending the system". Pasos:
expert_business_type.py._BUSINESS_TYPE_SLUG en preset completeness test.offer-type-preset-catalog.md.frontend/src/features/tenant-profile/types/tenant-profile.ts (string-literal union + frozen array).offer_ladder_hints.py — agregá entries (NEW_EBT, value_level) para cada nivel típico.Pregunta primero: tenants en prod con ese EBT? Si sí, NO elimines:
Si zero tenants: drop enum, drop presets de ese EBT, drop tests. Bump catalog version.
Workflow refactor field-contract-platform:
offer/domain/offer.py, details.py, assets.py, launch_edition.py.OFFER_SECTION_MAP (offer/domain/field_contract.py).OFFER_FIELD_OVERRIDES con metadata semántica:
"specific_details.<field>": Override(
priority=80,
is_required_semantic=True,
human_question_es="¿…?", # copilot conversacional
expects="hint formato", # opcional
gate="specific_details.archetype", # opcional precondición
label_es="Etiqueta", # FE label
archetype_filter=("PRODUCTO",), # si specific
),ADD COLUMN IF NOT EXISTS) si Pydantic field se persiste como column. Si vive en JSONB (specific_details, platform_details), zero migration.tests/architecture/test_field_contract_platform.py + tests/architecture/test_field_contract_completeness.py. Pydantic ⊆ FieldContract enforced.frontend/src/features/offer-studio/schemas/<section>.schema.ts) — agregar field declaración Zod. Schema FE NO se deriva auto; debe alinearse manual.propose_field_updates valida con catalog derivado, picks up auto. next_question algoritmo Fase 09 ranking deja entrar el field auto. Si gate / priority te interesa = setealo en Override.docs/domains/offer/.SectionKey.X enum value + entry en SECTION_CATALOG con label_es/subtitle_es/help_text_es/icon_name/scope/kind.scope: OFFER_LEVEL / EDITION_LEVEL / MIXED.kind: SINGLETON / COLLECTION (collection requiere landing + detail FE views).OFFER_SECTION_MAP (paths → SectionKey.X.value).archetype_catalog.py per archetype: ¿qué archetypes incluyen esta sección?offer_type_preset_catalog.py base_sections o conditional question on_yes.<section-slug>.schema.ts + register en SECTION_REGISTRY._CATALOG_VERSION bump.Antes:
SELECT COUNT(*) FROM products WHERE <field> IS NOT NULL.status=DEPRECATED en field overrides → consumers filtran auto).User dice "no se entiende" / "muy técnico" / "querés que pregunte distinto":
.claude/rules/spanish-text.md) — sin voseo. tú, no vos.human_question_es: pregunta natural conversational (Fase 09). Ej. "¿Cuál es la promesa principal de esta oferta?" (no "Promesa principal: …")._CATALOG_VERSION si tocaste preset o section.test_offer_editable_fields_baseline.py, test_buyer_persona_editable_fields_baseline.py) usan descripciones — actualizar baseline si descripcion cambia (intentional).Modelo persistido:
Offer.upsell_product_id: UUID | NoneOffer.downsell_product_id: UUID | NoneOffer.includes_offers: list[UUID] (bundle/pack)Para LEAD_MAGNET → CORE relation:
value_level=LEAD_MAGNET en lead magnet offer.upsell_product_id=<lead_magnet_offer.id> en core offer.API: POST /api/v1/offer/products/{id} + payload incluye estos UUID. No hay tabla join — son foreign keys directos.
Cambios sugeridos al user:
includes_offers.upsell_product_id / downsell_product_id.Decisión PRODUCTO:
upsell_product_id, downsell_product_id, includes_offers) que apuntan a la otra.deleted_at = now()).landing.offer_id references si aplica.NO existe API "merge offers" — operación manual via DB ad hoc o script. Si user pide repetir → considerar build feature.
Question:
QUESTION_REGISTRY en offer_type_preset_catalog.py.on_yes_sections (additive only) / on_yes_flags.conditional_question_ids=("new_q",) en presets aplicables.Flag:
PresetFlag enum.Bump version + tests.
offer/domain/variant_structure_catalog.py es pure base (zero outbound FK refs — arch test bloquea). 4 estructuras hoy: PERIOD (cohorts fechadas) / SCOPE (alcance customizable) / TIER (basic/pro/premium) / PACK (cantidades).
Agregar:
OfferArchetype.supported_structures mapping.| Cambio | Copilot acción | Porqué |
|---|---|---|
| Nuevo field en Pydantic + Override | zero-touch | Catalog derivado de FieldContract — auto pick-up |
Cambio human_question_es | zero-touch | next_question lee runtime del registry |
Cambio gate / priority | zero-touch | Algoritmo lee runtime |
Cambio can_propose=False | zero-touch | propose_field_updates filtra auto |
| Nuevo SectionKey | zero-touch | section_catalog reactive |
| Nuevo preset / question / flag | zero-touch + bump _CATALOG_VERSION | Cliente cache version-keyed |
| Drop section / field DEPRECATED | zero-touch | Status filter en projection auto |
| Nuevo PresetFlag con consumer landing/sales-agent nuevo | Add explicit branch en consumer | Flag ≠ silencioso si downstream depende |
| Nuevo EBT | FE mirror update obligatorio | Sin mirror, onboarding picker oculta |
| Cambio descripción que rompe baseline tests | Update baseline test | Intencional, debe mostrarse en commit msg |
Resumen: arquitectura post-Fase-09 hace que la mayoría de cambios sean reactive auto — copilot lee registry runtime. Solo bloqueantes manuales: nuevos PresetFlags con consumer, nuevos EBTs (FE mirror), baseline test updates.
shared/links/ports/offer.py. DDD arch test falla.OfferArchetype labels en wizard UX (es internal).Override.lead_magnet=True checkbox separado — derivar de value_level == LEAD_MAGNET._GROUP_MAP hardcoded en FE (channel-display etc.) — consume useFormatCatalog/useArchetypeCapabilities/useValueLevelCatalog.business_types en BrandIdentity. Vive en tenant_profile BC desde 2026-04-20.OFFER_SECTION_MAP — arch test cross-cutting Pydantic ⊆ FieldContract falla.archetype que no existe en ARCHETYPE_CATALOG.cd backend && .venv/bin/pytest tests/architecture/ -x -q --tb=short
cd backend && .venv/bin/pytest tests/architecture/test_offer_type_preset_catalog_completeness.py -x -q
cd backend && .venv/bin/pytest tests/modules/copilot/test_conversational_questioning.py tests/modules/copilot/test_guided_question_hint.py -x -q
cd frontend && npx vitest run src/__tests__/architecture/507 BE arch + 38 FE arch baseline post-Fase-09. Sin regression.
Antes de codear, si:
docs/domains/offer/INDEX.md (todos los docs offer)docs/domains/offer/catalogs-consolidation.md (5 axes base)docs/domains/offer/offer-type-preset-catalog.md (preset layer)docs/domains/offer/variant-structure-catalog.md (variants)docs/_archive/pre-sdd-2026-05-04/refactors/field-contract-platform/DESIGN.md (FieldContract platform — Fase 04-09)docs/_archive/pre-sdd-2026-05-04/refactors/field-contract-platform/LEARNINGS.md (descubrimientos cross-fase).claude/rules/offer-catalogs.md (DAG rules).claude/rules/spanish-text.md (neutro LATAM sin voseo).claude/rules/tdd-mandatory.md (test antes impl)offer-type-preset-expert — narrow scope sobre L7 preset catalog. Si user solo agrega/modifica preset → invocá ese. Si user mezcla layers (preset + field + section) → este skill maneja toda la cascada.references/offer-catalogs.md — 7 catalogs DAG, BE→FE flow, hooks, agregar workflow, anti-patternsreferences/form-runtime-array.md — array field cards/split mode, autosave preservedd31f7bc
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.