/** * Output diagnosis — a PURE, deterministic root-cause tree for Seedance output * quality failures. No I/O, no Date, no Math.random. * * Diagnose before rewriting: a generic/morphing/jittery/blocked/off-prompt output * has a root cause, and the fix is to remove the conflict, not add adjectives. * Each row carries a `tool` pointer to the existing vclaw remedy, so this is the * front door that unifies the harvested pieces (anti-slop, vfx, reference * transfer, retake, continuation, content-filter). * * The GENERAL output-quality rows, harvested from the MIT `Emily2040/seedance-2.0` * `seedance-troubleshoot` Diagnostic Tree (@63b32dc). The continuation/sequence * rows are intentionally NOT duplicated here — they live in * `continuation-handoff.ts` (`diagnoseContinuation`). */ export interface DiagnosisRow { symptom: string; cause: string; repair: string; /** The existing vclaw tool/remedy that addresses this failure, when one exists. */ tool?: string; } export const OUTPUT_DIAGNOSIS: readonly DiagnosisRow[] = [ { symptom: 'Product or face changes between frames', cause: 'The I2V prompt re-described visible identity or overloaded motion.', repair: 'Add preservation constraints; remove duplicate static detail; let the reference carry identity.', tool: 'prompt-lint (reference-transfer / proper-name leak) + Seedance Asset Library', }, { symptom: 'Camera jumps or stutters', cause: 'Several incompatible moves, or no endpoint.', repair: 'Choose one move with a clear start and finish.', tool: 'multi-shot (shot-grammar movement) / cinematography', }, { symptom: 'Generic output despite a long prompt', cause: 'Hollow style words and weak action diluted the attention budget.', repair: 'Replace evaluators with physical action, a source light, a material, and a sound.', tool: 'prompt-lint slop (anti-slop lexicon)', }, { symptom: 'Motion ignored / subject static', cause: 'Static prompt or no visible consequence.', repair: 'Add an actor, a verb, timing, and a changed end state.', tool: 'multi-shot / filmmaking-prompts FRAME MAP', }, { symptom: 'Lip-sync poor', cause: 'Moving head or camera, a long line, or an unassigned speaker.', repair: 'Lock framing, shorten the line, and assign the speaker on-screen.', tool: 'multi-shot --dialogue (speaker assignment)', }, { symptom: 'VFX noisy or overlay-like', cause: 'The effect has no source, physics, or dissipation.', repair: 'Add a source, material, motion path, interaction, and a visible endpoint.', tool: 'multi-shot --vfx (vfx-register)', }, { symptom: 'Prompt blocked / rejected', cause: 'Protected IP, a real-person likeness, graphic content, or bypass-like wording.', repair: 'Rewrite the intent in safe production language, without evasion.', tool: 'seedance content-filter (sanitizePrompt / preValidatePrompt)', }, { symptom: 'Extension / continuation quality degrades', cause: 'No last-frame anchor, or too many new variables across continuations.', repair: 'Use the returned last frame as the next first frame and change one variable only.', tool: 'reroll-scene (retake protocol) + continuation-handoff', }, { symptom: 'Audio reference ignored', cause: 'Competing video sound, no visual beat mapping, or an unsupported combination.', repair: 'Mute the competing video audio and map one visible event to the beat.', tool: 'audio-platform / assemble mix-plan', }, { symptom: 'Text or logos break up', cause: 'Small text was asked to move or be redrawn during motion.', repair: 'Keep text static, centered, and protected; animate light around it, not through it.', tool: 'filmmaking-prompts LAST FRAME (no-on-screen-text guard)', }, { symptom: 'Client QC fails on delivery', cause: 'Prompt output was treated as a final deliverable without post or QC.', repair: 'Route to delivery preflight, fix in post, or regenerate only the failing shot.', tool: 'assemble media-qc + reroll-scene', }, ]; export const CONSERVATIVE_RETRY_PATTERN = '[Reference role if any]. Preserve [identity/product/environment] exactly. ' + 'One visible action: [specific verb and consequence]. Camera: [single move]. ' + 'Lighting: [physical source]. Sound: [ambient/SFX/dialogue]. ' + 'Constraints: [what must not change].'; /** * Filter the diagnosis tree by a keyword over symptom/cause/repair * (case-insensitive). No query → every row (a fresh array copy). */ export function diagnoseOutput(query?: string): DiagnosisRow[] { if (!query || !query.trim()) return [...OUTPUT_DIAGNOSIS]; const needle = query.toLowerCase().trim(); return OUTPUT_DIAGNOSIS.filter((row) => `${row.symptom} ${row.cause} ${row.repair}`.toLowerCase().includes(needle), ); }