opción

plan-orchestrate

affaan-m/ECC affaan-m/ECC

Lee un documento de plan, lo desglosa en pasos, diseña una cadena de agentes para cada paso a partir del catálogo de ECC y genera indicaciones personalizadas listas para pegar u orquestar sin ejecutarlas.

...Expandir todo
9
Tiempo actualizado 4 de octubre de 2026

Planificar y coordinar

Conecta un documento de plan con /orchestrate custom generando una llamada lista para pegar por cada paso. La habilidad es únicamente generativa: nunca ejecuta /orchestrate. El usuario pega cada línea cuando esté listo.

Cuándo activarla

  • El usuario tiene un documento de plan de varios pasos (PRD, RFC, plan de implementación) y quiere llevarlo a cabo mediante /orchestrate.
  • El usuario dice «coordinar este plan», «muéstrame indicaciones de /orchestrate para cada paso» o «crea cadenas para este plan».
  • Existe un plan paso a paso, pero el usuario no quiere seleccionar manualmente los agentes para cada paso.

Omitir cuando:

  • El trabajo consiste en un único paso ad hoc → llamar directamente a /orchestrate custom.
  • El plan es ilegible o está vacío. La mera ausencia de numeración explícita no es motivo para omitirlo; véase el caso extremo «Sin pasos claros» más abajo.

Entradas

 [--lang=python|typescript|go|rust|cpp|java|kotlin|flutter|auto] [--scope=all|step:|range:-] [--dry-run]
  • — obligatorio; ruta relativa o absoluta (se acepta@docs/... ).
  • --lang — variante de idioma del revisor; el valor por defecto es «auto» (detectado a partir del proyecto).
  • --scope — limita los pasos emitidos; por defecto, «all».
  • --dry-run — muestra solo la descomposición y la justificación de la cadena; no emite las indicaciones finales.

Formato oficial de /orchestrate (no se debe desviar)

{ORCH_CMD} custom ",,...," ""

Donde {ORCH_CMD} se determina en la Fase 0 (véase más abajo). La cadena de comando en la salida emitida siempre utiliza una forma concreta: nunca ambas, nunca un marcador de posición.

  • «custom» es una cadena secuencial; el HANDOFF de cada agente alimenta al siguiente.
  • Lista de agentes separados por comas. Se prefiere que no haya espacios; se tolera un espacio.
  • No existen los indicadores --mode / --gate / --agents=...; nunca los inventes.
  • Los nombres de los agentes proceden del catálogo de esta habilidad. Las comillas dobles incrustadas en la descripción de la tarea se escapan como \".

Formato de instalación de ECC y espacios de nombres

Dos formatos de instalación determinan el prefijo tanto del comando de barra como de cada nombre de agente. Ambos DEBEN estar sincronizados: un formato por salida, nunca mezclados:

Que denote el directorio de inicio de Claude Code: ~/.claude en macOS/Linux, %USERPROFILE%\.claude en Windows. Resuélvelo tal y como la plataforma anfitriona resuelve el directorio de inicio del usuario (no codifiques ~ de forma fija).

Forma Detección {ORCH_CMD} Formato del nombre del agente
Instalación del complemento (1.9.0+) Existe/plugins/marketplaces/everything-claude-code/ /everything-claude-code:orchestrate everything-claude-code:
Instalación básica heredada Lo anterior no existe; los archivos del agente se encuentran en /agents/ /orchestrate

Por qué es importante: en la instalación mediante plugin, los agentes se registran como everything-claude-code:tdd-guide. Los nombres sin prefijo obligan a realizar una coincidencia aproximada, lo que falla de forma intermitente en llamadas paralelas. En la instalación heredada, las formas con prefijo no se registran y fallan directamente.

Catálogo de agentes disponibles (hay que elegir entre estos)

General:

  • planificador — reformulación de requisitos, descomposición de riesgos, planificación de pasos
  • architect — arquitectura, diseño del sistema, propuestas de refactorización
  • tdd-guide — escribir pruebas → implementar → cobertura superior al 80 %
  • revisor de código — revisión genérica del código
  • revisor de seguridad: auditoría de seguridad, OWASP, fugas de información confidencial
  • limpiador de refactorización: código muerto, duplicados, limpieza de clases «knip»
  • actualizador de documentación — documentación, mapa de código, README
  • docs-lookup — consultas a la API de bibliotecas de terceros (Context7)
  • e2e-runner — orquestación de pruebas de extremo a extremo
  • database-reviewer — esquema de PostgreSQL, migración, rendimiento
  • harness-optimizer — configuración del entorno de pruebas de agentes locales
  • loop-operator — bucles autónomos de larga duración
  • chief-of-staff — clasificación multicanal (rara vez encaja en los pasos del plan)

Resolventes de errores de compilación:

  • build-error-resolver (genérico) / cpp-build-resolver / go-build-resolver / java-build-resolver / kotlin-build-resolver / rust-build-resolver / pytorch-build-resolver

Revisores de código:

  • python-reviewer / typescript-reviewer / go-reviewer / rust-reviewer / cpp-reviewer / java-reviewer / kotlin-reviewer / flutter-reviewer

Un nombre de agente mal escrito provoca un error en /orchestrate. Comprueba esta lista antes de enviarlo.

Cómo funciona

Fase 0: detección del modo ECC y del lenguaje

  1. Leer . Si falta o está vacío, informar y detener el proceso.

  2. Detectar el formulario de instalación de ECC una vez y fijarlo en ECC_MODE. Algoritmo (ejecutar en orden, detenerse en la primera coincidencia):

    1. Si existe /plugins/marketplaces/everything-claude-code/ → ECC_MODE=plugin.
    2. En caso contrario, si existe /agents/ y contiene al menos un archivo de agente ECC (p. ej., tdd-guide.md, code-reviewer.md) → ECC_MODE=legacy.
    3. En caso contrario → se establece por defecto ECC_MODE=legacy y se muestra una advertencia de una línea al principio de la salida: > Advertencia: no se ha podido detectar la instalación de ECC; se utiliza por defecto el modo legacy. Si utilizas la instalación del plugin, edita los prefijos manualmente.
    4. Si existen ambos marcadores (instalación mixta), prevalece el complemento: el espacio de nombres del complemento es el único que resuelve los nombres de los agentes sin coincidencia aproximada.

    A partir de este momento, cada línea generada utiliza el prefijo correspondiente tanto en el comando de barra como en cada nombre de agente. Nunca se generarán ambas formas en la misma salida.

  3. Resolver --lang. Cuando sea «auto», ejecutar una detección compatible con múltiples lenguajes:

    • Marcadores de detección: pyproject.toml / uv.lock / requirements.txt → python; package.json → typescript; go.mod → go; Cargo.toml → rust; CMakeLists.txt o archivos *.cpp de nivel superior → cpp; pom.xml / build.gradle (Java) → java; build.gradle.kts o Kotlin de nivel superior → kotlin; pubspec.yaml → flutter.
    • Desempate en caso de poliglotismo: si coincide más de un marcador, elige el lenguaje cuyos archivos fuente superen en número a los demás (cuéntalos mediante `git ls-files`, excluyendo `vendor/`, `node_modules/`, `dist/`, `build/`, `.venv/`, los archivos generados y los entornos de prueba evidentes). En caso de empate o cuando ningún lenguaje supere el 60 % de los archivos fuente, establece lang=unknown.
    • Si no coincide ningún marcador → establece lang=unknown.
    • lang=unknown es un indicador —no es un nombre de agente—. Las reglas 4 y 5 de la fase 2 lo convierten en revisor de código / resolutor de errores de compilación en el momento de la composición de la cadena.
  4. Detectar un subperfil de PyTorch: cuando lang=python y cualquiera de los archivos pyproject.toml / requirements.txt / uv.lock declare una dependencia de torch, establece pytorch=true. Esto solo afecta a la selección de la cadena de compilación (regla de la Fase 2 más abajo); el revisor sigue siendo python-reviewer.

  5. Normaliza cualquier nombre de agente declarado en el plan: si el texto del plan hace referencia a los agentes mediante su forma con prefijo de complemento (p. ej., everything-claude-code:tdd-guide), elimina el prefijo para obtener el nombre básico del catálogo antes de validar o componer cadenas. La reasignación del prefijo solo se produce en el momento de la salida según ECC_MODE (Fase 4). Nunca dejes que un nombre con prefijo previo entre en la composición de la cadena, ya que se produciría una doble asignación de prefijos en el modo plugin.

