AiM Tours · Product & Engineering Plan

Listing Video Resilience & Recovery

A concrete policy and implementation roadmap for preventing avoidable failures, recovering expensive long-running renders, delivering usable videos when perfection is unavailable, and telling customers only what helps them act.

Status: Proposed resilience contract Updated: July 15, 2026 Scope: Tours Listing Video pipeline

North-star policy

Be strict before provider spend. After provider spend, preserve assets, repair deterministically, and deliver every genuinely usable result.

This plan replaces a binary “meets every invariant or fails” posture with an explicit distinction between lifecycle success and output quality. A small timing flaw should not erase a completed, expensive render. A corrupt or materially misleading video still must not be presented as successful.

Why this work is needed

The Listing Video Failure Catalog inventories the known failure contracts. Production review and code tracing show that the remaining risk is not only missing error codes. The pipeline needs a consistent disposition policy: when to retry, when to repair, when to reuse purchased assets, when to deliver a degraded result, and when failure is the only honest outcome.

1

Failure is sometimes recorded too early

A child attempt can mark the database run failed before an orchestrator-level retry has had a chance to recover it. Attempt state and terminal run state need separate ownership.

2

Provider work can outlive the process

A provider may finish an expensive job before an OOM, download failure, normalization failure, or persistence failure. Retrying safely requires a durable provider-job checkpoint or a same-run persisted asset.

3

Quality defects are treated like availability defects

Small FFmpeg or timeline differences can currently fail the render even when a playable, useful output can be repaired or delivered with a warning.

Confirmed constraint: the current application treats completed as the prerequisite for ready email, download, and result display. Adding a new lifecycle status without updating every consumer would create avoidable regressions.

Separate lifecycle status from output quality

Keep the existing lifecycle contract stable. Attach a second, additive quality classification and structured warnings to completed renders.

Lifecycle statusQualityMeaningCustomer result
completedstandardAll required stages completed and output met the normal quality contract.Ready email, preview, and download.
completedrepairedA deterministic correction was applied and the final output passed validation.Normal delivery; correction remains internal unless it is useful to disclose.
completeddegradedThe result is playable and useful, but a nonessential quality expectation was not fully met.Deliver it. Optionally show a calm Listing-page notice and “Try again.”
failedunusableNo honest, usable version of the promised product could be persisted.Failure email with the most useful safe action.
cancelledNot applicableUser cancellation or a newer render intentionally superseded this run.No failure email.

Recommended warning record

Warnings should be structured facts, not prose-only logs. A completed render can carry zero or more records such as:

{
  "code": "AVATAR_ENDED_BEFORE_TIMELINE",
  "stage": "final_assembly",
  "differenceSeconds": 1.42,
  "repair": "FADE_AVATAR_CONTINUE_SCENES",
  "customerVisible": false
}

Disposition framework

Every failure-producing boundary should answer the same questions in the same order.

1. PreventCan validation stop this before an expensive call?
2. ResumeDid the provider already create a job or output?
3. RetryIs the cause transient, bounded, and idempotent?
4. RepairCan a deterministic media or persistence correction recover it?
5. DeliverIs the remaining output genuinely usable?

Terminal failure test

A render is terminally failed only when retries are exhausted or inappropriate, no repair can create a usable result, and no already-created result asset can be safely delivered.

Spend-aware bias

Before provider spend, favor strict validation. After spend, favor recovery and salvage. Spend does not make corrupt output acceptable, but it raises the obligation to preserve and reuse completed work.

Failure disposition matrix

This is the working policy. Individual error codes in the catalog should map to one of these dispositions.

