Project tracking
Cómo trackeamos el trabajo en Axel, un sistema de 3 niveles sobre GitHub Projects, del roadmap ejecutivo al sprint.
Todo el trabajo de Axel se trackea en GitHub Projects (org heyaxel), en
un sistema de 3 niveles. La verdad técnica vive en el repo platform; los
Projects la agregan y le dan visibilidad por audiencia.
Los 3 niveles
Axel · MVP: un Gantt de los ~90 días con un item por hito/sub-proyecto,
fechas (Start/Target) y Owner (CTO/Legal/CEO). Es la vista para el CTO y el
CEO, sin detalle técnico.
Un Project por sub-proyecto (#1 Foundation … #5 Notifications), mismo
schema (18 campos), con fases propias derivadas de su design doc, no una
F0–F7 universal.
El campo Sprint (iteración semanal) dentro de cada sub-proyecto.
Los Projects son a nivel de organización, no de repo. Los issues viven en
platform; el Project los agrega. Cada Project se linkea al repo para que
aparezca en su pestaña Projects.
Anatomía de un Project de sub-proyecto
- Milestone = fase. Los milestones agrupan por fase (
F0 · Bootstrap, …). No se crean labels de fase: sería redundante. - Campos: Status · Phase · Priority · Estimate · Owner · Sprint.
- Vistas:
Tabla agrupada por Phase: el roadmap maestro, para planificar.
Kanban por Status: el trabajo día a día.
La frontera grabbable: Status = Todo y 0 blockers abiertos. La cola
de los agentes. Ver dependencias, abajo.
Dependencias nativas → la cola AFK
La cola AFK gatea por las relaciones Blocked by nativas de GitHub (REST
/issues/{n}/dependencies/blocked_by), no por el texto del issue. Un issue es
grabbable cuando tiene Status = Todo y 0 blockers abiertos.
- Las deps se derivan del desglose por fase: cada gate de fase bloquea por su trabajo; F0-01 (crear el repo) es el único punto de entrada real.
- Snapshot inicial: los issues bloqueados se ponen en
Status = Blocked, así la vista AFK-ready muestra solo la frontera. (Caveat: al cerrarse issues, los que se desbloquean hay que re-pasarlos a Todo, no hay automación nativa para “0 blockers → Todo”.)
Auto-add + repo compartido: como los 5 sub-proyectos comparten el repo
platform, un auto-add global metería todos los issues en todos los boards.
Los PRs de tooling se ponen en In Review para no ensuciar la cola grabbable.
Convención de labels
Todos los labels custom llevan prefijo de namespace:
type: qué tipo de trabajo (feature, chore, infra, test, docs), 1 por issue.
status: estado del workflow (needs-decision, blocked, in-progress), 1 por issue.
area: dónde en el codebase (backend, frontend, schema, tenancy…), 1+ por
issue. meta: cross-cutting (gate, edge-case), 0+ por issue.
Automatización nativa
Workflows built-in que mantienen el board al día sin trabajo manual:
- Auto-add: todo issue/PR nuevo de
platformentra al board. - Item closed → Done · PR merged: el estado se mueve solo.
Cuerpo de un issue bien formado
Current State · Goal · Scope · Technical Spec (archivos, contracts, deps) · Out of Scope · Acceptance Criteria (checkboxes ejecutables) · Edge cases · Dependencies/Blocks · Manual Verification · Definition of Done.
Flujo de una fase (commit local → push batch)
Los issues de una fase (ej. F0-01…F0-06) no se pushean uno por uno. Se acumulan
como commits locales en una rama de fase, y el primer push de toda la fase
ocurre recién al pasar su gate (el issue meta: gate, ej. F0-00).
Por qué diferir el push:
- Presupuesto de Actions. Una rama sin PR abierto no gasta CI. Abrir un PR por
cada issue de la fase dispararía el
claude-review(el workflow caro) N veces. Agrupando la fase en un solo momento de push → un run, no N. - El gate valida la fase completa. El sentido de un issue
gatees verificar que los entregables de la fase encajan juntos (entorno local + CI verde). Eso solo se puede correr cuando todos los issues previos existen, no antes.
Mantener la rama al día: si main avanza mientras la fase está en curso
(otros PRs mergean), rebasar la rama de fase sobre main antes de seguir:
así el trabajo se integra contra el estado real y los conflictos se resuelven
temprano, de a poco, en vez de todos juntos en el push final.
Estados del Project durante una fase
| Estado | Cuándo |
|---|---|
| Todo | Issue grabbable (0 blockers), aún no tomado. |
| In Progress | Se está trabajando o ya está commiteado local, pero sin PR todavía. Es el estado correcto para trabajo hecho-pero-no-entregado. |
| In Review | Hay un PR abierto esperando revisión. No usar antes del push: sin PR no hay nada que revisar. |
| Done | PR mergeado. Para issues de una fase con push diferido, esto ocurre en bloque al cerrar la fase. |
Un issue con commit local pero sin push se queda en In Progress, no In Review. La transición a In Review y luego Done pasa cuando la fase abre su(s) PR(s) en el gate.
El gate de merge (modelo AFK)
El ruleset protect-main de cada repo: require PR, bloquea force-push y borrado
de main. Requiere plan Team (en Free la protección de privados da 403).
approvals = 1: un agente no puede mergear su propio PR (GitHub no deja auto-aprobar). El humano aprueba; el CTO, como org admin, mergea sus propios PRs con bypass (--admin).- El review de Claude es advisory, no bloquea. No lo hicimos required status
check: pasa con solo correr (no por hallazgos), y sin
synchronizedejaba el check pending en cada push. El muro real esapprovals=1; el gate de seguridad de código es CI-tests-verde, que se agrega comorequired_status_checkscuando aterrizaci.yml.
Ver Automatización & agentes AFK para el detalle.