Fase 1 — Descomponer los pasos

Identifica las «unidades de paso» por orden de prioridad:

  1. Numeración explícita: ## Paso N / ### Fase N / ## N. ... / lista ordenada de nivel superior.
  2. Una columna «Paso» en una tabla.
  3. ----bloques separados con encabezados que comienzan por un verbo.
  4. En caso contrario, trata cada H2 como un paso.

Por paso, extrae el ID (a partir de 1), el título (≤ 80 caracteres), la intención (1-3 frases) y las etiquetas.

Fase 2 — Etiquetar y seleccionar la cadena

Etiqueta por intención (se permiten varias etiquetas; la cadena se construye a partir de la principal más las secundarias apiladas):

Las palabras clave que figuran a continuación se comparan sin distinguir entre mayúsculas y minúsculas. Se admiten planes multilingües al comparar las raíces de las palabras en cualquier idioma, siempre que el significado coincida con las palabras clave en inglés enumeradas.

Etiqueta Palabras clave Cadena predeterminada
diseño arquitectura, diseño, elegir, evaluar, RFC planificador, arquitecto
plan plan, desglose, hito planificador
impl implementar, construir, añadir, crear, portar guía de TDD,-revisor
prueba prueba, cobertura, e2e, integración guía-TDD, ejecutor-e2e
refactorizar refactorización, limpieza, eliminación de duplicados, división arquitecto, refactorizador-limpiador,-revisor
migración migrar, actualizar, reescribir, portar arquitecto, guía de TDD,-revisor
b.d. esquema, migración, índice, SQL, Postgres, Alembic, SQLModel revisor de bases de datos,-revisor
seguridad cifrado, autenticación, secretos, OWASP, datos de carácter personal revisor de seguridad,-revisor
compilación compilación, compilación, error de lint, CI -resolución-de-compilación (recurre a resolución-de-errores-de-compilación)
documentación documentación, archivo «readme», mapa de código, registro de cambios actualizador de documentación
búsqueda búsqueda, referencia, uso de la API búsqueda en la documentación
revisión revisión, auditoría, verificación -revisor, revisor de código
bucle bucle, autónomo, watchdog operador de bucle

Reglas de composición de cadenas:

  1. Selección de la etiqueta principal: cuando un paso coincide con varias etiquetas, la primera en el orden de la tabla (la parte superior de la tabla = máxima prioridad) es la principal; el resto son secundarias. Las reglas de composición 2 y 3 que figuran a continuación tratan explícitamente combinaciones específicas de varias etiquetas; en los demás casos, se añaden cadenas secundarias en el orden de la tabla de etiquetas.
  2. impl + security → tdd-guide,-reviewer,security-reviewer.
  3. impl + db → tdd-guide,database-reviewer,-reviewer.
  4. Elimina los duplicados de la cadena resultante (conserva la primera aparición). Por ejemplo, «review + lang=unknown» daría como resultado «code-reviewer,code-reviewer» tras aplicar la regla 5; la eliminación de duplicados lo reduce a «code-reviewer».
  5. -reviewer se resuelve como code-reviewer cuando lang=unknown.
  6. -build-resolver se resuelve como build-error-resolver cuando lang=unknown. Caso especial: si en la Fase 0 se establece pytorch=true, utilice pytorch-build-resolver para las cadenas de compilación independientemente de . No existe «python-build-resolver»; «--lang=python » sin «pytorch=true» se resuelve como «build-error-resolver».
  7. Pasos sin etiqueta: si no coincide ninguna palabra desencadenante, establece la cadena en «code-reviewer» y escribe «no se ha encontrado ninguna etiqueta»; cadena predeterminada «solo revisión » según la «Justificación de la cadena».
  8. Longitud de la cadena ≤ 4 tras la deduplicación. Si se supera, se descarta la etiqueta más débil (primero«lookup» y «docs» ).
  9. No emparejes «planner» y «architect» en una cadena «impl» (desperdicio de tokens). Emparejalos solo en pasos de diseño.
  10. Los pasos etiquetados como «impl», «refactor» o «migration» terminan con un agente de clase «reviewer »: cualquiera de los siguientes: «-reviewer», «code-reviewer», «security-reviewer» o «database-reviewer». El revisor más específico del dominio ocupa la última posición (por ejemplo, «impl+security» de la regla 2 termina con «security-reviewer»; «impl+db» de la regla 3 termina con «-reviewer», ya que «database-reviewer» ya controla la migración en una fase anterior de la cadena). Los pasos de prueba y compilación están controlados por sus propios validadores (e2e-runner y el resolutor de compilación, respectivamente) y no requieren un revisor adicional.

Fase 3 — Comprimir la descripción de la tarea

