Skip to content

Creative Commissions: let the user pick the creative output type and tailor params + directive per type #2769

Description

@atomantic

Part of #2657 (Autonomous Creation Engine).

Problem / Goal

A Creative Commission is a standing, scheduled creative brief. Today it can only ever produce video — the config form exposes video-only generation params (aspect ratio, duration, quality), the composed directive just says "Create a video piece.", and the scheduler hard-skips anything else. Yet the underlying Creative Director plan stage is a general orchestrator: data.reference/prompts/stages/cd-plan.md lists the entire registry (series, image, comic, music, universe, video tools) and asks the model to decompose the directive using whichever fit. So on every run the model is handed the full menu of "how to declare a series / image / music / video" options and left to infer intent from free-text, instead of being told up front what kind of thing to make.

We want the user to pick the creative output type (series, music, music video, image, video) when creating/editing a commission, and have the form params and the composed directive tailor themselves to that type — so a "make an image daily" commission ships an image with image params and an image-specific directive, not a video treatment with irrelevant duration controls.

This is the "ability adapter" already anticipated in the schema comment:

server/lib/creativeCommissionValidation.js:22"Phase 1 supports video only … Phase 3/4 widen it (image, universe, series, story, writers-room, music) alongside the ability adapter."

Context

Current state, grounded in the code:

  • Ability enum is frozen to video. CREATIVE_COMMISSION_ABILITIES = Object.freeze(['video']) (server/lib/creativeCommissionValidation.js:22). targetAbility defaults to 'video' in both the sanitizer (server/services/creativeCommissions/store.js:152) and the form mapper (client/src/components/creative-commission/commissionForm.js:38).
  • Generation params are video-only. creativeCommissionGenerationSchema (creativeCommissionValidation.js:99) is { model, quality, aspectRatio, targetDurationSeconds }. The form section is literally titled "Generation (video)" and hardcodes those three controls (CommissionConfigForm.jsx:156-198). There is no output-type selector in the form at all.
  • Directive is generic. buildCommissionDirective (server/services/creativeCommissions/directive.js:113-147) emits Create a ${ability} piece. <intent> + genre/category/style lines, then feeds it to createProject({ directive }). The deliverables line is One ${ability} artifact matching the brief.
  • Scheduler hard-skips non-video and passes video geometry. server/services/creativeCommissions/scheduler.js:212if (commission.targetAbility !== 'video') return skip('unsupported-ability'). Then createProject({ aspectRatio, quality, modelId, targetDurationSeconds, styleSpec, directive, modelOverrides }) (scheduler.js:276-286) — the video "locked render settings" the plan prompt references.
  • The CD registry already supports every requested type. server/services/creative/tools/ exposes pipeline_createSeries, pipeline_generateSeriesConcept, pipeline_startSeriesAutopilot, pipeline_renderComicCover/Page, media_enqueue*Job, music-bed generation (server/services/creativeDirector/firstPassMusicGen.js), universe tools, etc. cd-plan.md hands all of these to the planner. So no new generation capability is required — only front-end selection + a type-specific directive/params that steer the existing planner.
  • Federation & backward-compat. targetAbility and generation are federated fields (FEDERATED_COMMISSION_FIELDS, commissionForm.js:237; store briefUpdatedAt LWW at store.js:195). Existing installs have targetAbility: 'video' records that must keep working unchanged — the widening is additive.

Prior art to mirror:

  • Conditional-by-kind rendering already exists in the same form for the schedule section (CommissionConfigForm.jsx:103-151 switches fields on schedule.kind). The output-type param section should follow the same pattern, keyed on targetAbility.
  • Absent-vs-empty / per-field defaults conventions in creativeCommissionGenerationUpdateSchema (creativeCommissionValidation.js:110) and the deep-merge in store.js:544 must be preserved for whatever per-type param shape replaces the flat video one.

Proposed approach

