Skip to content

feat: remix worker engine (t0.5) — RemixJob orchestration + claim/report/upload#19

Open
mtmtian wants to merge 3 commits into
oratis:mainfrom
mtmtian:feat/remix-worker
Open

feat: remix worker engine (t0.5) — RemixJob orchestration + claim/report/upload#19
mtmtian wants to merge 3 commits into
oratis:mainfrom
mtmtian:feat/remix-worker

Conversation

@mtmtian

@mtmtian mtmtian commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What

Adds a second, worker-driven remix engine alongside the existing in-app single-shot text2video path (which is untouched). This phase ships tier t0.5 only: per-beat text-described regeneration — the storyboard from buildRemixBrief is generated beat-by-beat by an external worker (Cloud Run Job, separate repo), assembled with ffmpeg, brand-QC re-scanned (whisper + OCR), and lands as the same review-gated Creative(source:'remix', reviewStatus:'pending'). Competitor material stays analysis-only — no competitor pixels enter generation, consistent with the "borrow structure, not pixels" rules in remix-brief.ts / competitor-media.ts.

  • RemixJob model + migration: brief snapshot, per-beat progress, qcReport, costTokens; tier / segmentPlan fields reserved for later tiers (API rejects anything but t0_5 for now).
  • POST/GET /api/creatives/remix-jobs (session auth): reuses buildRemixBrief / competitorCreativeToAnalysis; shares the existing remix burst + daily-cap guardrails.
  • Worker endpoints under /api/worker/remix-jobs/* (HMAC via ingest-auth.verifyHmac, new WORKER_WEBHOOK_SECRET):
    • claim — atomic pickup (updateMany count check) with REMIX_JOB_LEASE_MINUTES stale-lease recycling
    • report — atomic status state machine (pending→claimed→running→assembling→qc→succeeded/failed, terminal states locked, 409 on illegal transitions); outputUrl must match the canonical upload path; QC-fail is surfaced to reviewers via Creative.reviewNotes (promotion not blocked — reviewer decides)
    • upload — raw mp4 → GCS via server-side uploadToGCS (content-sha256-bound HMAC, pre-buffer header checks, 100MB cap)

Design notes

  • Zero modifications to the existing remix/competitor files — only imports. storage.ts gains one additive export (gcsPublicPrefix).
  • Both engines feed the same /creatives/review gate; remix history keeps working via Creative(source:'remix').
  • Worker runtime lives in a separate repo (ffmpeg/whisper/tesseract image); dry-run mode reproduces the full flow at zero generation cost.

Test plan

  • npm run lint / npx tsc --noEmit clean; migration verified against schema with prisma migrate diff (no drift).
  • e2e/remix-jobs.spec.ts: 15 passed — happy path (ingest → job → claim → running/assembling/qc → succeeded promotes Creative to ready), claim atomicity, HMAC rejection, terminal-state 409, unclaimed→succeeded 409, non-canonical outputUrl 400, QC-fail reviewNotes.
  • Live cross-repo integration against the real worker: full sequence verified, including the 409 terminal guard.

Context: this is the first slice of the tier-ladder proposal (t0 = your existing path / t0.5 = this PR / t1 & t2 gated pending the policy question in the alignment doc we shared). Happy to adjust RemixJob modeling or StoryboardBeat integration to your preference.

🤖 Generated with Claude Code

mtmtian added 3 commits July 15, 2026 16:47
Add an independent worker-engine RemixJob path alongside the existing
Seedance2-direct remix: control plane creates a pending RemixJob + brief via
POST /api/creatives/remix-jobs, an external HMAC-authenticated worker claims
it, generates beats, assembles/QCs the clip, and reports progress/results
back via /api/worker/remix-jobs/{claim,report,upload}. Purely additive —
reuses buildRemixBrief/competitorCreativeToAnalysis from remix-brief.ts
without touching any existing files.
…n upload

Close the code-review gaps on the worker-facing RemixJob surface: report/
now enforces an atomic ALLOWED_PREV transition table (succeeded/failed are
terminal), validates outputUrl against the canonical GCS upload path, and
surfaces brand-QC failures via Creative.reviewNotes instead of silently
promoting. upload/ pre-checks HMAC headers and content-length before
buffering the body. claim/ recycles stale in-flight jobs after a configurable
lease window and collapses the duplicated jobId/queue branches into one
atomic updateMany. De-dupes asJson + canvas-dims math into
src/lib/growth/remix-job.ts, and shares the e2e HMAC-signing helper between
remix-jobs.spec.ts and competitor-ingest.spec.ts.
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.

1 participant