shipflow 0.3.1
shipflow: ^0.3.1 copied to clipboard
A Dart package and CLI that drives any Flutter project from a ticket to a merge request through a deterministic, config-driven pipeline.
Shipflow #
Convierte un ticket en un merge request con tu agente de IA. Tú traes el agente (Claude Code, Cursor, Gemini, Copilot, Codex); Shipflow pone los rieles deterministas: compuertas de arquitectura, generación de código por configuración y un pipeline reproducible de ticket → PR.
ticket ──► analiza → diseña → implementa → corre gates → revisa ──► merge request
En una frase: el ticket entra por la izquierda y el merge request sale por la derecha. En medio hay pasos que siempre se hacen igual; shipflow es el riel que obliga ese orden y verifica la arquitectura en cada paso, mientras tu agente de IA (Claude Code · Cursor · Gemini · Copilot · Codex) hace el trabajo. El ticket puede venir de Asana / Jira / Linear / archivo; el diseño, de Figma / imagen / markup. Diagrama completo y por capas →
Shipflow es un paquete de Dart + CLI (ship) para proyectos Flutter. Es
agnóstico a tu stack: manejador de estado (Riverpod / Bloc / GetX / Provider),
fuente de tickets (Asana / Jira / Linear / archivo), fuente de diseño (Figma /
imagen / markup) y proveedor de MR — todo se declara en un único archivo .ship.yaml.
⚠️ Léelo antes de instalar — qué es y qué no es #
- Shipflow no llama a ninguna IA por sí mismo. El paquete es 100% determinista
(analizadores, matching, scaffolding). La parte de IA son prompts en markdown
(
core/commands/) que ejecuta el agente que tú ya usas. Si no tienes una CLI de IA, Shipflow sigue siendo útil como linter de arquitectura — pero el pipeline ticket→MR no funcionará. - El núcleo está probado; el pipeline está en vista previa. Ver Madurez más abajo — es importante que lo leas antes de decidir.
Madurez #
Sé honesto sobre en qué confiar hoy:
| Parte | Qué es | Estado |
|---|---|---|
Núcleo determinista — ship analyze, match, scaffold, inventory, las compuertas, los 17 analizadores |
El motor que revisa arquitectura, fidelidad de diseño y genera scaffolds | ✅ Probado contra un proyecto real. La primera corrida de ship analyze sobre freya (app Flutter de producción) arrojó 890 hallazgos (1 bloqueador, 13 críticos, 847 mayores, 29 menores) — por eso existe el reporte HTML con triaje. 625 pruebas en verde. |
Pipeline IA ticket→MR — los prompts de core/commands/ orquestados por tu agente |
El flujo completo "lee el ticket → implementa → revisa → abre el MR" | 🧪 Vista previa. Funciona, pero trátalo como camino que puede requerir corrección humana: el tag 1.0.0 espera validar paridad de forma sistemática. Los reportes de bugs son bienvenidos. |
v0.1.0. El tag 1.0.0 espera la validación de paridad del pipeline completo.
¿Es para ti? #
| Si eres… | Shipflow te sirve para… | Encaje |
|---|---|---|
| Equipo Flutter con arquitectura por capas (Clean Architecture u otra) | Forzar invariantes de arquitectura en CI, generar scaffolds consistentes, y (preview) automatizar el flujo ticket→MR con IA | ✅ Ideal |
| Dev que quiere un linter de arquitectura/diseño determinista para Flutter | ship analyze + reporte HTML de triaje, sin tocar nada de IA |
✅ Sí |
| Indie sin estructura por capas que busca "una IA que escriba mi app" | Shipflow gobierna y verifica código sobre rieles; no es un generador de apps end-to-end | ⚠️ Probablemente no |
Sobre la arquitectura por capas: ship init autodetecta carpetas canónicas de
Clean Architecture (lib/src/{domain,infrastructure,presentation}/), pero no estás
obligado a usarlas — en .ship.yaml puedes declarar las capas y reglas de
importación que tu proyecto realmente tenga (ver el ejemplo real en
config/examples/sample_app.yaml). Si tu proyecto
no tiene ninguna noción de capas, Shipflow no es para ti todavía.
Requisitos #
Antes del inicio rápido, confirma que tienes:
- Dart SDK ≥ 3.12 (
dart --version). ~/.pub-cache/binen tuPATH— trasdart pub global activate, ahí queda el ejecutableship. Siship --helpda "command not found", agregaexport PATH="$PATH":"$HOME/.pub-cache/bin"a tu shell.- Un proyecto Flutter o Dart con alguna estructura por capas (ver ¿Es para ti?).
- (Solo para el pipeline ticket→MR) una CLI de IA con comandos invocables: Claude Code, Cursor, Gemini CLI, Copilot CLI o Codex. El núcleo determinista no la necesita.
Inicio rápido #
De un proyecto Flutter existente a tu primer reporte de análisis, copiando y pegando desde la raíz de tu proyecto.
1 — Instalar Shipflow #
dart pub global activate shipflow
ship --version # verifica la instalación → imprime "ship 0.1.0"
ship --help # (opcional) lista todos los subcomandos
Instalar desde el código fuente (o compilar a binario nativo)
git clone https://github.com/GuzCabQ/shipflow.git
cd shipflow
dart pub get
./tool/compile.sh # opcional: produce bin/ship, un binario nativo autocontenido (~10 MB)
2 — Generar .ship.yaml desde tu proyecto #
ship init --template config
Lee tu pubspec.yaml y escanea el sistema de archivos en busca de tus capas.
Cada campo generado lleva un comentario que documenta su origen — así sabes qué
ajustar:
# .ship.yaml (extracto generado)
state_management:
style: riverpod_manual # inferred from pubspec.yaml (flutter_riverpod)
architecture:
layers:
domain:
paths:
- lib/src/domain/ # detected at lib/src/domain/
forbid_imports:
- "package:flutter/" # default — el dominio no debe depender de Flutter
infrastructure:
paths:
- lib/data/ # PLACEHOLDER — no se detectó automáticamente
Abre .ship.yaml y resuelve los # PLACEHOLDER (los campos que Shipflow no pudo
detectar). Para un proyecto con estructura no canónica (data/ en vez de
infrastructure/, nombres en español, feature-first) habrá varios — es normal.
Atajo opcional con IA: el comando
/ship-complete-config(ver Instalar los comandos en tu agente) construye el grafo de tu código y propone las rutas de capa y reglas de importación a partir de tus dependencias reales, mostrándote un diff para aprobar. Si aún no configuras tu agente, resuelve los placeholders a mano guiándote porconfig/examples/sample_app.yaml.
3 — Ejecutar el primer análisis #
ship analyze --gate domain --format human
Salida esperada (ejemplo):
▶ Gate: domain (analizadores: layer_integrity, …)
✗ blocker lib/src/domain/user.dart:12
domain importa package:flutter/material.dart (forbid_imports)
! major lib/src/domain/order.dart:8
entidad sin test correspondiente (meaningful_test)
1 blocker · 0 critical · 1 major · 0 minor → GATE FAILED
Un blocker o critical reprueba la compuerta (útil en CI); major/minor son
informativos. Si aún no creaste las carpetas de capa, este es el momento en que se
señalan: la compuerta es la fuente de verdad sobre si tu .ship.yaml coincide con
la realidad.
Para proyectos grandes (recuerda: freya arrojó 890 hallazgos), el muro de terminal
es inútil. Usa --format html:
ship analyze --gate full --format html -o ship-reports/
Escribe una carpeta autocontenida (index.html + styles.css + app.js +
report.json). Abre ship-reports/index.html: muestra los pocos hallazgos
bloqueantes por encima de los muchos informativos, con agrupación por
severidad/archivo/analizador, filtros y búsqueda. Agrega ship-reports/ a tu .gitignore.
4 — (Opcional) Activar el flujo ticket → MR con tu agente de IA #
Hasta aquí usaste solo el núcleo determinista. Para el pipeline ticket→MR necesitas una CLI de IA. La ruta completa es:
ship install-commands --platform claude # 1. instala los prompts /ship-* en tu agente
/ship-complete-config # 2. (en tu agente) enriquece .ship.yaml desde el grafo del código
/ship-pipeline DEV-1234 # 3. (en tu agente) ejecuta TICKET → MR de punta a punta
Los pasos 2 y 3 son slash-commands que se invocan dentro de tu CLI de IA, no en la terminal. Detalle completo en El pipeline ticket → MR.
¿Qué plantilla de init necesito? #
| Tu situación | Comando | Qué produce |
|---|---|---|
| Proyecto Flutter/Dart existente con código | ship init --template config |
Solo .ship.yaml, desde tu pubspec.yaml + escaneo (el inicio rápido). |
Proyecto recién creado con flutter create |
ship init --template project |
.ship.yaml + carpetas de capa vacías + stub de tokens de tema + stub de go_router + test/fakes/. Asume Riverpod + go_router. |
| Nuevo paquete feature en monorepo Melos / pub workspaces | ship init feature_x --template feature |
Esqueleto de paquete Dart cuyo .ship.yaml apunta su catálogo de tokens a un design_system hermano (ADR-0011). |
Otros comandos útiles #
ship match color "#0066CC" # resolver un color contra tu catálogo de tokens
ship scaffold auth --layer presentation --style riverpod_manual # generar un scaffold de feature
ship inventory --output widget_inventory.json # inventariar widgets a JSON
ship context --run-directory .pipeline/runs/DEV-1234/ # construir el contexto para la siguiente llamada al agente
ship journal --run-directory .pipeline/runs/DEV-1234/ # inspeccionar el journal JSONL de una ejecución
El pipeline ticket → MR (vista previa) #
🧪 Esta es la capa en vista previa (ver Madurez): aún no validada de extremo a extremo contra un proyecto real. El núcleo determinista que la sostiene sí lo está.
.ship.yaml habilita un pipeline de slash-commands en core/commands/:
prompts en markdown que ejecuta tu CLI de IA. El paquete no llama a ninguna API de IA.
El pipeline lee el ticket, genera un spec, implementa cada capa, corre las compuertas por
capa, revisa y crea el MR. Todos los artefactos quedan en .pipeline/runs/<ticket_id>/.
Instalar los comandos en tu agente #
ship install-commands instala de forma determinística los prompts en tu plataforma:
ship install-commands # menú interactivo
ship install-commands --platform claude # o explícito
ship install-commands --platform all
ship install-commands --platform all --dry-run # vista previa, sin tocar el disco
| Plataforma | Destino | Notas |
|---|---|---|
claude |
.claude/commands/<id>.md |
Frontmatter YAML description; $ARGUMENTS nativo |
gemini |
.gemini/commands/<id>.toml |
TOML; $ARGUMENTS → {{args}} |
codex |
~/.codex/prompts/<id>.md |
Instalación global — aplica a toda la máquina |
cursor |
.cursor/commands/<id>.md |
Frontmatter YAML name + description |
ship init --template config --platform claude hace el bootstrap de config + comandos
en un solo paso. Para plataformas sin adaptador, ship commands-path imprime el
directorio con los prompts + un INSTALL.md que tu agente puede seguir. Detalles en
ADR-0021.
Ejecutar ticket → MR: /ship-pipeline #
Este es el comando que orquesta todo el flujo. Una vez instalados los comandos, invócalo dentro de tu agente de IA (no en la terminal):
/ship-pipeline DEV-1234
Lee el ticket → genera el spec → implementa cada capa → corre las compuertas → revisa → abre el MR + handoff a QA. Reanuda desde la última fase completada si lo vuelves a invocar.
/ship-pipeline DEV-1234 [--ticket-file <ruta>] [--mode guided|semi|auto] [--reset]
--ticket-file <ruta>— usa un archivo local (adaptadorfile/) en vez de la fuente de tickets configurada.--mode <modo>— sobrescribepipeline.default_modede.ship.yaml(ver Modos).--reset— borra el directorio de la corrida y empieza de cero.
Antes de la primera corrida conviene ejecutar
/ship-complete-configpara que el.ship.yamlquede afinado contra el grafo real de tu código.
Modos de ejecución #
Vía .ship.yaml::pipeline.default_mode:
| Modo | Se detiene en |
|---|---|
guided |
Cada compuerta — aprobación explícita antes de cada fase. |
semi |
Compuerta 0 (spec) y Compuerta Final (revisión). |
auto |
Solo cuando falla un validador. |
Comandos del pipeline (cada uno invocable por separado) #
ship-analyze-ticket (ticket → análisis) ·
ship-design-feature (análisis → spec) ·
ship-implement-{domain,infrastructure,presentation} (implementación por capa) ·
ship-implement-bugfix ·
ship-run-gates ·
ship-review-feature ·
ship-create-mr ·
ship-complete-config (enriquece .ship.yaml desde el grafo) ·
ship-review-diff (revisión sobre git diff, sin correr el pipeline).
Las fases consultan un grafo de conocimiento del código (ver glosario)
como fuente de hechos verificados: estima impacto, encuentra candidatos de reutilización,
señala posibles regresiones y advierte de hubs de alto acoplamiento. El motor del grafo
vive en el paquete dart_source_graph
(^0.1.0), del cual Shipflow depende — ver ADR-0019
y ADR-0022.
Glosario #
Términos que aparecen arriba, en una línea:
- Compuerta (gate): una verificación por capa (p. ej.
domain). Corre un conjunto de analizadores y reprueba si hay hallazgosblocker/critical. Es lo que pones en CI. - Capa (layer): una división de tu código (
domain,infrastructure,presentation, …) con reglas de qué puede importar qué. Tú las declaras en.ship.yaml. - Catálogo de design tokens: el inventario de colores/tipografía/espaciado de tu tema, contra el cual Shipflow valida que la UI no use valores fuera del sistema de diseño.
- Adaptador: la pieza que conecta Shipflow con un sistema externo o framework concreto (un manejador de estado, una fuente de tickets…). Agregar soporte = escribir un adaptador.
- Paquete de contexto (context packet): el bundle de información que Shipflow arma para pasarle a tu agente de IA en la siguiente llamada (código relevante, reglas, hechos del grafo).
- Grafo de conocimiento del código: el mapa de dependencias reales de tu
lib/que Shipflow construye para razonar sobre impacto, reutilización y regresiones.
Documentación #
docs/PROJECT_WALKTHROUGH.md— recorrido visual con diagramas. Empieza aquí si eres nuevo.docs/CONSUMER_INTEGRATION.md— guía completa para adoptar Shipflow en un proyecto.config/examples/sample_app.yaml— un.ship.yamlde consumidor real, comentado.ARCHITECTURE.md+docs/adr/— diseño interno y 22 registros de decisiones (ADRs). Para contribuyentes.CHANGELOG.md— cambios por versión.
Para contribuyentes — arquitectura interna #
Shipflow sigue Puertos y Adaptadores (hexagonal): todo sistema externo es un adaptador,
todo algoritmo es un servicio. Los límites los aplica el
PackageBoundaryAnalyzer sobre el
propio árbol de Shipflow en cada build de CI (Shipflow se aplica sus propias invariantes —
ver .ship.yaml y ADR-0001).
bin/ship.dart (shim CLI)
└─ lib/src/cli/ CommandRunner + 16 comandos
└─ Servicios lib/src/{scaffolding,resolvers,inventory,matching(puro),core}/
└─ Contratos lib/src/contracts/ ← la superficie estable; todos importan de aquí
└─ Adaptadores lib/src/adapters/{code_gen,token_catalog,…}/ (uno por sistema externo)
Invariantes estrictas (aplicadas por CI): contracts/ y matching/ son puros (sin I/O);
analyzers/, core/ y los servicios no pueden importar adapters/ — la selección de
adaptador ocurre en runtime por búsqueda de nombre en ProjectConfig. La estructura
completa del repo está en ARCHITECTURE.md.
Desarrollo #
dart pub get
dart analyze
dart test # 625 pruebas
dart run tool/check_shipflow_boundaries.dart # Shipflow se valida a sí mismo
./tool/compile.sh # compilar a nativo
Licencia #
Licencia MIT — ver LICENSE.