Introduce a small ability-adapter registry — one adapter per output type — so the type owns its params, directive, and project-creation mapping, and every other layer keys off targetAbility instead of assuming video.

  1. Widen the enum. Extend CREATIVE_COMMISSION_ABILITIES (creativeCommissionValidation.js:22) to ['video', 'image', 'music', 'music-video', 'series']. Keep 'video' first so it stays the default.

  2. Ability-adapter module (new, e.g. server/services/creativeCommissions/abilityAdapters.js, a pure leaf like directive.js). Each adapter declares:

    • ability, human label
    • generationDefaults + a Zod generationSchema (and .partial() update variant) for that type's params
    • buildDirective(commission){ goal, deliverables, constraints } that is prescriptive for the type (e.g. image → "Produce a single still image …" using catalog/image tools; series → "Create a new series in the target universe and generate its first issue …"; music → "Compose a music bed …"; music-video → video + music). This replaces the generic Create a ${ability} piece line in buildCommissionDirective — refactor that function to delegate to the adapter, keeping the feedback-digest fold and char-budget clamps (MAX_DIRECTIVE_GOAL_LEN etc.) intact and type-agnostic.
    • buildProjectParams(commission) → the arg map for createProject (video/music-video pass aspect/duration/quality; image/music/series pass their own and let the video geometry defaults be harmless since the planner only forces geometry onto media_enqueueVideoJob steps).
    • Per-type generation param set, e.g.: image = aspect ratio + count + quality (no duration); video = current (aspect ratio + duration + quality); music = length + engine/genre (no aspect ratio); music-video = video + music params; series = target universe/series + episode count + autopilot depth.
  3. Validation. Replace the flat creativeCommissionGenerationSchema with a per-ability shape (discriminated union on targetAbility, or a generationSchemaFor(ability) selector), wired into both POST and PUT (.partial() for PUT) per the "schema parity" convention. Keep tolerating an empty generation object (the existing no-.default({}) reasoning at creativeCommissionValidation.js:93).

  4. Sanitizer. Update sanitizeCommission (store.js) to fill per-type generation defaults from the selected adapter and to preserve type-specific keys (don't strip an image count or a series episodeCount), keeping the deep-merge (store.js:544) shape-correct across types.

  5. Form. Add an output-type <select> to CommissionConfigForm.jsx (bind targetAbility), and render the generation section from the selected adapter's field list — conditionally, exactly like the schedule-kind switch. Update commissionForm.js toForm/toPayload/blankForm/validateForm to carry the adapter's params. Retitle the section from "Generation (video)" to the adapter label.

  6. Scheduler. Replace the unsupported-ability hard-skip (scheduler.js:212) with a lookup: unknown ability → skip('unknown-ability'); known → build the directive and createProject args from the adapter (scheduler.js:276). Keep the existing provider-pin guard and budget/autonomy gates unchanged.

  7. Tests. Unit-test each adapter's buildDirective/buildProjectParams and generation schema; extend directive.test.js for the per-type goal composition (feedback digest still folds); update store.test.js sanitizer cases for each type; update scheduler.test.js so a non-video commission now creates a project instead of skipping. Add a form-mapper test for toForm/toPayload round-trip across types.

Land order (may be stacked PRs, but all five are in scope for this issue): framework + enum + video refactored onto the adapter first (behavior-preserving), then image, music, music-video, series.

Acceptance criteria

  • CREATIVE_COMMISSION_ABILITIES includes video, image, music, music-video, series; video remains the default and existing video commissions run unchanged (no migration needed — verified additive).
  • The commission config form shows an output-type selector, and the generation-param section renders the fields for the selected type (image has no duration control; music has no aspect-ratio control; etc.).
  • buildCommissionDirective delegates to the per-type adapter and emits a type-specific goal + deliverables (an image commission's directive tells the planner to produce an image, a series commission to create a series, etc.), with the feedback-digest fold and char-budget clamps preserved.
  • The scheduler creates a CD project for every supported type (no unsupported-ability skip for image/music/music-video/series), passing the adapter's project params.
  • Generation params are validated per-type on both POST and PUT (.partial()), and the sanitizer preserves type-specific keys through the deep-merge.
  • targetAbility + per-type generation continue to federate correctly (sanitizer tolerant of every type's shape; briefUpdatedAt LWW unaffected).
  • Unit tests cover each adapter (directive + project params + generation schema), the sanitizer per type, the scheduler non-video path, and the form-mapper round-trip.

Out of scope

  • New generation capabilities — this reuses the existing CD registry tools; it does not add new renderers, engines, or cd-plan.md tool entries.
  • The broader ability set the schema comment also names (universe, story, writers-room) — only the five the request enumerates are in scope; the rest stay future work under Autonomous Creation Engine: schedule the Creative Director with a recurring, feedback-steered creative brief #2657.
  • Changes to the CD cd-plan.md / cd-treatment.md prompt files unless a type genuinely can't be steered by the directive goal alone (prefer directive text over prompt-file edits; if a prompt-file change is unavoidable it needs the usual stage-prompt migration).
  • Backfilling or migrating existing commissions to a new type (they stay video).

Metadata

Metadata

Assignees

Labels

area:createUniverse/catalog/Create-suiteenhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions