---
name: shopify-ciclo-vida-productos
description: "Cambia en lote el estado de tus productos entre borrador, activo y archivado (DRAFT → ACTIVE → ARCHIVED). Úsala cuando lances una colección de temporada o retires productos que ya no vas a vender."
---

## Propósito
Consulta los productos que coinciden con un filtro por etiqueta, proveedor, colección o estado y los pasa en lote a un estado de destino (DRAFT, ACTIVE o ARCHIVED, es decir, borrador, activo o archivado). Se usa para lanzamientos de temporada (DRAFT → ACTIVE), para retirar productos al final de la temporada (ACTIVE → ARCHIVED) y para preparar lanzamientos (crear como DRAFT y activar en una fecha).

## Requisitos
- Sesión autenticada de Shopify CLI: `shopify store auth --store <tu-tienda>.myshopify.com --scopes read_products,write_products`
- Las consultas se ejecutan con `shopify store execute`.
- Permisos (scopes) de la API: `read_products`, `write_products`

## Parámetros

| Parámetro | Tipo | Obligatorio | Por defecto | Descripción |
|-----------|------|-------------|-------------|-------------|
| store | string | sí | — | Dominio de la tienda (p. ej., tu-tienda.myshopify.com) |
| filter | string | sí | — | Filtro de búsqueda de productos (p. ej., `tag:summer-2026`, `vendor:Nike`, `status:draft`) |
| target_status | string | sí | — | Estado de destino: `ACTIVE`, `DRAFT` o `ARCHIVED` |
| dry_run | bool | no | true | Muestra una vista previa de los productos sin ejecutar mutaciones |
| format | string | no | human | Formato de salida: `human` o `json` |

## Seguridad

> ⚠️ Los productos ARCHIVED (archivados) se ocultan de todos los canales de venta y no se pueden comprar. Los productos ACTIVE (activos) quedan visibles para los clientes de inmediato. Ejecuta con `dry_run: true` para revisar la lista de productos antes de aplicar los cambios, sobre todo al pasar productos a ARCHIVED, porque es difícil revertirlo en lote.

## Pasos

1. **OPERACIÓN:** `products` — consulta
   **Entradas:** `query: <filter>`, `first: 250`, cursor de paginación
   **Resultado esperado:** Productos con `id`, `title`, `status`, `tags`; pagina hasta que `hasNextPage: false`

2. Quédate solo con los productos que NO están ya en `target_status`; omite los que ya tienen el estado correcto

3. **OPERACIÓN:** `productUpdate` — mutación
   **Entradas:** `id: <product_id>`, `status: <target_status>`
   **Resultado esperado:** `product { id, title, status }`, `userErrors`

## Operaciones GraphQL

```graphql
# products:query — validado con api_version 2025-01
query ProductsByFilter($query: String!, $after: String) {
  products(first: 250, after: $after, query: $query) {
    edges {
      node {
        id
        title
        status
        vendor
        tags
        publishedAt
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

```graphql
# productUpdate:mutation — validado con api_version 2025-01
mutation ProductUpdateStatus($input: ProductInput!) {
  productUpdate(input: $input) {
    product {
      id
      title
      status
    }
    userErrors {
      field
      message
    }
  }
}
```

## Seguimiento de la sesión

**Claude DEBE mostrar esta salida en cada etapa. Es obligatorio.**

**Al iniciar**, muestra:
```
╔══════════════════════════════════════════════╗
║  SKILL: Ciclo de vida de productos           ║
║  Tienda: <dominio de la tienda>              ║
║  Inicio: <YYYY-MM-DD HH:MM UTC>              ║
╚══════════════════════════════════════════════╝
```

**Después de cada paso**, muestra:
```
[N/TOTAL] <CONSULTA|MUTACIÓN>  <NombreOperación>
          → Parámetros: <resumen breve de las entradas clave>
          → Resultado: <conteo o resultado>
```

Si `dry_run: true`, antepón `[SIMULACIÓN]` a cada paso de mutación y no lo ejecutes.

**Al terminar**, muestra:

Para `format: human` (por defecto):
```
══════════════════════════════════════════════
RESUMEN DEL RESULTADO
  Productos encontrados:      <n>
  Ya tenían el estado:        <n> (omitidos)
  Estado actualizado:         <n>
  Errores:                    <n>
  Archivo:                    lifecycle_update_<fecha>.csv
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "shopify-ciclo-vida-productos",
  "store": "<dominio>",
  "started_at": "<ISO8601>",
  "completed_at": "<ISO8601>",
  "dry_run": true,
  "filter": "<filtro>",
  "target_status": "ACTIVE",
  "outcome": {
    "matched": 0,
    "skipped_already_correct": 0,
    "updated": 0,
    "errors": 0,
    "output_file": "lifecycle_update_<fecha>.csv"
  }
}
```

## Formato de salida
Archivo CSV `lifecycle_update_<YYYY-MM-DD>.csv` con las columnas:
`product_id`, `title`, `previous_status`, `new_status`, `vendor`, `tags`

## Manejo de errores
| Error | Causa | Solución |
|-------|-------|----------|
| `THROTTLED` | Se superó el límite de solicitudes de la API | Espera 2 segundos y reintenta hasta 3 veces |
| `userErrors` en productUpdate | Producto bloqueado o en un estado no válido | Registra el error, omite el producto y continúa |
| Ningún producto coincide con el filtro | Filtro demasiado específico | Termina con 0 coincidencias y sugiere ampliar el filtro |

## Buenas prácticas
- Antes de ejecutar, usa etiquetas para marcar los lotes de temporada (p. ej., etiqueta los productos con `launch:2026-05` antes de activarlos) para que el filtro sea preciso.
- El estado ARCHIVED saca los productos de todos los canales, incluida la tienda online, el POS y los botones de compra: confirma que eso es lo que quieres antes de ejecutarlo a gran escala.
- En catálogos grandes (más de 500 productos), el límite de solicitudes hará más lenta la ejecución; la skill reintenta automáticamente, pero los lotes grandes pueden tardar varios minutos.
- Antes de activar productos en DRAFT, combínala con `shopify-calidad-fichas-producto` para asegurarte de que tengan todos los campos necesarios.
