/jira-administration cubre dos trabajos de administración del proyecto de Jira: reconciliar sus Components con los módulos reales de la app, o repuntar el repo a otra instancia de Atlassian después de una migración de sitio. Los dos escriben fuera del repo (en Jira, o en la sesión de acli de toda la máquina), así que los dos pasan por la misma secuencia: leer primero, mostrar el plan y esperar tu aprobación antes de tocar nada.
components o instance-migration. Si no está claro, pregunta.
Los Components actuales, o las dos instancias y todo lo que nombra la vieja.
Una tabla que ves completa: qué cambia, qué no, y qué está en juego.
Escribe, y después verifica leyendo el destino, no el código de salida.
Es una skill de uso raro y consecuencias grandes. El día a día con Jira (crear, transicionar, comentar) pasa por otra puerta.
Cada corrida elige exactamente un modo y carga solo su referencia. Nunca combina los dos ni cae de uno en el otro. Un "arregla Jira" a secas no alcanza para elegir: la IA te pregunta.
| Modo | Frases que lo disparan | Lee |
|---|---|---|
| components | "jira-components" · reconcile / sync Jira Components | references/components.md |
| instance-migration | "jira-instance-migration" · changed / repoint Jira instance | references/instance-migration.md |
los viejos nombres de comando (jira-components, jira-instance-migration) sobreviven solo como frases disparadoras
Viven en el bloque ## Compact Rules de la skill, que es lo que viaja a los subagentes a través de .agents/skills/REGISTRY.md.
No una épica. Una épica es una unidad de trabajo; un component es una unidad del sistema en marcha, más fina a propósito, porque un filtro sirve tanto como discrimina. Es un campo nativo de Jira (se setea directo, nunca a través de {{jira.*}}) y es el eje de agrupación de filtros JQL, métricas y dashboards.
Dos entradas. Lo que existe: el árbol de rutas de la app (app/**/page.tsx y app/api/**/route.ts en Next.js App Router), agrupado con el vocabulario del producto. Lo que viene: épicas e historias del backlog que todavía no tienen ruta.
Un component se puede declarar antes que el código: una feature en refinamiento ya tiene historias que necesitan dónde colgarse. La IA propone, no decide.
Lista cada component con su cantidad de issues. Ese número es el punto: borrar y recrear uno con nombre nuevo dejaría huérfanos a todos sus issues.
Cada módulo propuesto queda clasificado: ya existe (skip), existe con otro nombre (rename) o falta (create).
Escribe el plan en .context/reports/jira-components-plan.json, te lo muestra como tabla (renames aparte, cada uno con su cantidad de issues) y corre el dry run. Si quieres cambiar nombres o agrupación, regenera y vuelve a mostrar.
Solo después de tu sí: --apply, y enseguida otro --list. La lista viva tiene que coincidir con el plan aprobado.
# fase 2 · estado actual, con cantidad de issues bun scripts/sync-jira-components.ts --list --project {{PROJECT_KEY}} # fase 3 · dry run (es el default: no escribe nada) bun scripts/sync-jira-components.ts .context/reports/jira-components-plan.json # fase 4 · solo con aprobación explícita bun scripts/sync-jira-components.ts .context/reports/jira-components-plan.json --apply bun scripts/sync-jira-components.ts --list --project {{PROJECT_KEY}}
Lee el código y el backlog, agrupa rutas en módulos y arma el plan.
Avisa si el vocabulario del producto choca con nombres genéricos (Tests, Runs, Bugs) y propone prefijar cada component con el nombre del producto.
La agrupación y los nombres de cada módulo.
Si se aplica el prefijo: nunca va en silencio, es parte del plan.
El sí que habilita el --apply.
El plan en .context/reports/.
El módulo de Components del proyecto reconciliado, y un reporte de lo renombrado, creado y salteado.
Una migración de sitio reasigna los IDs de los campos personalizados. El ID viejo suele seguir existiendo en la instancia nueva, apuntando a otro campo. La falla no es un 404: es un 200 OK que escribe tus datos en el campo equivocado, en silencio.
Origen: lo detecta leyendo .agents/project.yaml, la sesión de acli y lo que resuelve bun run jira:url. Si no coinciden, el repo ya está a medio migrar: lo trata como una reparación y te pregunta cuál es el "antes" real. Destino: nunca lo adivina, te lo pide.
Confirma los dos hosts en una línea, y antes de seguir comprueba que el destino responde 200 en /rest/api/3/myself. Migrar a una instancia vacía publica catálogos vacíos.
Barre el repo buscando el host viejo y clasifica cada hallazgo en "cambia" o "no cambia". Te muestra la tabla antes de tocar nada. Lo que no encaja en ninguna lista (un workflow de CI, un README, .mcp.json) lo pregunta.
Primero atlassian_url en .agents/project.yaml, que es lo que todo lo demás lee. Después borra cualquier ATLASSIAN_URL suelto. Al final, el re-login de acli con el host leído de vuelta del yaml.
Cinco chequeos en una tabla: el yaml, lo que resuelve jira:url y la sesión de acli nombran el destino; la sonda de presencia [ -n "${ATLASSIAN_URL+x}" ] dice unset; la llamada REST devuelve 200. Cualquier cosa menos que eso es una migración fallida.
| Cambia | No cambia |
|---|---|
| .agents/project.yaml → atlassian_url: el único lugar donde se escribe el host | Un dominio alias de la organización: suele redirigir a la instancia activa. Pero no se ve desde el repo, así que lo confirmas a mano |
| Un ATLASSIAN_URL viejo en .env o en el proceso: se borra, no se actualiza | Registros históricos: reportes de sprint, retros, changelogs. Reescribirlos falsea el pasado |
| La sesión de acli: re-login por máquina | Código que ya matchea con una regex general, y el caché regenerable de .context/PBI/ |
Las variables de los agentes nunca guardan IDs de Jira: resuelven slugs contra tres catálogos propios de cada workspace. Es la parte que la gente saltea, y la que corrompe datos.
| Catálogo | Se regenera con | Guarda | Ojo |
|---|---|---|---|
| .agents/jira-fields.json | bun run jira:sync-fields --force | IDs de campos personalizados y sus opciones | sin --force frena: el catálogo ya está poblado |
| .agents/jira-workflows.json | bun run jira:sync-workflows | estados y transiciones por tipo de trabajo | idempotente; --force no suma nada |
| .agents/jira-link-types.json | bun run jira:sync-link-types | tipos de vínculo entre issues | no tiene --force, y lo traga sin avisar |
.agents/jira-required.yaml no guarda IDs, pero es la entrada de la regeneración: jira:sync-workflows cataloga solo los tipos de trabajo que declara. Un manifiesto viejo produce un catálogo amputado que sale con código 0.
Se compara contra el de upstream y, si hay diferencia, la IA para y te deja elegir tipo por tipo: el archivo es co-propiedad del upstream y del proyecto.
Un diff sin cambios de ID significa que el sync no llegó a la instancia nueva. Pero dos slugs pueden intercambiar IDs y sobrevivir a ese chequeo. Por eso pregunta a la instancia viva qué es cada ID catalogado y lo compara con el nombre registrado.
Revisa también campos que quedaron con opciones vacías, IDs literales fuera de los catálogos y cualquier variable que fije un ID por encima del catálogo.
Un commit para el repunte de atlassian_url, otro para los tres catálogos. Si el manifiesto cambió, va antes, en un tercero. Todo a través de /git-flow-master, y sin push sin tu confirmación.
.agents/project.yaml → issue_tracker.atlassian_url, y en ningún otro lado del repo. Una segunda copia es lo que se pone viejo: tras una migración, un host suelto en el entorno apunta los scripts al sitio anterior y reporta éxito.
La primera palabra después del nombre de la skill elige el modo, y el resto viaja tal cual a la referencia: la clave del proyecto y la ruta de la app, o las dos instancias.
Barra de la skill más el modo. Sin modo, la IA lo saca de la frase o pregunta.
Sin barra: nombras la skill y el modo en la frase.
Mismo patrón que OpenCode, CLI o Desktop.
# components: clave y fuente explícitas, o vacío para que la fase 1 las resuelva /jira-administration components BK ../bunkai # instance-migration: origen y destino, en ese orden, o vacío para que la fase 0 detecte y pregunte /jira-administration instance-migration oldsite.atlassian.net newsite.atlassian.net
Al entrar resuelve sus categorías complementarias (issue-tracker, meta-skill) desde .agents/skills/REGISTRY.md.
Dueña de cada lectura de Jira, del estado de autenticación y del cambio de sitio. Se carga antes de cualquier operación. También es la puerta para el trabajo diario con tickets.
Dueña del contrato de commit, branch y push con el que se publican el repunte y los catálogos. Nunca empuja sin confirmación.
El espejo local del backlog, y por qué un host viejo lo corrompe reportando éxito. Deck: PBI como caché de Jira.