Cada debe:

  • Ser autónoma (el primer agente no necesita tener abierto el documento del plan).
  • Comenzar con [Plan: #step-].
  • Incluir entre 1 y 3 criterios de aceptación verificables.
  • Incluir una cláusula de alcance (Fuera de alcance: ...) solo si el plan declara una para este paso. Heredarla tal cual. Si el plan no contiene ninguna declaración de fuera de alcance, omitir la cláusula por completo; no inventar ninguna.
  • Tenga entre 200 y 600 caracteres; una sola línea; el carácter «» debe escaparse como «\»; no incluya saltos de línea literales.

Fase 4 — Salida

Genera Markdown utilizando el formato determinado por ECC_MODE. La salida utiliza un único formato en todo momento: cada {ORCH_CMD} y cada nombre de agente se representa con el prefijo correspondiente de la Fase 0. No emitas ambos formatos; no incluyas instrucciones del tipo «esta es la forma del complemento» o «elimina el prefijo» en la salida generada.

Reglas concretas de representación:

  • {ORCH_CMD} = /everything-claude-code:orchestrate en el plugin, /orchestrate en el modo heredado.
  • {AGENT(nombre)} = everything-claude-code: en el plugin, en el modo heredado.
  • La columna «Chain» de la tabla de resumen utiliza la misma representación {AGENT(name)}.
  • Los bloques bash por paso contienen únicamente el comando ejecutable. No hay comentarios del tipo # plugin form ni # legacy form: el formato es implícito y uniforme en toda la salida.

Estructura de la salida:

# Resultado de Plan-Orchestrate 
**Plan**: ``
**Lenguaje**: ``
**Modo ECC**: ``
**Pasos**: 
**Ámbito**: 

## Resumen de los pasos

| # | Título | Etiquetas | Cadena |
|---|---|---|---|
| 1 | ... | impl, db | `{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}` |
| ... | | | |

---

## Paso 1 — 

**Objetivo**: <1–3 sentences>
**Etiquetas**: <a, b>
**Justificación de la cadena**: <why this chain; which agent closes the loop>

```bash
{ORCH_CMD} custom "{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}" "[Plan: docs/foo.md#step-1] <compressed task description>; Aceptación: <1–3 items>; Fuera del alcance: <…>"
```
</code></pre>
<blockquote>
<p>La notación <code>{ORCH_CMD}</code> y <code>{AGENT(...)}</code> anterior describe la sustitución que realiza esta habilidad en tiempo de ejecución. El código Markdown emitido realmente contiene las cadenas resueltas, nunca los marcadores de posición.</p>
</blockquote>
<p>Añade un bloque final de «Ejecución por lotes» que agrupe los comandos de cada paso en orden, para que el usuario pueda pegarlos todos a la vez. <strong>Omite el bloque de ejecución por lotes en el modo de solo resumen</strong> (véase el caso extremo «Plan extenso»): cuando solo se genera la tabla de resumen, no hay comandos por paso que agrupar.</p>
<h3>Fase 5 — Autocomprobación (ejecutar antes de generar)</h3>
<ul>
<li><input disabled="" type="checkbox"> Cada agente de cada cadena procede del catálogo (tras eliminar cualquier prefijo <code>«everything-claude-code:»</code> que apareciera en el plan; véase la fase 0, paso 5).</li>
<li><input disabled="" type="checkbox"> Los <code>{ORCH_CMD}</code> resueltos y todos <code> los {AGENT(...)}</code> resueltos utilizan el <strong>mismo</strong> formato (<code>complemento</code> o <code>heredado</code>); nunca se mezclan en una misma salida.</li>
<li><input disabled="" type="checkbox"> No quedan anotaciones del tipo <code> «# forma de plugin</code> » o <code> «# forma heredada»</code>, ni instrucciones de «eliminar el prefijo» en la salida generada.</li>
<li><input disabled="" type="checkbox"> No hay campos inventados como <code>--mode</code> / <code>--gate</code> / <code>--agents=...</code> </li>
<li><input disabled="" type="checkbox"> Cada descripción de tarea ocupa una sola línea, entre comillas dobles, con el carácter <code> «»</code> escapado.</li>
<li><input disabled="" type="checkbox"> Cada descripción de tarea comienza con <code>[Plan: <path>#step-<id>]</code> e incluye Aceptación (1–3 elementos). La cláusula <code>«Fuera del alcance:»</code> solo está presente cuando se hereda del plan.</li>
<li><input disabled="" type="checkbox"> No hay agentes duplicados en ninguna cadena tras la deduplicación de la Fase 2.</li>
<li><input disabled="" type="checkbox"> Longitud de la cadena ≤ 4.</li>
<li><input disabled="" type="checkbox"> Los pasos etiquetados como<code>«impl», «refactor»</code><code>o</code><code>«migration»</code> terminan con un agente de clase «reviewer» (<code><lang>-reviewer</code>, <code>code-reviewer</code>, <code>security-reviewer</code> o <code>database-reviewer</code>). <code>«test»</code> y <code>«build»</code> están exentos; véase la regla 10 de la Fase 2.</li>
<li><input disabled="" type="checkbox"> Los pasos sin etiqueta generan <code>un «code-reviewer»</code> con la justificación <code>«no se ha encontrado ninguna etiqueta que coincida»; cadena predeterminada de solo revisión</code>.</li>
<li><input disabled="" type="checkbox"> La tabla de resumen enumera todos los pasos del plan, independientemente de <code>--scope</code>.</li>
<li><input disabled="" type="checkbox"> El recuento de bloques de detalle por paso coincide con el <code>--scope</code> resuelto (plan completo cuando <code>--scope=all</code>; un bloque para <code>el paso n</code>; tamaño del rango para <code>el rango a-b</code>). En el modo de solo resumen, no se emiten bloques por paso ni el bloque «Batch».</li>
</ul>
<h2>Casos extremos</h2>
<ul>
<li><strong>Si no hay pasos claros</strong>: se prefiere la división H2/H3; si sigue habiendo ambigüedad, se informa de que «no se han detectado pasos estructurados» junto con el esquema del documento y se pide al usuario que confirme la ejecución según el esquema.</li>
<li><strong>Plan extenso (>1500 líneas)</strong>: pasar <strong>al modo «solo resumen»</strong>; generar únicamente la tabla de resumen y pedir al usuario que acote el alcance con <code>--scope</code> antes de volver a ejecutar la tarea para obtener detalles. En este modo, omitir los bloques de detalles por paso y el bloque de ejecución por lotes.</li>
<li><strong>Paso demasiado amplio</strong> (p. ej., «completar todo el trabajo de backend»): no forzar una única cadena. Sugerir la división en N.a y N.b y proponer dicha división.</li>
<li><strong>El plan declara agentes</strong> (poco frecuente): primero <strong>elimina cualquier prefijo <code>«everything-claude-code:»</code></strong> para obtener el nombre básico del catálogo (Fase 0, paso 5) y, a continuación, valida el resultado con el catálogo. Sustituye los agentes no válidos y explica el motivo en «Justificación de la cadena». El nombre básico se vuelve a prefijar en el momento de la salida según <code>ECC_MODE</code>.</li>
<li><strong>Proyecto políglota en el que <code>--lang=auto</code> no puede elegir un ganador</strong>: establece <code>lang=unknown</code>; el revisor se resuelve como <code>«code-reviewer»</code> y el resolutor de compilación como <code>«build-error-resolver</code>». Menciona la opción de reserva en «Justificación de la cadena».</li>
</ul>
<h2>Ejemplos</h2>
<h3>Ejemplo 1 — Modo de complemento, plan de Python</h3>
<p>Entrada:</p>
<pre><code>plan-orchestrate @docs/plan/example-feature.md --lang=python
</code></pre>
<p>Fragmento de la salida esperada:</p>
<pre><code class="language-markdown">## Paso 2 — Cifrar campos sensibles de UserProfile

**Objetivo**: Introducir un tipo `EncryptedString` de SQLAlchemy y cifrar con AES-GCM los campos `birth_datetime` y `location` antes de su almacenamiento; cargar la clave desde una variable de entorno.
**Etiquetas**: impl, seguridad, db
**Justificación de la cadena**: Ruta de escritura sensible desde el punto de vista de la seguridad, por lo que `security-reviewer` cierra la cadena; `database-reviewer` valida la migración de Alembic; `python-reviewer` se encarga de la tipificación y del cumplimiento de la PEP 8.

```bash
/everything-claude-code:orchestrate custom "everything-claude-code:tdd-guide,everything-claude-code:database-reviewer,everything-claude-code:python-reviewer,everything-claude-code:security-reviewer" «[Plan: docs/plan/example-feature.md#step-2] Implementar el tipo EncryptedString de SQLAlchemy y migrar las columnas UserProfile.birth_datetime/location; clave de ENV APP_DB_KEY; Aceptación: superadas las pruebas de cifrado/descifrado de ida y vuelta; actualización/reversión de Alembic sin errores en una base de datos vacía; ausencia de texto sin cifrar en la base de datos tras la migración; Fuera del alcance: lógica de uso compartido de perfiles entre inquilinos"
```
</code></pre>
<h3>Ejemplo 2 — Modo heredado, mismo paso</h3>
<p>Si se detectara <code>ECC_MODE=legacy</code>, se emitiría el mismo paso como un único comando uniforme (sin formas con prefijo de plugin en ninguna parte de la salida):</p>
<pre><code class="language-bash">/orchestrate custom "tdd-guide,database-reviewer,python-reviewer,security-reviewer" "[Plan: docs/plan/example-feature.md#step-2] ..."
</code></pre>
<p>Los dos ejemplos anteriores ilustran <strong>las dos salidas posibles</strong> para dos entornos diferentes. Una única invocación de la skill produce solo una de ellas, de principio a fin.</p>
<h2>Notas</h2>
<ul>
<li>Solo generativo. Nunca invoques <code>/orchestrate</code> desde dentro de esta habilidad.</li>
<li>Adapta el idioma del documento del plan para las descripciones de las tareas (los nombres de los agentes siempre se mantienen en inglés).</li>
<li>No insertes líneas «Co-Authored-By» ni emojis en la salida, a menos que el usuario lo solicite explícitamente.</li>
</ul>                                </div>
                                <div class="skilldetailsL1_skillmd">
                                    <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="Ver en GitHub" target="_blank" rel="nofollow"
                                        aria-label="Ver en GitHub" class="skilldetails_toGitHub">
                                        <span>Ver en GitHub</span>
                                        <b></b>
                                    </a>
                                    <pre><code>---
name: plan-orchestrate
description: Reads a plan document, decomposes it into steps, designs a per-step agent chain from the ECC catalogue, and emits ready-to-paste /orchestrate custom prompts without executing them.
---

# Plan Orchestrate

Bridge a plan document to `/orchestrate custom` by emitting one ready-to-paste invocation per step. The skill is generative only — it never executes `/orchestrate`. The user pastes each line when ready.

## When to Activate

- User has a multi-step plan document (PRD, RFC, implementation plan) and wants to drive it through `/orchestrate`.
- User says "orchestrate this plan", "give me orchestrate prompts for each step", "compose chains for this plan".
- A step-by-step plan exists but the user does not want to manually pick agents per step.

Skip when:
- The work is one ad-hoc step → call `/orchestrate custom` directly.
- The plan is unreadable or empty. Lack of explicit numbering alone is not a skip condition — see the "No clear steps" edge case below.

## Inputs

```
<plan-doc-path> [--lang=python|typescript|go|rust|cpp|java|kotlin|flutter|auto] [--scope=all|step:<n>|range:<a>-<b>] [--dry-run]
```

- `<plan-doc-path>` — required; relative or absolute path (`@docs/...` accepted).
- `--lang` — reviewer language variant; defaults to `auto` (detected from project).
- `--scope` — limits emitted steps; defaults to `all`.
- `--dry-run` — print decomposition + chain rationale only; do not emit final prompts.

## Authoritative `/orchestrate` shape (do not deviate)

```
{ORCH_CMD} custom "<agent1>,<agent2>,...,<agentN>" "<task description>"
```

Where `{ORCH_CMD}` is determined in Phase 0 (see below). The command string in the emitted output **always uses one concrete form** — never both, never a placeholder.

- `custom` is a sequential chain; each agent's HANDOFF feeds the next.
- Comma-separated agent list. No spaces preferred; one space tolerated.
- No `--mode` / `--gate` / `--agents=...` flags exist — never invent them.
- Agent names come from the catalogue in this skill. Embedded double quotes in the task description are escaped as `\"`.

## ECC install form and namespacing

Two install forms determine the prefix on **both** the slash command and every agent name. The two MUST stay in sync — one form per output, never mixed:

Let `<claude-home>` denote the Claude Code home directory: `~/.claude` on macOS/Linux, `%USERPROFILE%\.claude` on Windows. Resolve it the way the host platform resolves the user home directory (do not hardcode `~`).

| Form | Detection | `{ORCH_CMD}` | Agent name format |
|---|---|---|---|
| Plugin install (1.9.0+) | `<claude-home>/plugins/marketplaces/everything-claude-code/` exists | `/everything-claude-code:orchestrate` | `everything-claude-code:<name>` |
| Legacy bare install | Above absent; agent files under `<claude-home>/agents/` | `/orchestrate` | `<name>` |

Why this matters: under the plugin install, agents register as `everything-claude-code:tdd-guide`. Bare names force fuzzy matching, which fails intermittently under parallel calls. Under legacy, the prefixed forms are not registered and fail outright.

## Available agent catalogue (must pick from these)

General:
- `planner` — requirement restatement, risk decomposition, step planning
- `architect` — architecture, system design, refactor proposals
- `tdd-guide` — write tests → implement → 80%+ coverage
- `code-reviewer` — generic code review
- `security-reviewer` — security audit, OWASP, secret leakage
- `refactor-cleaner` — dead code, duplicates, knip-class cleanup
- `doc-updater` — documentation, codemap, README
- `docs-lookup` — third-party library API lookups (Context7)
- `e2e-runner` — end-to-end test orchestration
- `database-reviewer` — PostgreSQL schema, migration, performance
- `harness-optimizer` — local agent harness configuration
- `loop-operator` — long-running autonomous loops
- `chief-of-staff` — multi-channel triage (rarely a fit for plan steps)

Build error resolvers:
- `build-error-resolver` (generic) / `cpp-build-resolver` / `go-build-resolver` / `java-build-resolver` / `kotlin-build-resolver` / `rust-build-resolver` / `pytorch-build-resolver`

Code reviewers:
- `python-reviewer` / `typescript-reviewer` / `go-reviewer` / `rust-reviewer` / `cpp-reviewer` / `java-reviewer` / `kotlin-reviewer` / `flutter-reviewer`

A misspelled agent name fails `/orchestrate`. Cross-check against this list before emitting.

## How It Works

### Phase 0 — Detect ECC mode + language

1. Read `<plan-doc-path>`. If missing or empty, report and stop.
2. Detect ECC install form once and freeze it into `ECC_MODE`. Algorithm (run in order, stop at the first match):
   1. If `<claude-home>/plugins/marketplaces/everything-claude-code/` exists → `ECC_MODE=plugin`.
   2. Else if `<claude-home>/agents/` exists and contains at least one ECC agent file (e.g. `tdd-guide.md`, `code-reviewer.md`) → `ECC_MODE=legacy`.
   3. Else → default to `ECC_MODE=legacy` and emit a one-line warning at the top of the output: `> Warning: could not detect ECC install; defaulting to legacy form. If you use the plugin install, edit the prefixes manually.`
   4. If both markers exist (mixed install), `plugin` wins — the plugin namespace is the only one that resolves agent names without fuzzy matching.

   From this point on, every emitted line uses the matching prefix on **both** the slash command and every agent name. **Never emit both forms in the same output.**
3. Resolve `--lang`. When `auto`, run a polyglot-aware detection:
   - Probe markers: `pyproject.toml` / `uv.lock` / `requirements.txt` → python; `package.json` → typescript; `go.mod` → go; `Cargo.toml` → rust; `CMakeLists.txt` or top-level `*.cpp` → cpp; `pom.xml` / `build.gradle` (Java) → java; `build.gradle.kts` or top-level Kotlin → kotlin; `pubspec.yaml` → flutter.
   - **Polyglot tie-break**: if more than one marker matches, pick the language whose source files outnumber the others (count via `git ls-files`, excluding `vendor/`, `node_modules/`, `dist/`, `build/`, `.venv/`, generated files, and obvious test fixtures). On a tie or when no language exceeds 60% of source files, set `lang=unknown`.
   - No marker matched → set `lang=unknown`.
   - `lang=unknown` is a sentinel — it is **not** an agent name. Phase 2 rules 4 and 5 turn it into `code-reviewer` / `build-error-resolver` at chain composition time.
4. Detect a **PyTorch sub-profile**: when `lang=python` and any of `pyproject.toml` / `requirements.txt` / `uv.lock` declares a dependency on `torch`, set `pytorch=true`. This only affects `build` chain selection (Phase 2 rule below); the reviewer remains `python-reviewer`.
5. **Normalize any agent names declared in the plan**: if the plan text references agents by their plugin-prefixed form (e.g. `everything-claude-code:tdd-guide`), strip the prefix to get the bare catalogue name before validating or composing chains. Re-prefixing happens only at output time per `ECC_MODE` (Phase 4). Never let a pre-prefixed name flow into chain composition — it would double-prefix in plugin mode.

### Phase 1 — Decompose steps

Identify "step units" in priority order:

1. Explicit numbering: `## Step N` / `### Phase N` / `## N. ...` / top-level ordered list.
2. A "Step" column in a table.
3. `---`-separated blocks with verb-led headings.
4. Otherwise treat each H2 as one step.

Per step extract `id` (1-based), `title` (≤ 80 chars), `intent` (1–3 sentences), `tags`.

### Phase 2 — Tag and pick chain

Tag by intent (multi-tag allowed; chain built from primary + stacked secondaries):

Trigger words below are matched case-insensitively. Multilingual plans are supported by matching the word stems in any language as long as the meaning aligns with the listed English trigger words.

| Tag | Trigger words | Default chain |
|---|---|---|
| `design` | architecture, design, choose, evaluate, RFC | `planner,architect` |
| `plan` | plan, breakdown, milestone | `planner` |
| `impl` | implement, build, add, create, port | `tdd-guide,<lang>-reviewer` |
| `test` | test, coverage, e2e, integration | `tdd-guide,e2e-runner` |
| `refactor` | refactor, cleanup, dedupe, split | `architect,refactor-cleaner,<lang>-reviewer` |
| `migration` | migrate, upgrade, rewrite, port | `architect,tdd-guide,<lang>-reviewer` |
| `db` | schema, migration, index, SQL, Postgres, alembic, sqlmodel | `database-reviewer,<lang>-reviewer` |
| `security` | encrypt, auth, secret, OWASP, PII | `security-reviewer,<lang>-reviewer` |
| `build` | build, compile, lint failure, CI | `<lang>-build-resolver` (falls back to `build-error-resolver`) |
| `docs` | docs, readme, codemap, changelog | `doc-updater` |
| `lookup` | lookup, reference, API usage | `docs-lookup` |
| `review` | review, audit, verify | `<lang>-reviewer,code-reviewer` |
| `loop` | loop, autonomous, watchdog | `loop-operator` |

Chain composition rules:
1. **Primary tag selection**: when a step matches multiple tags, the **first one in table order** (top of the table = highest priority) is the primary; the rest are secondaries. Composition rules 2 and 3 below handle specific multi-tag combinations explicitly; otherwise, append secondary chains in tag table order.
2. `impl` + `security` → `tdd-guide,<lang>-reviewer,security-reviewer`.
3. `impl` + `db` → `tdd-guide,database-reviewer,<lang>-reviewer`.
4. **Deduplicate** the resulting chain (preserve first occurrence). E.g. `review` + `lang=unknown` would yield `code-reviewer,code-reviewer` after rule 5; deduplication collapses it to `code-reviewer`.
5. `<lang>-reviewer` resolves to `code-reviewer` when `lang=unknown`.
6. `<lang>-build-resolver` resolves to `build-error-resolver` when `lang=unknown`. **Special case**: if Phase 0 set `pytorch=true`, use `pytorch-build-resolver` for `build` chains regardless of `<lang>`. There is no `python-build-resolver`; `--lang=python` without `pytorch=true` resolves to `build-error-resolver`.
7. **Zero-tag steps**: if no trigger word matches, set chain to `code-reviewer` and write `no tag matched; default review-only chain` under "Chain rationale".
8. Chain length ≤ 4 after deduplication. If exceeded, drop weakest tag (`lookup` and `docs` first).
9. Do not pair `planner` and `architect` in an `impl` chain (token waste). Pair them only on `design` steps.
10. Steps tagged `impl`, `refactor`, or `migration` end with a **reviewer-class** agent — any of `<lang>-reviewer`, `code-reviewer`, `security-reviewer`, or `database-reviewer`. The most domain-specific reviewer wins the tail position (e.g. rule 2's `impl+security` ends with `security-reviewer`; rule 3's `impl+db` ends with `<lang>-reviewer` because `database-reviewer` already gates the migration earlier in the chain). `test` and `build` steps are gated by their own validators (`e2e-runner` and the build resolver respectively) and do not require an additional reviewer.

### Phase 3 — Compress task description

Each emitted `<task description>` must:
- Be self-contained (the first agent does not need the plan document open).
- Start with `[Plan: <path>#step-<id>]`.
- Include 1–3 verifiable Acceptance criteria.
- Include a Scope guard (`Out of scope: ...`) **only if the plan declares one for this step**. Inherit verbatim. If the plan has no out-of-scope statement, omit the clause entirely — do not invent one.
- Be 200–600 characters; one line; embedded `"` escaped as `\"`; no literal newlines.

### Phase 4 — Output

Emit Markdown using **the form determined by `ECC_MODE`**. The output uses one form throughout — every `{ORCH_CMD}` and every agent name is rendered with the matching prefix from Phase 0. **Do not emit both forms; do not include "this is plugin form" / "strip the prefix" instructions in the rendered output.**

Concrete rendering rules:

- `{ORCH_CMD}` = `/everything-claude-code:orchestrate` under `plugin`, `/orchestrate` under `legacy`.
- `{AGENT(name)}` = `everything-claude-code:<name>` under `plugin`, `<name>` under `legacy`.
- The overview-table "Chain" column uses the same `{AGENT(name)}` rendering.
- Per-step bash blocks contain only the runnable command. **No `# plugin form` or `# legacy form` comments** — the form is implicit and uniform across the whole output.

Output structure:

````markdown
# Plan-Orchestrate Result

**Plan**: `<path>`
**Lang**: `<detected-or-given>`
**ECC mode**: `<plugin | legacy>`
**Steps**: <N>
**Scope**: <all | step:n | range:a-b>

## Steps overview

| # | Title | Tags | Chain |
|---|---|---|---|
| 1 | ... | impl, db | `{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}` |
| ... | | | |

---

## Step 1 — <title>

**Intent**: <1–3 sentences>
**Tags**: <a, b>
**Chain rationale**: <why this chain; which agent closes the loop>

```bash
{ORCH_CMD} custom "{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}" "[Plan: docs/foo.md#step-1] <compressed task description>; Acceptance: <1–3 items>; Out of scope: <…>"
```
````

> The `{ORCH_CMD}` and `{AGENT(...)}` notation above describes the substitution this skill performs at runtime. The actual emitted Markdown contains the resolved strings, never the placeholders.

Append a final "Batch execution" block aggregating every step's command in order so the user can paste them all at once. **Skip the Batch block in overview-only mode** (see "Large plan" edge case): when only the overview table is being emitted, there are no per-step commands to aggregate.

### Phase 5 — Self-check (run before emitting)

- [ ] Every agent in every chain comes from the catalogue (after stripping any `everything-claude-code:` prefix that appeared in the plan; see Phase 0 step 5).
- [ ] Resolved `{ORCH_CMD}` and every resolved `{AGENT(...)}` use the **same** form (`plugin` or `legacy`) — never mixed in one output.
- [ ] No `# plugin form` / `# legacy form` annotations and no "strip the prefix" instructions remain in the rendered output.
- [ ] No invented `--mode` / `--gate` / `--agents=...` fields.
- [ ] Each task description is single-line, double-quoted, with embedded `"` escaped.
- [ ] Each task description begins with `[Plan: <path>#step-<id>]` and includes Acceptance (1–3 items). The `Out of scope:` clause is present only when inherited from the plan.
- [ ] No duplicate agent in any chain after Phase 2 dedup.
- [ ] Chain length ≤ 4.
- [ ] Steps tagged `impl`/`refactor`/`migration` end with a reviewer-class agent (`<lang>-reviewer`, `code-reviewer`, `security-reviewer`, or `database-reviewer`). `test` and `build` are exempt — see Phase 2 rule 10.
- [ ] Zero-tag steps emit `code-reviewer` with the rationale `no tag matched; default review-only chain`.
- [ ] Overview table lists every step in the plan, regardless of `--scope`.
- [ ] Per-step detail block count matches the resolved `--scope` (full plan when `--scope=all`; one block for `step:n`; range size for `range:a-b`). In overview-only mode, no per-step blocks and no Batch block are emitted.

## Edge cases

- **No clear steps**: prefer H2/H3 splitting; if still ambiguous, report "no structured steps detected" with the document outline and ask the user to confirm running by outline.
- **Large plan (>1500 lines)**: enter **overview-only mode** — emit only the overview table and ask the user to narrow with `--scope` before re-running for details. In this mode, skip per-step detail blocks and skip the Batch execution block.
- **Step too broad** (e.g. "complete all backend work"): do not force a single chain. Suggest splitting into N.a and N.b and propose a split.
- **Plan declares agents** (rare): first **strip any `everything-claude-code:` prefix** to get the bare catalogue name (Phase 0 step 5), then validate against the catalogue. Replace invalid agents and explain under "Chain rationale". The bare name is re-prefixed at output time per `ECC_MODE`.
- **Polyglot project where `--lang=auto` cannot pick a winner**: set `lang=unknown`; reviewer resolves to `code-reviewer` and build resolver to `build-error-resolver`. Mention the fallback under "Chain rationale".

## Examples

### Example 1 — Plugin mode, Python plan

Input:
```
plan-orchestrate @docs/plan/example-feature.md --lang=python
```

Excerpt of expected output:
````markdown
## Step 2 — Encrypt sensitive UserProfile fields

**Intent**: Introduce an `EncryptedString` SQLAlchemy type and AES-GCM encrypt `birth_datetime` / `location` before persistence; load the key from an environment variable.
**Tags**: impl, security, db
**Chain rationale**: Security-sensitive write path, so `security-reviewer` closes the chain; `database-reviewer` validates the alembic migration; `python-reviewer` covers typing and PEP 8.

```bash
/everything-claude-code:orchestrate custom "everything-claude-code:tdd-guide,everything-claude-code:database-reviewer,everything-claude-code:python-reviewer,everything-claude-code:security-reviewer" "[Plan: docs/plan/example-feature.md#step-2] Implement EncryptedString SQLAlchemy type and migrate UserProfile.birth_datetime/location columns; key from ENV APP_DB_KEY; Acceptance: encrypt/decrypt roundtrip tests pass; alembic upgrade/downgrade clean on empty DB; no plaintext in DB after migrate; Out of scope: cross-tenant profile sharing logic"
```
````

### Example 2 — Legacy mode, same step

If `ECC_MODE=legacy` were detected, the same step would be emitted as a single uniform command (no plugin-prefixed forms anywhere in the output):

```bash
/orchestrate custom "tdd-guide,database-reviewer,python-reviewer,security-reviewer" "[Plan: docs/plan/example-feature.md#step-2] ..."
```

The two examples above illustrate **the two possible outputs** for two different environments. A single skill invocation produces only one of them, end to end.

## Notes

- Generative only. Never invoke `/orchestrate` from inside this skill.
- Match the language of the plan document for task descriptions (agent names always remain English).
- Do not insert "Co-Authored-By" lines or emoji in the output unless the user explicitly asks.
</code></pre>                                </div>
                            </div>

                        </div>
                        <script>
                            layui.use(function () {
                                var element = layui.element;
                                element.tab({
                                    headerElem: "#skilldetailsL1_header>button",
                                    bodyElem: "#skilldetailsL1_body>div",
                                });
                            });
                        </script>
                        <div class="skilldetailsL2">
                            <div class="skilldetailsL2_title">
                                <h2>Todos los archivos</h2>
                                <span>1 archivos</span>
                            </div>
                                                        <div class="skillFiles">
                                <div class="skillFilesL">
                                    <b></b>
                                    <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="plan-orchestrate.md" target="_blank"
                                        aria-label="plan-orchestrate.md"
                                        rel="nofollow">plan-orchestrate.md</a>
                                    <span>17.5k</span>
                                </div>
                                <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="Ver" target="_blank" aria-label="Ver"
                                    rel="nofollow">Ver</a>
                            </div>
                                                    </div>
                    </div>
                    <div class="skilldetailsR">
                        <div class="skilldetailsR1">
                            <div class="skilldetailsR1s">
                                <h2>Instalar plan-orchestrate</h2>
                                <div class="skilldetailsR1s_header" id="skilldetailsR1s_header">
                                    <button class="layui-this">
                                        <b></b>
                                        <span>Descargar ZIP</span>
                                    </button>
                                    <button class="">
                                        <b></b>
                                        <span>Git Clone</span>
                                    </button>
                                </div>
                                <div class="skilldetailsR1s_body" id="skilldetailsR1s_body">
                                    <div class="skilldetailsR1s_body1 layui-show">
                                        <p>Descarga y descomprime los archivos de habilidades en tu directorio .claude/skills/.</p>
                                        <a href="javascript:;" title="Descargar ZIP" data-source="TeeN26C1ni2ZDZRkOJVh9w"
                                            aria-label="Descargar ZIP" role="button" class="skill_downloadzip">
                                            <b></b>
                                            <span>Descargar ZIP</span>
                                        </a>
                                    </div>
                                    <div class="skilldetailsR1s_body2">
                                        <p>Clona el repositorio y copia los archivos de la habilidad a tu proyecto.</p>
                                        <div class="skill_clone">
                                            <p>
                                                git clone https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate
# Copy SKILL.md to your .claude/skills/ directory                                            </p>
                                            <a href="javascript:;" title="Copiar" role="button" aria-label="Copiar"
                                                class="skill_clone_copy">
                                                <img src="/assets/images/prompt_word2RMs_p_btn.png"
                                                    alt="Copiar" />
                                                <span>Copiar</span>
                                            </a>
                                        </div>
                                    </div>
                                </div>
                                <div class="skilldetailsR1s_info">
                                    <span>Configuración rápida: </span>
                                    Copia la carpeta de la habilidad en .claude/skills/
Claude detectará y utilizará automáticamente la habilidad                                </div>
                                <div class="skilldetailsR1s_repository">
                                    <span>Repositorio</span>
                                    <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="affaan-m/ECC" target="_blank"
                                        aria-label="Repositorio" rel="nofollow">affaan-m/ECC</a>
                                </div>
                            </div>
                        </div>
                        <div class="skilldetailsR2">
                            <h2>Habilidades relacionadas</h2>
                            <div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/es/skill/detail/airtableautomation.html" title="airtable-automation" aria-label="airtable-automation">airtable-automation</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>Tiempo actualizado                                                29 de junio de 2026</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="P_PqrAzxvKSebU4gaXatSw">
                                            <b></b>
                                            <span
                                                class="collectNums_P_PqrAzxvKSebU4gaXatSw">0</span>
                                        </button>
                                    </div>
                                </div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/es/skill/detail/notionautomation.html" title="notion-automation" aria-label="notion-automation">notion-automation</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>Tiempo actualizado                                                29 de junio de 2026</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="yLOF7em0zgx36kG9EQmIAQ">
                                            <b></b>
                                            <span
                                                class="collectNums_yLOF7em0zgx36kG9EQmIAQ">0</span>
                                        </button>
                                    </div>
                                </div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/es/skill/detail/seoprogrammatic.html" title="seo-programmatic" aria-label="seo-programmatic">seo-programmatic</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>Tiempo actualizado                                                29 de junio de 2026</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="qrlDZwmv4vNLPwqrODKcOQ">
                                            <b></b>
                                            <span
                                                class="collectNums_qrlDZwmv4vNLPwqrODKcOQ">0</span>
                                        </button>
                                    </div>
                                </div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/es/skill/detail/revops.html" title="revops" aria-label="revops">revops</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>Tiempo actualizado                                                29 de junio de 2026</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="ZDIT-veTOzkFQQ0eUEoT-g">
                                            <b></b>
                                            <span
                                                class="collectNums_ZDIT-veTOzkFQQ0eUEoT-g">0</span>
                                        </button>
                                    </div>
                                </div>
                                
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </main>
        <footer>
  <div class="footer">
    <div class="footer1">
      <div class="footer11">
        <span class="footer11_title">Herramientas de IA caliente</span>
        <div class="footer11info">
                    <a href="/es/tool/ai-clothes-remover.html" aria-label="AI Clothes Remover" class="footer11s">AI Clothes Remover</a>
                    <a href="/es/tool/deepnude-generator.html" aria-label="DeepNude generator" class="footer11s">DeepNude generator</a>
                    <a href="/es/tool/purechat.html" aria-label="PureChat" class="footer11s">PureChat</a>
                  </div>
      </div>
      <div class="footer12">
        <span class="footer11_title">Herramientas de IA con potencial</span>
        <div class="footer11info">
                    <a href="/es/tool/idea-box-ai-tool.html" aria-label="Name Idea Box" class="footer11s">Name Idea Box</a>
                    <a href="/es/tool/qi-jing-ai-ai-tool.html" aria-label="奇境 AI" class="footer11s">奇境 AI</a>
                    <a href="/es/tool/ezaudio-ai-tool.html" aria-label="EZAudio" class="footer11s">EZAudio</a>
                  </div>
      </div>
      <div class="footer13">
        <span class="footer11_title">LEER MÁS</span>
        <div class="footer11info">
                    <a href="/es/ainews/ai-hosts-notebooklm-podcast-interviews.html" aria-label="Los anfitriones de AI del podcast Notebooklm ahora están disponibles para entrevistas" class="footer11s">Los anfitriones de AI del podcast Notebooklm ahora están disponibles para entrevistas</a>
                    <a href="/es/ainews/corporate-ai-adoption-leveling-ramp-data.html" aria-label="Los datos de Ramp revelan un estancamiento en la adopción de la IA por parte de las empresas" class="footer11s">Los datos de Ramp revelan un estancamiento en la adopción de la IA por parte de las empresas</a>
                    <a href="/es/ainews/microsoft-unveils-businessfocused-copilot-surface-devices-powered-intel.html" aria-label="Microsoft presenta dispositivos de Copilot+ Surface centrados en los negocios con Intel" class="footer11s">Microsoft presenta dispositivos de Copilot+ Surface centrados en los negocios con Intel</a>
                  </div>
      </div>
      <div class="footer4">
        <span class="footer11_title">Seguir</span>
        <div class="footer11info">
          <a href="javascript:;" class="footer11s">Contáctenos</a>
          <a href="mailto:admin@xix.ai" role="button" aria-label="Contáctenos" class="footer11s">admin@xix.ai</a>
          <a href="/sitemap.xml" class="footer11s" aria-label="SiteMap">SiteMap</a>
        </div>
      </div>
    </div>
    <span class="footer2"></span>
    <div class="footer3">Copyright ©2025 xix.ai All Rights Reserved.</div>
  </div>
</footer>
<div class="ai_cookie" style="display: none">
      <div class="ai_cookie_b">
        <div class="icon_f ai_cookie_close">
          <svg class="icon" aria-hidden="true">
            <use xlink:href="#icon-guanbi1"></use>
          </svg>
        </div>
        <p>
          Al hacer clic en "Aceptar todos los cookies", usted acepta el almacenamiento de cookies en su dispositivo para mejorar la navegación por el sitio, analizar el uso del sitio y ayudar en nuestros esfuerzos de marketing.<span>Política de privacidad</span> Aviso        </p>
        <div class="cokiesetRight">
          <a href="javascript:;" class="cokieA ai_cookie_open"  role="button" aria-label="Configuración de cookies">Configuración de cookies</a>
          <a href="javascript:;" class="cokieA RefuseCookies" role="button" aria-label="Rechazar todos">Rechazar todos</a>
          <a href="javascript:;" class="cokieA cokieAall" role="button" aria-label="Aceptar todos los cookies">Aceptar todos los cookies</a>
        </div>
      </div>
    </div>
    <div class="ai_cookieSettings" style="display: none">
      <div class="layuiDivcokie layui-layer-wrap" id="layuiDivcokie" style="display: block">
        <div class="cokielayTop dlyflx">
          <img src="/assets/images/logo.png" alt="" />
          <div class="icon_f ai_cookie_close1">
            <svg class="icon" aria-hidden="true">
              <use xlink:href="#icon-guanbi"></use>
            </svg>
          </div>
        </div>
        <hr />
        <div class="cokielayDown dlyflx">
          <p class="cokielaydTop">Preferencias de privacidad</p>
          <p class="cokielaydDesc">
            Al visitar cualquier sitio web, este puede almacenar o recuperar información en su navegador, principalmente en forma de cookies. Esta información puede referirse a usted, sus preferencias o su dispositivo y se usa principalmente para que el sitio funcione como espera. Por lo general, la información no lo identifica directamente, pero puede brindarle una experiencia web más personalizada. Debido a que respetamos su derecho a la privacidad, puede optar por no permitir algunos tipos de cookies. Haga clic en los diferentes títulos de categoría para obtener más información y cambiar nuestros ajustes predeterminados. Sin embargo, bloquear algunos tipos de cookies puede afectar su experiencia en el sitio y los servicios que podemos ofrecer. <a href="#" title="Política de privacidad" aria-label="Política de privacidad"><span>Política de privacidad</span></a> <b>Declaración</b>          </p>

          <div class="cokielayDivdown">
            <p class="coklaydownP">Gestionar preferencias</p>
            <ul class="cokidownUl">
              <li class="cokidownli dlyflx" style="padding: 25px 0px 25px">
                <div class="ckdTops">
                  <div class="ckdLeft">
                    <div class="icon_f">
                      <svg class="icon" aria-hidden="true">
                        <use xlink:href="#icon-add"></use>
                      </svg>
                      <svg class="icon icon_active" aria-hidden="true">
                        <use xlink:href="#icon-add1"></use>
                      </svg>
                    </div>
                    <p class="ckdlipmid">Cookie estrictamente necesario</p>
                  </div>
                  <p class="ckdlipr">Siempre activo</p>
                </div>
                <p class="ckdDowns">
                  Estos cookies son necesarios para que el sitio web funcione y no pueden ser desactivados en nuestros sistemas. Por lo general, solo se establecen en respuesta a acciones que realice usted que equivalen a una solicitud de servicios, como configurar sus preferencias de privacidad, iniciar sesión o completar formularios. Puede configurar su navegador para bloquear estos cookies o alertarle sobre ellos, pero algunas partes del sitio no funcionarán luego. Estos cookies no almacenan ninguna información que permita identificar personalmente.                </p>
              </li>
            </ul>
          </div>
        </div>
        <div class="cklyBtn">
          <a href="javascript:;" role="button" aria-label="Aceptar todos los cookies" class="active cokieAall">Aceptar todos los cookies</a>
        </div>
      </div>
      <script>
        $(document).on("click", ".ai_cookie_close", function () {
          $(".ai_cookie").hide();
        });
        $(document).on("click", ".ai_cookie_close1", function () {
          $(".ai_cookieSettings").hide();
        });
        $(document).on("click", ".ai_cookie_open", function () {
          $(".ai_cookieSettings").show();
        });
        $(document).on("click", ".ckdLeft", function () {
          var $li = $(this).closest("li"); 
          var $downs = $li.find(".ckdDowns"); 
          var $iconBox = $(this).find(".icon_f"); 

         
          $downs.slideToggle(200, function () {
            if ($downs.is(":visible")) {
              $iconBox.find(".icon").hide();
              $iconBox.find(".icon_active").show();
            } else {
              $iconBox.find(".icon").hide();
              $iconBox.find(".icon").first().show(); 
            }
          });
        });     
      </script>
    </div>
<link rel="stylesheet" type="text/css" href="https://accounts.google.com/gsi/style">
<div class="login_tab">
  <div class="login_mainC">
    <div class="login_tab_top">
      <div class="login_tab_top1">
        <a href="javascript:;" role="tab" aria-label="Iniciar sesión" aria-selected="true" class="login_tab_top1a ">Iniciar sesión</a>
        <a href="javascript:;" role="tab" aria-label="Inscribirse" aria-selected="false" class="login_tab_top2a">Inscribirse</a>
      </div>
      <div class="login_tab_top2">
        <a href="javascript:;"><img src="/assets/images/login_mainC_top_m_img.png" alt=""></a>
      </div>

    </div>
    <div class="forms_google">
      <div id="g_id_signin"></div>
    </div>
    <div class="forms_or">
      <div class="forms_line"></div>
      <span>OR</span>
      <div class="forms_line"></div>
    </div>
    <div class="login_tab_bottom">
      <div class="login_tab_top1a_bottom">

        <div class="login_form ">
          <div class="login_forms">
            <img src="/assets/images/login_email.png" alt="Correo electrónico">
            <input type="text" placeholder="Complete su dirección de correo electrónico" class="login_forms_email">
            <span></span>
          </div>
          <div class="login_forms">
            <img src="/assets/images/login_password.png" alt="Contraseña">
            <input type="password" placeholder="Ingrese su contraseña" class="login_forms_password">
            <i style="cursor: pointer;" class="layui-icon layui-icon-eye-invisible toggle-password"
              id="toggleLoginPassword"></i>
            <span></span>
          </div>
          <div class="login_forms forms_code1">
            <input type="text" placeholder="Ingrese el código de verificación gráfico"
              class="login_forms_captcha">
            <img src="" alt="Ingrese el código de verificación gráfico" class="login-js-refresh-captcha">
            <span></span>
          </div>
          <div class="login_forms_bottom">
            <label class="login_remember">
              <input type="checkbox" aria-label="Acuérdate de mí">
              <span>Acuérdate de mí</span>
            </label>
            <a href="/es/account/forgetPassword.html" aria-label="Cambiar la contraseña" class="login_forget">Has olvidado tu contraseña</a>
          </div>
          <a href="javascript:;" type="button" role="button" aria-label="Iniciar sesión" id="login_button" class="login_button">Iniciar sesión</a>

        </div>
      </div>
      <div class="login_tab_top2a_bottom">
        <div class="login_form">
          <div class="login_forms">
            <img src="/assets/images/login_email.png" alt="Correo electrónico">
            <input type="text" placeholder="Complete su dirección de correo electrónico" class="register_forms_email">
            <span></span>
          </div>
          <div class="login_forms">
            <img src="/assets/images/login_password.png" alt="Contraseña">
            <input type="password" placeholder="Ingrese su contraseña" class="register_forms_password">
            <i style="cursor: pointer;" class="layui-icon layui-icon-eye-invisible toggle-password"
              id="toggleRegisterPassword"></i>
            <span></span>
          </div>
          <div class="login_forms forms_code1">
            <input type="text" placeholder="Ingrese el código de verificación gráfico"
              class="register_forms_captcha">
            <img src="" alt="Ingrese el código de verificación gráfico" class="register-js-refresh-captcha" id="register_captcha">
            <span></span>
          </div>
          <div class="login_forms">
            <input type="text" class="verify-code-input" placeholder="Ingrese el código de verificación">
            <button id="verifyCodeBtn" class="verify-code-btn" data-text="Obtener código de verificación">Obtener código de verificación</button>
            <span></span>
          </div>
          <a href="javascript:;" role="button" aria-label="Inscribirse" class="login_button" id="register_button">Inscribirse</a>
        </div>
      </div>

    </div>
  </div>
</div>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
  $(document).ready(function () {
    LoginRegister.init({
      selectors: {
        email: {
          login: '.login_forms_email',
          register: '.register_forms_email'
        },
        password: {
          login: '.login_forms_password',
          register: '.register_forms_password'
        },
        captcha: {
          login: '.login_forms_captcha',
          register: '.register_forms_captcha',
          verify: '.verify-code-input'
        },
        buttons: {
          login: '#login_button',
          register: '#register_button',
          verifyCode: '#verifyCodeBtn'
        },
        tabs: {
          login: '.login_tab_top1a',
          register: '.login_tab_top2a',
          close: '.login_tab_top2 a'
        }
      },
      messages: {
        email: "El formato de correo electrónico es incorrecto",
        password: {
          empty: "Ingrese su contraseña",
          invalid: "La contraseña debe ser de 6-18 caracteres y contener letras y números"
        },
        captcha: "Ingrese el código de verificación gráfico",
        verifyCode: "Ingrese el código de verificación",
        operationInProgress: "Operación en progreso, espere",
        unexpectedError: "Se produjo un error inesperado"
      },
      urls: {
        login: "/es/account/dologin.html",
        register: "/es/account/register.html",
        getMailSign: "/es/account/getMailSign",
        sendMail: "/es/account/registerSendMail.html",
        redirctUrl:'pc'
      }
    });
  });
  function initializeGoogleSignIn() {
    if (typeof google === 'undefined' || !google.accounts) {
      setTimeout(initializeGoogleSignIn, 100);
     
      return;
    }

    google.accounts.id.initialize({
      client_id: "294584378011-s53466qiuig7d30tcqrpjv1ue3ni2gun.apps.googleusercontent.com",
      callback: handlePCCredentialResponse,
      auto_select: false,
      locale: 'es',
      
    });
    
    google.accounts.id.renderButton(
      document.getElementById("g_id_signin"),
      {
        theme: "outline",
        size: "large",
        type: "standard",
        shape: "rectangular",
        logo_alignment: "left",
        text: "signin_with",
        width: 400,
        locale: 'es',
      }
    );
    
  }
  document.addEventListener('DOMContentLoaded', initializeGoogleSignIn);
</script>
  <!-- Google tag (gtag.js) -->
  <script  async src="https://www.googletagmanager.com/gtag/js?id=G-LN407DS0B4"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
  
    gtag('config', 'G-LN407DS0B4');
  </script>
  <script src="/kukukuwl.js"   type="text/javascript"></script>
 <a href="javascript:void(0);" class="totop" role="button" aria-label="Volver arriba"><img src="/assets/images/totop.png" alt="" /></a>
        <script>
            layui.use(function () {
                var element = layui.element;
                element.tab({
                    headerElem: "#skilldetailsR1s_header>button",
                    bodyElem: "#skilldetailsR1s_body>div",
                });
            });
            function initSkillCloneCopy() {
                $(document)
                    .off("click.skillCloneCopy")
                    .on("click.skillCloneCopy", ".skill_clone .skill_clone_copy", function (e) {
                        e.preventDefault();

                        var $btn = $(this);
                        var $img = $btn.find("img");

                        var text = $.trim($btn.siblings("p").text());

                        var $temp = $("<textarea>");
                        $("body").append($temp);
                        $temp.val(text).select();

                        try {
                            document.execCommand("copy");

                            // 切换成功图标
                            $img.attr("src", "/assets/images/prompt_word2RMs_p_btn_ok.png");
                            $btn.addClass("active");
                            // 清除上一次定时器
                            clearTimeout($btn.data("copyTimer"));

                            // 3秒后恢复原图
                            var timer = setTimeout(function () {
                                $img.attr("src", "/assets/images/prompt_word2RMs_p_btn.png");
                                $btn.removeClass("active");
                            }, 3000);

                            $btn.data("copyTimer", timer);
                        } catch (err) {
                            alert("复制失败");
                        }

                        $temp.remove();
                    });
            }

            function initSkilldetailsFixed() {
                var $box = $(".skilldetailsR1");
                if (!$box.length) {
                    return;
                }
                var fixedTop = 20;
                var topOffset = $box.offset().top;
                var boxHeight = $box.outerHeight();
                var $placeholder = $("<div></div>").height(boxHeight).hide();
                $box.before($placeholder);
                function handleFixed() {
                    if ($(window).width() <= 1024) {
                        $placeholder.hide();
                        $box.css({
                            position: "",
                            top: "",
                            width: "",
                            zIndex: "",
                        });
                        return;
                    }
                    var scrollTop = $(window).scrollTop();
                    if (scrollTop >= topOffset - fixedTop) {
                        $placeholder.show();
                        $box.css({
                            position: "fixed",
                            top: fixedTop + "px",
                            width: $placeholder.width() + "px",
                            zIndex: 100,
                        });
                    } else {
                        $placeholder.hide();
                        $box.css({
                            position: "",
                            top: "",
                            width: "",
                            zIndex: "",
                        });
                    }
                }
                $(window).on("scroll.skilldetailsFixed resize.skilldetailsFixed", handleFixed);
                handleFixed();
            }
            function initSkilldetailsExpand() {
                $(".skilldetailsL_p").each(function () {
                    var $item = $(this);

                    $item.find(".skilldetailsL_p_expand").text($item.hasClass("active") ? "...Expandir todo" : "Oculto");
                });

                $(document)
                    .off("click.skilldetailsExpand")
                    .on("click.skilldetailsExpand", ".skilldetailsL_p_expand", function (e) {
                        e.preventDefault();

                        var $parent = $(this).closest(".skilldetailsL_p");

                        if ($parent.hasClass("active")) {
                            $parent.removeClass("active");
                            $(this).text("Oculto");
                        } else {
                            $parent.addClass("active");
                            $(this).text("...Expandir todo");
                        }
                    });
            }

            function checkFollow() {
                let dataSources = [];
                $('button.skill_datas').each(function () {
                    let source = $(this).data('source');
                    if (source) {
                        dataSources.push(String(source).trim());
                    }
                });
                dataSources = [...new Set(dataSources)];
                if (dataSources.length === 0) {
                    return;
                }
                $.post('/api/user/FindSkillFollow', {
                    source: dataSources
                }, function (res) {
                    if (res.code == 1 && res.data.length > 0) {
                        res.data.forEach(function (id) {
                            $('button.skill_datas[data-source="' + id + '"]').addClass('active');
                        });
                    }
                }, 'json');
            }
            $(function () {
                checkFollow();
                initSkillCloneCopy();
                initSkilldetailsFixed();
                initSkilldetailsExpand();
            });
            $(document).on('click', 'button.skill_datas', function (e) {
                e.preventDefault();
                const that = $(this);
                let source = that.data('source');
                if (!source || source === undefined || !CommonUtils.checkLogin()) return false;
                layer.load(2, {
                    shade: [0.3, "#000"],
                    time: 0,
                });
                var path = "/user/followSkill";
                var realPath = CommonUtils.getRealPath(path);
                $.post(realPath, { source: source }, function (result) {
                    layer.closeAll();
                    CommonUtils.showMsg(result.msg, result.code);
                    if (result.code == 1) {
                        var values = result.data.data_source;
                        var count = result.data.count;
                        var collected = result.data.collected;
                        var elements = $(".collectNums_" + values);
                        if (elements.length > 0) {
                            elements.each(function () {
                                $(this).parents('button').toggleClass('active', collected);
                                $(this).text(count);
                            });
                        }
                    }
                })
            })

            $(document).on('click', '.skill_downloadzip', function (e) {
                e.preventDefault();
                const url = $(this).data("source");
                if (!url) return;
                window.open("/api/index/download_zip?source=" + encodeURIComponent(url), "_blank");
            })

        </script>
    </body>

</html>