Levantado ao fechar a Etapa 1 do Crystal Ball (Linear PROD-2127, PR #16).
O passo reason cria a linha em generations antes de executar, de propósito: é o que faz o card acender "em geração" no kanban durante uma espera longa de motor (o primeiro passo do Crystal Ball leva de 100 a 240 segundos). O passivo é direto: se o processo morrer no meio, a linha fica pending para sempre.
deriveColumn (web/lib/queries.ts:281, 308 do repo do Workbench) prende o card em "em geração" enquanto houver generation pending ou running, e não há saída. failStaleRuns (web/lib/runs.ts:166) cobre só app_runs, e cleanup_engine._scan_failed_generations (lib/cleanup_engine.py:217-232) só varre status='failed'.
Não morde no Eco, cujo passo reason é template instantâneo. Morde no Crystal Ball.
Caminho: varredura de generation pending com created_at velho, marcando failed com motivo, junto ou separado do reaper de run pausada.
Levantado ao fechar a Etapa 1 do Crystal Ball (Linear PROD-2127, PR #16).
O passo
reasoncria a linha emgenerationsantes de executar, de propósito: é o que faz o card acender "em geração" no kanban durante uma espera longa de motor (o primeiro passo do Crystal Ball leva de 100 a 240 segundos). O passivo é direto: se o processo morrer no meio, a linha ficapendingpara sempre.deriveColumn(web/lib/queries.ts:281, 308 do repo do Workbench) prende o card em "em geração" enquanto houver generationpendingourunning, e não há saída.failStaleRuns(web/lib/runs.ts:166) cobre sóapp_runs, ecleanup_engine._scan_failed_generations(lib/cleanup_engine.py:217-232) só varrestatus='failed'.Não morde no Eco, cujo passo
reasoné template instantâneo. Morde no Crystal Ball.Caminho: varredura de generation
pendingcomcreated_atvelho, marcandofailedcom motivo, junto ou separado do reaper de run pausada.