Skip to content

feat: remix tier gating — t1/t2 behind explicit opt-in (default unchanged)#20

Open
mtmtian wants to merge 5 commits into
oratis:mainfrom
mtmtian:feat/remix-tiers
Open

feat: remix tier gating — t1/t2 behind explicit opt-in (default unchanged)#20
mtmtian wants to merge 5 commits into
oratis:mainfrom
mtmtian:feat/remix-tiers

Conversation

@mtmtian

@mtmtian mtmtian commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

This PR does NOT change the shipped default: REMIX_ENABLED_TIERS defaults to t0_5 only — the borrow-structure-not-pixels policy in remix-brief.ts / competitor-media.ts remains the effective behavior out of the box.

What this adds

Tier codes for t1/t2 exist in the remix worker engine's control plane, but stay behind an explicit env opt-in. Nothing about the default request path changes.

Tier What it does Competitor pixels in output?
t0 Your existing single-shot remix path (/api/creatives/remix) untouched by this PR
t0.5 (#19) Pure text-derived storyboard, no visual reference zero
t1 Generates using the already-stored Tier-2 competitor video as an @reference for the worker zero — reference only, no competitor frames in the output
t2 Reuses specific, human-approved clean segments from the stored competitor video (segmentPlan) yes — output is tagged containsCompetitorFootage: true

Gating mechanics

  • REMIX_ENABLED_TIERS (comma-separated, default "t0_5") gates which tiers POST /api/creatives/remix-jobs will accept. Tier not in the set → 403. Tier not a known code → 400.
  • t2 requires a validated segmentPlan with at least one action: "reuse" segment, or 400.
  • t1/t2 both require the competitor's video to already be stored via your existing Tier-2 "Save video" flow (CompetitorCreative.assetIdAsset.fileUrl) — this reuses your hand-picked, legal-cleared winners gate rather than adding a new one. Missing it → 400 with a "use the Tier-2 Save video flow first" message.
  • POST /api/worker/remix-jobs/claim now returns refs: [{url, kind:'video'}] for t1/t2 jobs, pointing the worker at that stored Asset. t0_5 is untouched.
  • Every tier still creates the Creative with reviewStatus: 'pending' — the human review gate is identical across tiers, this PR only changes what's allowed to be generated, never what's allowed to ship without review.

Why gate via env instead of code-only

This moves the t1/t2 IP boundary from "not possible in code" to "off by default, explicit config choice + auditable via REMIX_ENABLED_TIERS, gated behind your own Tier-2 hand-picked-video approval step." That gives you (or legal/product) a deliberate lever to pull per deployment, rather than a hardcoded wall — while leaving the out-of-the-box behavior identical to today.

Stacked on #19

This branch is based on feat/remix-worker (#19, still pending review) and includes its commits. Once #19 merges, this diff will automatically shrink to just the tier-gating commit (51c1ce8).

Test plan

  • npm run lint — 0 errors (pre-existing warnings only)
  • npx tsc --noEmit — clean
  • npx playwright test e2e/remix-jobs.spec.ts — 14/14 passing, including new coverage for: unknown-tier 400, t2-without-segmentPlan 400, t2/t1-without-stored-video 400. (The e2e webServer runs with REMIX_ENABLED_TIERS="t0_5,t1,t2" so these 400 branches — which sit downstream of the 403 gate — are exercised; the refs[] happy path requires a stored competitor Asset and is left to cross-repo integration with the worker.)

🤖 Generated with Claude Code

mtmtian and others added 5 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.
Adds t1/t2 tier codes to the remix worker engine behind an explicit
REMIX_ENABLED_TIERS opt-in (defaults to t0_5 only, matching current
IP policy). t1/t2 require a segmentPlan (t2) and a Tier-2 hand-picked
competitor video already stored via the Save video flow; claim now
returns refs[] pointing the worker at that stored Asset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WHY: post-PR adversarial review of 51c1ce8
WHAT: segmentPlan requires non-negative ordered non-overlapping segments
(max 64) within the source video duration; REMIX_ENABLED_TIERS always
keeps t0_5 enabled; t2 Creative.duration derives from kept segments;
claim refs lookups scoped to the job's org
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