# Approval-first Retention Studio core scaffold

Use this reference when implementing a short-form video automation repo before touching real Telegram, publishing APIs, or GPU/video generation.

## Durable pattern from the AutoShortsBot build

Build the pipeline as typed, side-effect-free layers first:

```text
ContentPillar
→ ContentBrief
→ ScriptDraft
→ VideoCandidate
→ TestBatch
→ ReviewBatch
→ Telegram ReviewDelivery
→ ShotPlan
→ RenderManifest / preview renderer later
```

Each layer should be deterministic and testable. Real external I/O comes after a pure preparation boundary.

## Recommended modules

```text
autoshorts/config/pillars.py          # channel strategy and no-go topics
autoshorts/content/brief.py           # pillar + topic + audience problem + payoff
autoshorts/content/script_draft.py    # hook, outline, retention beats, visual concept, caption, CTA
autoshorts/content/to_candidate.py    # ContentBrief + ScriptDraft -> CandidateDraft/VideoCandidate
autoshorts/ideas/factory.py           # stable candidate ids, default hashtags, duration classes
autoshorts/review/workflow.py         # ready / blocked / invalid buckets
autoshorts/review/render.py           # Telegram-safe review text
autoshorts/telegram/review_sender.py  # side-effect-free delivery plan, no real send
autoshorts/rendering/shot_plan.py     # five-scene retention plan before render manifests
```

## TDD sequence

For each layer:

1. Write the wished-for import/API test first.
2. Verify RED as a missing module/API or missing behavior.
3. Implement the smallest deterministic model/function.
4. Run the focused test and then the full suite.
5. Update README and commit.

Useful test assertions:

- stable IDs and order;
- review bucket counts;
- no publish/post language in review/delivery text;
- `requires_human_approval=True` and `side_effects=()` at delivery boundaries;
- no static slideshow asset modes;
- labels/captions are renderer-owned;
- first scene is `first_frame_hook`;
- invalid explicit blanks are rejected.

## Guardrails to bake into code

- Never publish/send/render as part of formatting or preparation code.
- Keep Telegram/publishing adapters behind an explicit later boundary.
- Use `x if x is not None else default`, not `x or default`, in factories/helpers so intentionally blank invalid inputs can be tested.
- Validate platform limits early, e.g. Telegram 4096 characters.
- Reject generic AI-slop phrases in script drafts before converting to candidates.
- Reject baked/generated/fake UI text in shot plans; captions, labels, arrows, and UI text must be renderer-owned.
- Start with a deterministic five-scene shot plan before invoking Qwen-Image, Wan, ComfyUI, or any other video/image generator.

## Why this matters

This prevents the common failure mode where a bot jumps from script prose directly to a generic AI slideshow or to dangerous posting automation. A boring typed artifact chain makes later GPU experiments cheaper, safer, and easier to review.