Lab Notes
Research

Mission Lifecycle

Cómo se crea, ejecuta, pausa, reanuda y completa una misión de investigación: el ciclo de vida alrededor de las fases.

Propósito

Esta página es la referencia canónica del ciclo de vida de una misión. El framework está en Framework; el grafo de fases está en Mission DAG; los artefactos escritos en cada etapa están en Artifacts.

Una misión pasa por las siguientes etapas de alto nivel:

Loading diagram…
Estados del ciclo de vida de la misión y transiciones.

Etapa 1 — Created

Una misión se crea cuando:

  • El Coordinator reenvía una petición de investigación al Research Worker.
  • El usuario invoca el CLI directamente con research_cli.py run.
  • Un proceso automatizado dispara una misión (job programado, test, auditoría).

f0_init corre y:

  1. Crea <runs_dir>/<mission_id>/.
  2. Parsea la query cruda en un ParsedQuery.
  3. Escribe task.json (tipado: Task).
  4. Escribe el phase.json inicial con F0 marcado como succeeded y la siguiente fase como pending.

La misión está ahora Created y el orquestador puede recogerla.

Etapa 2 — Running

El run_mission del orquestador entra en un bucle:

  1. Carga el RunState actual desde phase.json.
  2. Resuelve la(s) siguiente(s) fase(s) a ejecutar.
  3. Para cada fase:
    • La marca como running en el estado.
    • Ejecuta el handler de la fase.
    • Captura el PhaseResult.
    • Actualiza el estado para reflejar el resultado.
  4. Repite hasta que todas las fases estén en estado terminal.

El StateStore escribe el estado tras cada transición. Esta es la capa de checkpointing (ver más abajo).

Etapa 3 — Checkpointed

Tras cada transición de fase, el orquestador escribe el nuevo RunState a <run_dir>/phase.json. El estado contiene:

  • El mission_id y el status global (running, paused, completed, failed).
  • El current_phase (la fase que se acaba de ejecutar o está a punto de correr).
  • Una lista de registros por fase: name, status, started_at, ended_at, attempts, output_artifacts, error.

El checkpointing es síncrono y write-through. El StateStore usa un RLock por path para permitir escrituras concurrentes seguras desde fases paralelas.

Por qué hacer checkpoint

Tres razones:

  1. Resumability. Una misión se puede pausar y reanudar en cualquier frontera de fase. Una misión con crash se puede reiniciar desde el último checkpoint.
  2. Auditabilidad. El fichero de estado es un registro completo de lo que pasó. El Coordinator puede mostrárselo al usuario bajo demanda.
  3. Observabilidad. El fichero de estado es la telemetría primaria del framework. Las herramientas pueden leerlo para construir dashboards.

Formato del checkpoint

phase.json es un único documento JSON. Extracto:

{
  "mission_id": "hotel-barcelona-2026-09",
  "status": "running",
  "current_phase": "F2",
  "phases": {
    "F0": {
      "status": "succeeded",
      "started_at": "2026-06-10T20:15:00Z",
      "ended_at": "2026-06-10T20:15:01Z",
      "attempts": 1,
      "output_artifacts": ["task.json"]
    },
    "F1": {
      "status": "succeeded",
      "started_at": "2026-06-10T20:15:01Z",
      "ended_at": "2026-06-10T20:15:34Z",
      "attempts": 1,
      "output_artifacts": ["candidates.json"]
    },
    "F2": {
      "status": "running",
      "started_at": "2026-06-10T20:15:34Z",
      "attempts": 1
    }
  }
}

Etapa 4 — Paused

Una misión se puede pausar en cualquier frontera de fase por el usuario. El Coordinator envía una señal de "pause"; el orquestador termina la fase actual, actualiza el estado a paused y se detiene.

Una misión pausada puede:

  • Reanudarse. El orquestador continúa desde el último checkpoint.
  • Cancelarse. El directorio del run se mueve a un subdirectorio cancelled/ bajo runs_dir/.

Pausar es un stop blando: el orquestador no aborta las peticiones HTTP en curso. La fase actual se completa antes de que se acuse la pausa.

Etapa 5 — Partial

Una misión es partial cuando una o más fases terminaron en succeeded_partial. El orquestador continúa, pero el informe final se marca.

Las misiones parciales no son fallos. Son un resultado normal cuando:

  • Un adaptador está rate-limited y devuelve menos resultados de los pedidos.
  • Una fuente de reseñas o precios no está disponible.
  • La fase de YouTube no encuentra contenido relevante.

El informe incluye una sección "Limitations" que lista las fases que quedaron parciales y los artefactos que faltan o están incompletos.

Etapa 6 — Failed

Una misión es failed cuando una fase es failed_terminal y el orquestador no puede continuar. El estado se actualiza, el directorio del run se mueve a runs_dir/failed/, y se notifica al Coordinator.

Los fallos se diferencian de los parciales en dos cosas:

  1. El orquestador no puede producir un informe que cumpla el contrato mínimo.
  2. Se espera que el usuario tome acción: reintentar, cambiar la query o aceptar el fallo.

Una misión fallida no se borra. Se preserva para post-mortem. Se le puede pedir al Coordinator que muestre el fichero de estado, el mensaje de error y los artefactos parciales.

Etapa 7 — Completed

Una misión es completed cuando F6 ha escrito report.md y el estado se ha actualizado a succeeded. Se notifica al Coordinator con un resumen del informe y un enlace al fichero.

Las misiones completadas se conservan en runs_dir/. La política de retención es configurable (SCOUTE_RETENTION_DAYS, default 30). Tras expirar la retención, la misión se mueve a runs_dir/archive/.

Reanudar una misión

Para reanudar una misión, el usuario llama:

python -m scout.tools.research_cli resume \
  --mission-id hotel-barcelona-2026-09 \
  --runs-dir /tmp/scoute/runs

El orquestador:

  1. Carga el estado desde phase.json.
  2. Valida el estado (la misión debe estar paused o failed).
  3. Identifica la(s) siguiente(s) fase(s) a ejecutar.
  4. Continúa desde ahí.

Reanudar es el mismo code path que un arranque nuevo — el orquestador solo lee el estado y retoma donde lo dejó.

Cancelación

Una misión se puede cancelar en cualquier fase. La cancelación es dura: el orquestador aborta la fase actual, escribe un estado cancelled y mueve el directorio del run a runs_dir/cancelled/.

La cancelación no deshace el trabajo que ya estaba checkpointed. Si el usuario quiere deshacer una misión, debe cancelar y luego arrancar una nueva.

Retención y archivado

StatusUbicación por defectoRetención
runningruns_dir/<mission_id>/Indefinida
pausedruns_dir/<mission_id>/30 días
completedruns_dir/<mission_id>/30 días
partialruns_dir/<mission_id>/30 días
failedruns_dir/failed/<mission_id>/90 días
cancelledruns_dir/cancelled/<mission_id>/7 días
archiveruns_dir/archive/<mission_id>/Indefinida

La retención la aplica una tarea diaria de limpieza. Se le puede pedir al Coordinator que ejecute la limpieza bajo demanda.

Ver también

On this page