Failure classDefault responseRetry or repair boundaryFinal outcomeCustomer disclosure
Customer-fixable preflightStop before spend.No retry until input/account state changes.Failed to startSpecific cause and direct action.
Invalid script-plan duration or read-timeRun one constrained LLM repair before TTS/video generation.Repair only invalid scenes; validate again.Continue, or fail before spend.Generic retry if repair still fails.
Malformed model JSONRetry parsing/generation with schema feedback.Small bounded attempt count; do not restart purchased media stages.Continue, or terminal planning failure.Generic; raw model output stays internal.
Provider timeout, network failure, 429, or 5xxRetry with backoff and jitter.Resume an existing provider job when one was created.Continue, or fail after bounded exhaustion.Usually generic “try again.”
Provider credits exhaustedDo not retry.Wait for the customer or operator to add provider credits.FailedName the provider and required action.
Bad provider request or unsupported model capabilityDo not replay the same request.Correct validation/configuration first.Fail before spend where possible.Generic unless customer configuration can fix it.
OOM before provider workRetry on the configured larger machine.Stage-local retry only.Continue, or fail after escalation.Generic; machine details internal.
OOM after provider job creationResume the provider job or reuse the same-run asset.Never submit a duplicate paid job merely because the worker restarted.Continue, or fail after recovery exhaustion.Generic.
FFmpeg duration or timestamp mismatchApply direction-aware normalization and re-probe.Do not blindly rerun an identical deterministic command.repaired, degraded, or unusable.Usually none; visible degradation may get a calm notice.
Upload or asset-row persistence failureRetry persistence using the existing local/provider output.Do not regenerate upstream media.Continue, or fail if no durable result can be stored.Generic.
Final asset exists but completion update failsReconcile the run to the persisted result asset.Database repair, not media regeneration.completedNormal ready email after reconciliation.
Parent process death or stale runWatchdog inspects child runs, assets, and heartbeat.Resume, reconcile, or terminally fail outside the dead parent.Recovered completion or true failure.Email only after watchdog establishes terminal state.
Email delivery failureRetry email independently.Must not change render outcome.Render stays completed or failed as recorded.No duplicate emails; support can resend.

Final-media salvage policy

Narration is the canonical timeline because truncating spoken content is usually the most damaging result. Duration difference alone should not be a hard-failure threshold.

Acceptance versus investigation

  • Frame-scale differences are normal and should be accepted.
  • A difference around one second is a useful quality-warning and investigation threshold—not an automatic failure threshold.
  • Every repair must be re-probed and produce a playable final file.
  • Large differences should increase warning severity and observability, even when repair succeeds.

What should actually hard-fail

  • Corrupt, empty, or unplayable final output.
  • Essential narration is absent or unintelligible.
  • Most required scenes are missing or materially wrong.
  • A selected Presenter never appears.
  • Synchronization is misleading or obviously broken after repair.
  • The finished output cannot be persisted or securely delivered.
Observed conditionPreferred repairQuality result
Scene track is longer than narration/Presenter timeline.Trim to the canonical timeline and apply a short ending fade where helpful.repaired
Scene track ends before narration.Extend or freeze the final visual, with a subtle motion/fade treatment if available.repaired or degraded
Presenter ends before narration.Fade the Presenter out and allow scenes plus narration to finish.degraded
Presenter continues beyond narration.Trim verified trailing silence; otherwise extend the visual timeline without cutting speech.repaired or degraded
Joined video differs from the canonical timeline because of timestamp/frame rounding.Normalize timestamps, trim to the canonical timeline, and re-probe once.repaired
Repair produces a valid but slightly awkward ending.Deliver it with a warning record; optionally offer “Try again.”degraded
Do not use -shortest as the quality policy. It is a useful FFmpeg safeguard, but it can silently truncate the wrong stream. Measure inputs first, choose the repair intentionally, and validate the produced output.

Repair invalid plans before expensive generation

The script-planning prompt already expresses duration and word-count limits, but silent numeric clamping can hide a semantic mismatch: the text may still be too long for the clamped Scene. The image-to-video provider also has its own hard duration limit. The validator must operate on the raw plan and on the final provider request duration, including Transition handles.

DraftGenerate the full Scene-ordered plan.
ValidateSchema, Scene ids, duration, words/read-time, handles.
Repair onceSend only actionable issues and preserve valid Scenes.
Validate againNo silent semantic clamping.
GenerateOnly now call TTS, Presenter, and video providers.

Repair-call contract

Recommended terminal code: use a distinct internal result such as SCRIPT_PLAN_REPAIR_FAILED so malformed transport JSON, semantic plan invalidity, and provider duration incompatibility are observable separately.

Retry, resume, and OOM strategy

Retries belong at the smallest stage that can recover without repeating unrelated work or repurchasing provider output.

StageRetry strategyIdempotency requirement
Script/movement planningBounded retry for malformed JSON and transient OpenRouter errors; one semantic repair pass.Persist only a validated plan; no downstream provider work has started.
NarrationRetry transient transport/provider failures; do not retry credits, authentication, or invalid voice configuration.Reuse a persisted narration asset; persist provider request identity when supported.
Scene provider generationResume polling/import when a provider job exists. OOM retry may escalate the machine.Persist provider job id/output checkpoint before download and normalization; same-run asset reuse first.
Presenter generationResume the HeyGen video id rather than submitting another creation request.Persist the video id immediately after creation; reuse stored Presenter video and metadata independently.
Final FFmpeg assemblyRetry OOM on a larger machine; apply deterministic repair for known media defects.All narration, Scene, and Presenter assets are already durable and must be reused.
Persistence and completionRetry the failed upload/database operation or reconcile an existing asset.Stable storage paths, fingerprints, and asset/run linkage.

