# Dashboard production concept gate and prepared-package handoff

Use this when producing AutoShorts/TrueTraceShorts from the Dashboard production plan.

## Contract: dashboard is source of truth

Do not produce from chat improvisation. The allowed sequence is:

1. `GET /api/agent/production/next`
2. Build a detailed concept proposal from the returned queue item.
3. `POST /api/agent/production/{id}/concept-proposed`
4. Present the concept in chat and stop.
5. Wait for `APPROVE_PRODUCTION <queue_item_id>` or an unambiguous approval for that exact concept.
6. Only after approval:
   - `POST /api/agent/production/{id}/approve-generation`
   - `POST /api/agent/production/{id}/mark-started`
7. Produce the prepared package.
8. `POST /api/imports/scan`
9. `POST /api/agent/production/{id}/attach-package`
10. `POST /api/agent/production/{id}/mark-ready-for-review`

A casual user command like “mach mal” or “Produziere das nächste Short gemäss Dashboard-Produktionsplan” is **not** enough to start production. The first response must be a detailed concept proposal.

## Backend safety rule

No UI button or API route may put an item into `producing` unless `concept_approved` is already true. Legacy/direct routes such as:

```http
POST /api/production-queue/{item_id}/send-to-production
```

must be safe. Preferred behavior: set/propose `concept_proposed`, not `producing`. Acceptable alternative: return HTTP 409 when `concept_approved` is missing.

Regression test shape:

- `send-to-production` returns/sets `concept_proposed`
- `mark-started` before `approve-generation` returns 409
- after `approve-generation`, `mark-started` may set `producing`

## Prepared package requirements

Create the package under:

```text
storage/incoming/<expected_package_id>/
```

Minimum files:

```text
video.mp4
manifest.json
```

Useful review files:

```text
thumbnail.jpg
transcript.txt
production_report.json
```

Manifest should include: `package_id`, `source: prepared_package`, `queue_item_id`, `family_id`, `working_title`, `language`, `series`, captions/titles/descriptions/hashtags, `script`, `hook`, `production_notes`, `disclosure.synthetic_media`, and `status: ready_for_review`.

## Review-only stop point

After import and attach, the target state is:

- Video appears in `/videos`
- Review page plays the video
- TikTok manual export is available
- YouTube private upload controls are available but not executed
- ProductionQueueItem status is `in_review`
- no UploadRequest for the new video unless explicitly approved later
- no TikTok upload/mock/draft API flow
- no YouTube upload, private or public
- no website push/merge/delete

## QA pattern before reporting

Run factual checks rather than relying on intent:

- `ffprobe` confirms 1080×1920, DAR 9:16, duration sane, audio present.
- Read manifest and verify queue/package IDs match dashboard expected fields.
- Vision-check thumbnail/startframe and fix visible issues before import: clipped footer text, black bars, fake UI overflow, unreadable chat text, or real-looking sensitive data.
- Browser-check `/videos` and the review page; confirm video element `readyState`, duration, width/height.
- Check linked UploadRequests for the new `video_asset_id` equals 0 unless upload was separately approved.

## Pitfalls

- If a visual QA catches small layout defects (e.g. a clipped footer), re-render before import. Do not rationalize it as “minor” for a first production run.
- Do not call `mark-started` before the explicit approval step, even if the dashboard item is locked/fixed.
- Do not invent YouTube IDs or assume upload success; upload must be represented by a real UploadRequest/audit or explicit later approval.
- Keep TikTok manual: dashboard can expose MP4/caption/hashtags, but do not use TikTok API flows for this workflow.
