Taskcenter DocsOpen app

Features

Partial

Aesthetics

Platform-wide style presets for Design and Video

Overview

Platform-wide image and video style presets. A platform admin curates them under Admin → Configuration → Style presets; a user picks one as a tile in the composer's Design or Video lane. The chosen aesthetic's prompt fragment reaches image generation verbatim. Video selection has no production effect while rendering is unavailable. This is Taskcenter's analogue of Studio's `globalStylePresets` (Admin, Global Presets: name, prompt, cover image, reference images, picked as a tile in the composer and injected into the send). It is distinct from `design_directions` (migration 0061): a design direction is an org-scoped palette/typography/composition profile the website and deck lanes resolve automatically (`directionId: "auto"`); an aesthetic is an explicitly chosen, admin-authored prompt fragment for the image and video lanes with no palette schema to fake.

01

Status

`Live` for the admin section, the composer picker, and the image lane prompt. `Partial` for video: Video composer requests stop before model planning because no rendering provider is configured. The chosen aesthetic is not consumed by a video tool or model brief, and no rendered video is claimed. The curated starter catalog ships product-owned generated reference art under `/aesthetics/catalog/*`. Admin-authored reference images remain plain `https` URLs. There is no admin upload path into R2 for non-artifact bytes yet, so the editor stores URLs and says so; the first URL is the composer cover and the remaining references stay attached to the preset for review. Presets without approved reference media remain typography-led and say that no approved image exists; the product never fabricates a thumbnail.

02

Entry routes

- Admin: `/admin#aesthetics` (section "Style presets", collapsed Configuration group). - Composer: the Design lane (`+` menu, Design) presents aspect ratio followed by a searchable aesthetic gallery. Automatic is the first/default choice. The one-image count, redundant model Auto, tone selector, and prompt starters are intentionally absent from this focused lane. As the gallery scrolls, the same prompt bar sticks to the top of the canvas and transitions to its compact thread geometry; it expands again on return to the top. Video keeps the same server-backed aesthetic picker while rendering remains unavailable. - API (platform admin only, browser session; API tokens are refused): - `GET /api/admin/aesthetics` lists every aesthetic, active and archived. - `POST /api/admin/aesthetics` creates one (`name`, `description`, `promptFragment`, `referenceImageUrls[]`, `sortOrder`). - `PATCH /api/admin/aesthetics/:aestheticId` edits the same fields, or `{ "action": "archive" | "restore" }` flips its status. - API (any signed-in workspace member): `GET /api/agent/aesthetics` returns active aesthetics as composer tiles (`id`, `name`, `description`, `referenceImageUrls`). The prompt fragment never leaves the server on this route.

03

Data source

- Table `aesthetics` (`migrations/0267_aesthetics.sql`), indexed on `(status, sort_order, name)` for both list reads. Rows are platform-wide; `organization_id` records the organization of the platform admin who last wrote the row (audit provenance and the guarded adapter's organization binding), never a read scope. - `migrations/0310_curated_aesthetic_catalog.sql` installs 36 platform-owned starter directions, including the requested print, digital, image-processing, and art-history looks. Each row contains an executable prompt fragment that affects live image generation. Migration rows use `platform_catalog` and `system_migration` as explicit provenance; they do not pretend to be authored by a workspace user. A platform admin can edit, archive, reorder, and attach up to four approved HTTPS reference images to any row. - Guarded access only: `src/features/aesthetics/server.ts` (feature block `aesthetics`) reads with `allowGlobalRead` and writes through `adapter.write` with audit events `aesthetics.created`, `aesthetics.updated`, `aesthetics.archived`, `aesthetics.restored` (target type `aesthetic`). - Rule 0: the composer only renders rows returned by D1. The starter catalog is durable product configuration rather than a hardcoded client fallback, and its prompt fragments are the real generation inputs.

04

Permissions

- `aesthetics:read` (platform scope, low risk): every workspace role including `agent`; gates the composer route and the runtime resolution. - `aesthetics:manage` (platform scope, high risk): owner only in the registry; the admin routes additionally require `requirePlatformAdmin`, and `adminSurfaceDeniedResponse` refuses API-token actors before the platform lookup.

05

How the choice reaches generation

1. The picker writes `brief.aestheticId` (bounded id, no prompt text) and the composer mirrors it onto `mediaOptions.aestheticId` at submit. 2. For admitted Design requests, the DO runtime adds one `<selected_aesthetic>` block to the turn context (`src/features/aesthetics/runtime-brief.ts`) so the model plans against the real name and fragment; an archived choice is reported as unavailable, never replaced with an invented look. Video composer requests stop before that model-planning path. 3. For images, `applyComposerMediaOptions` (`src/features/open-design-artifacts/composer-media-tool-input.ts`) resolves the id through the guarded adapter at admission and copies `{ id, name, promptFragment }` onto the durable `design_media_tasks` request, so the retained task records exactly what rendered even if the admin edits the aesthetic later. The model-visible media schema cannot supply an aesthetic; without a server-resolved composer selection, the tool input is forced to `null` even if a caller invents one. An archived choice fails the tool call loudly. 4. `processMediaTask` forwards the selection and the production media provider (`src/features/open-design-artifacts/media-lifecycle-production.ts`), the one live prompt owner, composes `subject`, then `Aesthetic (<name>): <fragment>`, then the aspect-ratio and variation constraints, and records `normalizedInputs.aesthetic` for provenance. No second prompt builder was added.

06

Empty state

- If the catalog migration is unavailable or every row has been archived, the admin shows "No aesthetics yet" with the instruction to add the first one, and the composer explains that generation will use no preset look. The picker never substitutes a placeholder list. - When rows exist, the composer presents a bounded responsive gallery with search. A reference image becomes the tile cover and its preview action opens all attached references in a bounded dialog; a preset without one explicitly states that no approved reference image exists until a platform admin attaches one.

07

Failure state

- D1 unbound: the admin section and the composer route return 503 with "Cloudflare D1 is unavailable; aesthetics could not be loaded."; the composer shows that message with a Retry control, and the admin panel shows it in an alert with Retry. Neither surface spins indefinitely. - Not a platform admin: 403 "Platform admin access is required."; an API token gets the actionable browser-session refusal. - Invalid input: 400 with the field-level validation message (names 1-80 chars, fragment 1-1200 chars, up to 4 https reference URLs). - Unknown id on edit/archive/restore: 404. - Chosen aesthetic archived after selection: the image tool call fails with "The selected aesthetic is no longer available" and the model is told to ask the user to pick another.

08

Verification

- `tests/unit/aesthetics-server.test.ts`: permissions matrix and guarded CRUD with audit events through a fake D1. - `tests/unit/aesthetics-admin-routes.test.ts`: 403 for non-platform-admins and API tokens before any data access, 503 when D1 is unbound, create/edit/ archive/restore/404 contracts, composer route shape. - `tests/unit/aesthetics-prompt-seam.test.ts`: the fragment reaches the production provider prompt (exact composition), the durable request admits the bounded selection, admission resolution and the archived-choice failure, the brief block. - `tests/unit/aesthetic-picker.test.tsx`: list, selected state, thumbnail, empty sentence, failure with Retry. - `tests/unit/aesthetic-starter-catalog-migration.test.ts`: exact starter catalog, durable provenance, and substantive prompt fragments. - Browser proof of the admin section and both lane pickers follows the deploy.