Attempt versus terminal ownership

A child task may report attempt telemetry, but it should not mark the whole render run terminally failed while its retry policy can still recover. One coordinator—or a watchdog when the coordinator dies—owns the terminal transition and failure-email enqueue.

Same-run recovery versus fresh customer renders

Recovery reuse must be scoped to the same render run. A customer choosing “Generate” for a fresh version should continue to receive fresh provider generation. A worker retry within that run should reuse every successfully generated asset and provider job.

Customer communication policy

Expose information when it helps the customer resolve the problem. Keep implementation diagnostics internal.

OutcomeEmailListing-page surfaceInternal record
completed / standardNormal ready email.Preview and download.Ordinary stage metrics.
completed / repairedNormal ready email.No warning unless the repair is perceptible or actionable.Original difference, repair action, probe result.
completed / degradedReady email; do not call the render failed.Calm notice: “Your video is ready. We made a timing adjustment near the ending. You can use this version or try again.”Warning code, severity, affected stage, support reference.
Provider credits exhaustedFailure email names ElevenLabs or HeyGen and links back to the Listing.Explain that provider credits must be added before retrying.Normalized billing classification; raw payload private.
Transient/internal terminal failureGeneric saved-work assurance, Listing link, and retry/help path.Retry action and safe support reference.Provider HTTP status, task attempt, asset ids, stack/FFmpeg diagnostics.
Failure email rule: send exactly once, only after terminal state is established and no usable final asset can be delivered. A recovered retry or degraded completion must not send a failure email.

Implementation roadmap

Build the disposition foundation before adding isolated retries. Otherwise retries, failure emails, and database status can disagree.

  1. Outcome and warning foundation

    Add a quality classification and structured warning records without changing the existing completed lifecycle semantics. Define one terminal-state owner.

  2. Pre-spend plan validation and repair

    Validate raw LLM output, read-time, Transition handles, and provider limits. Add one constrained repair pass and make silent provider-duration caps unreachable.

  3. Final-media salvage

    Probe narration, joined scenes, Presenter, and output; apply direction-aware trim/extend/fade; re-probe; record repaired or degraded quality.

  4. Provider checkpoints and same-run reuse

    Persist OpenRouter and HeyGen job identities immediately, resume polling/import, and ensure retries never repurchase completed work.

  5. Stage-local retry and OOM escalation

    Classify transient errors, add bounded backoff, retry FFmpeg OOM on larger machines, and remove attempt-level terminal database writes.

  6. Watchdog and reconciliation

    Detect stale runs, inspect child/provider/asset state, resume or reconcile completion, then mark true failure and enqueue notification if recovery is impossible.

  7. Customer and support surfaces

    Verify failure email in a controlled environment, add provider-credit guidance, show degraded-output notices, and provide a safe support reference.

  8. Operational feedback loop

    Report frequency, provider spend exposure, recovery rate, duplicate-job prevention, degraded-delivery rate, and terminal failures by normalized disposition.

Required production-shaped validation

Unit tests alone are insufficient for process death, provider resumption, and FFmpeg timing behavior. Each high-risk policy needs a failure-injection scenario.

Success measures

Recovery

Higher percentage of runs with provider spend that end in a deliverable asset.

No duplicate spend

No second provider creation request when a resumable job or same-run asset exists.

Honest outcomes

Failure notifications correspond only to terminal unusable runs; degraded results remain available.

Decision log and open calibration

Accepted direction
  • Prefer a usable, slightly imperfect result over discarding expensive completed work.
  • Do not use a one-second duration difference as an automatic hard-failure rule.
  • Keep lifecycle completion separate from output-quality warnings.
  • Use strict pre-spend validation and salvage-oriented post-spend handling.
  • Preserve fresh-render semantics while reusing work during retries of the same run.
Calibration to make with real outputs
  • How many frames constitute silent acceptance versus a recorded repair.
  • When a degradation notice is perceptible enough to show to the customer.
  • How long a frozen final visual remains acceptable before the result should be flagged for support review.
  • Whether severe but usable degradation should automatically offer a no-charge retry.

These should be calibrated from a small library of real repaired videos, not chosen solely from numeric duration thresholds.

Non-goals for the first resilience release
  • Guaranteeing email delivery when the entire task platform and independent monitor are both unavailable.
  • Automatically exposing raw provider, FFmpeg, storage, or Trigger.dev diagnostics to customers.
  • Rebuilding every render stage around a new lifecycle-status enum in one release.
  • Using unlimited retries to mask deterministic defects or provider billing failures.