Skip to content

fix(commands): no tumbar la recuperación de cola por un leftover de imagen huérfano - #277

Closed
cursor[bot] wants to merge 1 commit into
feat/shared-generation-commandsfrom
cursor/bc-4891a3eb-7bb7-4c02-bc72-1b91e66c7133-a230
Closed

fix(commands): no tumbar la recuperación de cola por un leftover de imagen huérfano#277
cursor[bot] wants to merge 1 commit into
feat/shared-generation-commandsfrom
cursor/bc-4891a3eb-7bb7-4c02-bc72-1b91e66c7133-a230

Conversation

@cursor

@cursor cursor Bot commented Sep 9, 2026

Copy link
Copy Markdown

Resumen ejecutivo

Qué cambia

Listar, reanudar o descartar la cola de recuperación ya no falla con 503 si un leftover generation.image no tiene admisión. Esa fila se omite; el resto de jobs se recuperan igual.

Para qué sirve

Tras un crash, borrar el workspace de una imagen (o perder su SQLite de tareas) dejaba una fila en la cola global. Un solo mismatch bloqueaba vídeo, audio y el propio discard.

Impacto para el usuario

La recuperación de cola vuelve a listar y reanudar el trabajo válido. El leftover de imagen huérfano no se relanza; Discard lo limpia de la cola.

Riesgo

  • Bajo
  • Medio
  • Alto

Estado

  • Listo para revisión

Summary

ImageGenerationCommands._recovery_task raised HTTPException(503, recovery_mismatch) when a durable queue row had capability: generation.image but no matching task_command_admissions row (or a drifted job_id). GET /api/v1/jobs/recovery, POST .../resume and POST .../discard all call filter_recovery / discard_recovery with no try/except, so one stale image leftover failed the entire recovery API.

Concrete trigger after #275:

  1. Studio/Wizard/MCP admits an image command; the global durable queue persists the job.
  2. The process crashes. _jobs is empty, so DELETE /api/v1/workspaces/{name} is allowed.
  3. Deleting the workspace removes .maestro-tasks-v1.sqlite3 but not the global queue file.
  4. Any later list/resume/discard — including unrelated video leftovers — returns 503 until the queue file is edited by hand.

The same 503 also fired for an invalid leftover workspace name or a corrupt admission snapshot.

The matcher now withholds that one row (False) instead of raising. Non-image leftovers still pass through. Linked interrupted image leftovers still resume/discard as before.

Overview

Crash leftovers stay in DurableGenerationQueue. Recovery endpoints restore interrupted admissions, then filter the queue. Image rows must still match their admission before they are listed or resumed. Unlinked image rows are skipped so they cannot poison the batch. Native discard still removes inactive queue rows, including the orphan.

Detailed changes

Backend

app/services/image_generation_commands.py: _recovery_task returns None (not an image command), (registry, task) (linked), or False (unlinked / invalid / storage error). filter_recovery skips False. discard_recovery only updates linked interrupted tasks.

UI and Wizard

Unchanged.

Data, provenance and compatibility

No receipt or admission schema change. A leftover without admission is no longer recoverable as a generation job; it remains fail-closed for that row only.

Files and ownership

  • app/services/image_generation_commands.py — recovery matcher
  • tests/test_image_generation_commands.py — orphan + invalid workspace + job-id drift mixed with a video leftover

Intentionally untouched: queue storage, admission writes, HTTP/MCP submit, UI Generate.

Validation

  • Date (UTC): 2026-09-09

  • Base SHA: cc0d760 (feat/shared-generation-commands)

  • Head SHA: d057b46

  • Validation scope: focused

  • python scripts/verify_clean_repo.py

  • python -m compileall -q app/services/image_generation_commands.py → clean

  • Focused Python tests: .venv/bin/python -m pytest tests/test_image_generation_commands.py -q25 passed, 0 failed

  • cd ui && npm run i18n:check

  • UI tests: N/A (backend recovery only)

  • cd ui && npm run lint -- --max-warnings=0

  • cd ui && npm run build

  • git diff --check (clean commit)

  • E2E/smoke: N/A — no browser or GPU path; matcher is covered by the focused suite

Code quality

  • Score: pending CI
  • Complexity trend: pending CI
  • Production LOC trend: pending CI
  • Regression versus main: pending CI
  • Ratchet: pending CI

CI and review

  • CI of this HEAD: pending

  • Independent agent review of this HEAD: pending

  • Human merge click (operational, not code review): pending

  • Pending

Coste de la tarea

  • Tests simulados: 0 tokens externos
  • Tests reales: N/A
  • Llamadas LLM externas: 0
  • Tokens de prompt: N/A
  • Tokens de respuesta: N/A
  • Tokens totales: N/A
  • Generaciones de imágenes/audio/vídeo: 0
  • Tiempo transcurrido: N/A
  • Proveedores/modelos: N/A

Notes and limitations

An orphaned image leftover is not reconstructed from the queue row. Resume will not start it. Discard still clears the queue file. Merge into #275 before that branch lands, or cherry-pick onto development after #275.

Follow-up work

Workspace delete still does not sweep the global generation queue; that is a separate cleanup. #276 (form leftovers blocking Generate) remains open.

Checklist

  • The executive summary is understandable without reading the code.
  • The detailed Summary/Overview has not been removed or shortened.
  • Tests and their actual results are recorded.
  • Generated assets, secrets and local-only files are not committed.
  • Required CI and Cursor/Bugbot review are complete, or the PR is clearly marked as waiting for them.
Open in Web View Automation 

A single generation.image queue row without a matching admission used to
raise 503 from list/resume/discard and block every other leftover. Skip
the unmatched row instead so video and valid image recovery still work.

Co-authored-by: ignaciodelcano+dcl <ignaciodelcano+dcl@gmail.com>
@IAnMove

IAnMove commented Sep 9, 2026

Copy link
Copy Markdown
Owner

These ideas are already in #275 (65ed2852, refined locally). They cannot target development until that feature lands, so this stacked draft is closed instead of duplicating #275. Grouped development fixes are in #279.

@IAnMove IAnMove closed this Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants