spec: separar responsabilidades feat: agregra pipeline de construccion en gitea
4.2 KiB
Design: split-main-into-files
Context
El proyecto outline-mcp vive íntegramente en main.go (425 líneas, paquete main), según la decisión D2 del change create-outline-mcp-server, que explícitamente anticipaba la extracción a múltiples archivos como refactor futuro. El archivo mezcla tres dominios independientes (cliente HTTP de Outline, handlers de tools MCP, auto-update vía Gitea). No hay tests aún; la verificación actual es go build, golangci-lint run y prueba manual por stdio.
Goals / Non-Goals
Goals:
- Repartir
main.goen archivos por responsabilidad dentro del mismo paquetemain, sin ningún cambio de comportamiento. - Dejar el código preparado para añadir tests y nuevas tools sin fricción.
- Cumplir la promesa de D2: extracción sin impacto en specs de comportamiento ni en el pipeline de release.
Non-Goals:
- Introducir paquetes
internal/(descartado: no hay necesidad de ocultar API entre dominios con el alcance actual). - Añadir tests (cambio posterior; solo se deja el terreno listo).
- Renombrar o refactorizar funciones, tipos o lógica.
- Modificar
go.mod, dependencias, pipeline de release o contrato de nombres de assets.
Decisions
D1: Múltiples archivos en paquete main (opción B) frente a internal/ (opción C)
- Elección: dividir en archivos del mismo paquete
main. Estructura resultante:main.go— funciónmain(), variables de build (Version,GiteaURL,RepoOwner,RepoName) y registro de tools.client.go— tipoOutlineClient,newOutlineClient, métodopost.tools.go— los cuatro handlers de tools MCP.updater.go—giteaRelease,parseVersion,versionNewer,doUpdate.
- Alternativa (
internal/outline,internal/tools,internal/selfupdate): descartada porque obliga a decidir superficie exportada acoplando los handlers al SDK (mcp.CallToolResulten firmas) y no aporta ocultación real con el alcance actual. Queda como refactor futuro si el número de tools crece de forma significativa. - Alternativa (mantener un solo archivo): descartada; el argumento de bootstrap de D2 ya se cumplió y la mezcla de dominios penaliza la legibilidad y los futuros diffs.
D2 (revisión): se actualiza la decisión del change create-outline-mcp-server
La D2 original ("todo el código en main.go") queda sustituida por esta organización multi-archivo en paquete único. El carácter de monolito deliberado (un único binario, un único paquete) se mantiene; lo que cambia es la distribución física en archivos.
D3: Movimiento mecánico de código, sin reescritura
Las funciones y tipos se trasladan íntegras (mismos nombres, firmas, comentarios y directivas //nolint). Solo se ajustan los bloques import de cada archivo nuevo. Esto minimiza el riesgo del refactor y hace el diff auditable como puro movimiento.
D4: Las variables de build permanecen en main.go
Version, GiteaURL, RepoOwner y RepoName se inyectan con -ldflags -X main.Version=... y el paquete sigue siendo main, por lo que no hay razón para moverlas. Permanecen junto al entrypoint, que es su punto natural de referencia.
Risks / Trade-offs
- [División incorrecta de imports causa fallo de compilación] → Verificación inmediata con
go build ./...en el contenedor tras cada movimiento; es un error de compilación, no un error silencioso. - [
golangci-lintseñala imports sin usar o duplicados] → Ejecutargolangci-lint runen el contenedor como parte de la verificación. - [Confusión temporal por familiaridad con el archivo único] → El diff es puro movimiento de código; los nombres de archivo (
client.go,tools.go,updater.go) se corresponden directamente con los dominios. - [Regresión funcional no detectada por compilación] → Prueba manual por stdio del servidor MCP (handshake + tools/list) tras el refactor, igual que en el change original.
Migration Plan
- Crear los tres archivos nuevos moviendo bloques completos desde
main.go. - Reducir
main.goa entrypoint + variables de build + registro de tools. - Compilar, lintear y probar por stdio en el contenedor DevPod.
- Rollback trivial:
git revertdel commit único del refactor.
Open Questions
(ninguna)