# AutoShortsBot

AutoShortsBot is a semi-automatic short-form content engine for high-quality YouTube Shorts, TikTok, and Instagram Reels.

Current public strategy: **TrueTraceShorts — Digital Red Flags / Scam Self-Defense for Normal People**.

Core promise: **One screen. One red flag. One safer move.**

The channel shows normal people one dangerous detail before they click, pay, scan, or log in. It is no longer primarily an AI workflow / prompt engineering channel; those topics are secondary specialist formats.

The project is deliberately approval-first: it can draft, score, render previews, and prepare publishing metadata, but it must not publish anything without explicit human approval.

## Current scope

Implemented foundation:

- `autoshorts.cli.demo_local_preview_video` — local CLI entry point that renders deterministic PNG frames and an MP4 timing preview.
- `autoshorts.cli.demo_render_preview` — local CLI entry point that prints side-effect-free render-preview metadata plus HTML.
- `autoshorts.cli.demo_review_batch` — local CLI entry point that prints the deterministic review demo.
- `autoshorts.cli.demo_social_draft` — local CLI entry point that prints a side-effect-free social media draft review delivery.
- `autoshorts.cli.demo_telegram_delivery` — local CLI entry point that prints side-effect-free Telegram delivery metadata plus review text.
- `autoshorts.config.pillars` — content pillar registry for Digital Red Flags / Scam Self-Defense pillars and pillar fit validation.
- `autoshorts.content.brief` — strategy brief model for retention-led content development before scripting.
- `autoshorts.content.demo_pipeline` — deterministic content-to-Telegram-review demo pipeline.
- `autoshorts.content.script_draft` — structured script drafts with retention beats, visual concept, caption, CTA, and AI-slop validation.
- `autoshorts.content.to_candidate` — converts content briefs and script drafts into candidate drafts and validated video candidates.
- `autoshorts.demo.sample_batch` — deterministic AI-life-systems review demo with ready, blocked, and invalid candidates.
- `autoshorts.demo.truetrace_concepts` — five concrete TrueTraceShorts concept candidates with metadata for strategy review.
- `autoshorts.demo.truetrace_preview_packages` — renders top-3 TrueTrace local MP4 timing previews plus approval/manual upload packages.
- `autoshorts.audio.subtitles` — deterministic Hormozi-inspired, renderer-owned subtitle cue planning with active-word metadata.
- `autoshorts.audio.tts_plan` — side-effect-free TTS provider planning: EdgeTTS phase-1 baseline, Magpie A/B candidate, Whisper alignment-only.
- `autoshorts.audio.edge_tts_adapter` — explicit EdgeTTS MP3 generation boundary for final voiceover previews.
- `autoshorts.audio.final_preview` — ASS subtitle generation plus FFmpeg audio/caption MP4 rendering boundary.
- `autoshorts.audio.probe` — FFprobe duration helper used to align subtitle tracks to generated audio.
- `autoshorts.audio.voiceover` — beginner-friendly final English TrueTrace voiceover scripts and a single-source script-draft bridge for aligned visuals/captions.
- `autoshorts.ideas.candidate` — structured video candidate model and validation.
- `autoshorts.ideas.factory` — draft-to-candidate factory with stable ids, default hashtags, and duration classes.
- `autoshorts.ideas.testbatch` — testbatch validation and renderable-candidate filtering.
- `autoshorts.preview.package` — combines MP4 timing preview plus social draft review into an approval package.
- `autoshorts.review.approvals` — deterministic Telegram approval command parser.
- `autoshorts.strategy.brand` — TrueTraceShorts brand profile, default descriptions/bios/tags, and brand-fit validation.
- `autoshorts.strategy.score` — follower-conversion strategy scoring for hook, curiosity, identity, emotion, trust, follow reason, originality, and variety.
- `autoshorts.strategy.series` — public-safe series registry and hard no-go validation before public content advances.
- `autoshorts.rendering.final_video_plan` — final-near 1080x1920 production plans that keep AI visuals text-free and renderer-owned.
- `autoshorts.rendering.scene_backgrounds` — scene-specific ChatGPT Image/Codex background prompt plans that explicitly forbid readable text/logos and require renderer-owned overlays.
- `autoshorts.rendering.motion_renderer` — procedural motion preview renderer for inbox cards, warning routes, and three-path mechanism diagrams before heavier AI-video work.
- `autoshorts.rendering.ffmpeg_plan` — side-effect-free FFmpeg concat planning for local preview frames.
- `autoshorts.rendering.ffmpeg_renderer` — explicit FFmpeg boundary that writes concat files and MP4 timing previews.
- `autoshorts.rendering.local_frame_writer` — deterministic Pillow PNG scene-card writer for local preview plans.
- `autoshorts.rendering.local_preview` — side-effect-free local preview frame planning from render manifests.
- `autoshorts.rendering.manifest` — side-effect-free vertical render manifest generation from shot plans.
- `autoshorts.rendering.preview` — side-effect-free HTML timeline previews for render manifests.
- `autoshorts.rendering.shot_plan` — retention-led shot planner before render manifests or video generation.
- `autoshorts.review.package` — Telegram-friendly review package renderer for human approval.
- `autoshorts.social.delivery` — side-effect-free delivery preparation for social draft review messages.
- `autoshorts.social.final_approval` — final-video approval packages with media path, checksum, platform metadata, and Telegram-safe review copy.
- `autoshorts.social.draft` — approval-first social media draft model from candidate plus render preview.
- `autoshorts.social.manual_posting` — side-effect-free manual upload copy pack for phase-1 YouTube/TikTok metadata.
- `autoshorts.social.review` — Telegram-safe approval text renderer for social media drafts.
- `autoshorts.review.render` — renders complete review batches into Telegram-safe text.
- `autoshorts.review.workflow` — splits candidates into ready, blocked, and invalid review buckets.
- `autoshorts.telegram.review_sender` — validates Telegram review text and prepares side-effect-free delivery plans.
- `autoshorts.scripting.quality` — conservative pre-render quality gate.
- Tests for content briefs, content demo pipeline, content-to-candidate conversion, content pillars, candidate factory, idea candidates, script drafts, shot plans, testbatches, sample review CLI, sample Telegram delivery CLI, sample review demos, review workflow, review-batch rendering, approval parsing, review formatting, Telegram delivery preparation, and script quality gating.

## Brand profile

`autoshorts.strategy.brand.TRUETRACE_SHORTS_BRAND` captures the phase-1 public brand contract for `True Trace Shorts`:

- channel name and handles;
- tagline: `Systems over prompts.`;
- public YouTube description and TikTok bio;
- default hashtags and YouTube tags;
- tone and visual rules;
- forbidden public topics;
- generic AI-tips patterns;
- mechanism keywords for brand fit.

`validate_candidate_brand_fit()` rejects candidates that violate no-go topics, generic AI-tips positioning, or the mechanisms-over-hype promise. `apply_brand_metadata()` appends default hashtags and brand policy notes without changing the candidate content or performing side effects.

`autoshorts.demo.truetrace_concepts.build_truetrace_concept_batch()` provides the current five-candidate TrueTrace concept testbatch for strategy review:

- `Why Most AI Automations Break After Three Days`
- `This Prompt Looks Smart — But the Workflow Still Breaks`
- `The Hidden Reason Your AI Notes Become Useless`
- `Claim: AI Agents Will Replace Teams`
- `One Rule Before You Automate Anything With AI`

`render_truetrace_concept_summary()` renders those candidates with hooks, outlines, visuals, hypotheses, YouTube descriptions, TikTok captions, and tags. It performs no platform action and avoids action language.

`autoshorts.demo.truetrace_preview_packages.build_top_truetrace_preview_packages()` turns the top three concepts into local German approval timing previews and side-effect-free approval/manual-upload packages. It writes PNG scene cards and MP4 timing previews under the selected output directory, then prepares `ContentPreviewApprovalPackage` and `ManualPostingPack` artifacts for each candidate. Each preview artifact also now carries a deterministic English subtitle cue track and the phase-1 EdgeTTS provider plan, so audio/caption decisions travel with the candidate before any real TTS call happens.

Subtitle/TTS strategy is documented in `docs/subtitle_tts_strategy.md`: use deterministic Hormozi-inspired renderer-owned captions; final-motion videos use compact phrase-boundary subtitle cues; start TTS with EdgeTTS English baseline; A/B test NVIDIA Magpie later only after script/retention quality is proven.

The first public-facing audio/caption pilot now uses the accessible `weird email` framing: top card, scene captions, subtitles, and voiceover are derived from the final voiceover source instead of mixing old approval-card text with new spoken copy.

The first final-near motion prototype uses a hybrid model: ChatGPT Image/Codex can provide text-free background texture, while `autoshorts.rendering.motion_renderer` owns the actual inbox cards, arrows, labels, captions, and FFmpeg assembly. This keeps generated imagery useful without trusting it to spell or explain anything.

## Strategy scoring

`autoshorts.strategy.score.ContentStrategyScore` evaluates whether a candidate can move beyond generic AI tips and plausibly convert viewers into followers. It scores:

- hook;
- curiosity;
- identity;
- emotion;
- trust;
- follow reason;
- originality;
- variety.

`build_candidate_strategy_review()` returns a `CandidateStrategyReview` with `render_allowed`, reject reasons, and improvement suggestions. It blocks generic AI-slop language, weak future-value promises, forbidden public topics, and recent format repetition before render capacity is wasted.

`autoshorts.strategy.series.DEFAULT_CONTENT_SERIES` currently exposes only public-safe series:

- `Prompt vs System`
- `AI System Autopsy`
- `One Rule, One Example`
- `AI Hype Court`

`validate_candidate_series_fit()` rejects public content about JARVIS/Hermes, the user, their collaboration, private/behind-the-scenes material, politics, legal loopholes, private-data misuse, rule-bypassing, exploitation, or anything that could enable lawbreaking.

## Content development

`autoshorts.content.brief.create_content_brief()` turns a pillar, topic, audience problem, and payoff into a deterministic `ContentBrief`. The brief carries positioning, tone, visual rules, no-go topics, target platforms, and target duration before any script or renderer exists.

`validate_content_brief()` rejects missing strategy fields, unsupported platforms, and durations outside `10..180` seconds.

`autoshorts.content.script_draft.create_script_draft()` turns a `ContentBrief` into a structured `ScriptDraft` with:

- exact hook;
- script outline;
- 3–5 retention beats;
- visual concept;
- caption and CTA;
- estimated duration.

`validate_script_draft()` rejects missing core fields, invalid beat counts, invalid durations, and generic AI-slop phrases such as `in this video` or `unlock your full potential`.

`autoshorts.content.to_candidate.convert_script_draft_to_candidate_draft()` turns a validated `ContentBrief` + `ScriptDraft` pair into the existing `CandidateDraft` type. It preserves platform strategy, hook, script outline, visual concept, caption, CTA, no-go policy notes, and an initial conservative quality score.

`convert_script_draft_to_candidate()` then uses the existing candidate factory to create a validated `VideoCandidate`, including stable candidate id generation, default hashtags, duration classification, and pillar/platform validation.

`autoshorts.content.demo_pipeline.build_ai_life_systems_demo_delivery()` runs the deterministic demo path end-to-end:

```text
ContentBrief
→ ScriptDraft
→ VideoCandidate
→ TestBatch
→ ReviewBatch
→ Telegram ReviewDelivery
```

The result object exposes every intermediate artifact for inspection and still has no send/publish side effects.

## Render planning

`autoshorts.rendering.shot_plan.create_shot_plan()` turns a validated `ScriptDraft` into a deterministic five-scene retention plan:

```text
first_frame_hook
→ pattern_interrupt
→ core_explanation
→ screen_or_card_visual
→ cta
```

Each `ShotScene` carries timing, voiceover beat, visual action, asset mode, caption beat, retention goal, and whether labels/captions remain renderer-owned.

`validate_shot_plan()` rejects static slideshow asset modes, baked-in fake UI text, non-renderer-owned labels/captions, bad timing, missing fields, and plans whose first scene is not the first-frame hook.

`autoshorts.rendering.manifest.build_render_manifest()` turns a validated `ShotPlan` into a machine-readable `RenderManifest` with:

- vertical `1080x1920` render settings;
- `30` fps;
- one timeline item per shot scene;
- motion instructions inherited from the shot plan;
- deterministic placeholder asset paths;
- renderer-owned caption and label layers;
- `no_generated_text_inside_assets=True`;
- `static_card_limit=0`.

`validate_render_manifest()` rejects unsafe render settings, generated text inside assets, non-renderer-owned captions/labels, static slideshow timeline items, missing timeline fields, and bad timeline timing. The manifest is still a preparation artifact only; it renders nothing and calls no external API.

`autoshorts.rendering.preview.build_html_preview()` turns a validated `RenderManifest` into a side-effect-free `RenderPreview` HTML document. It exposes script metadata, vertical format, fps, every timeline item, placeholder asset paths, motion instructions, and renderer-owned caption/label text for local inspection before any media generation.

`validate_render_preview()` rejects blank previews, wrong preview types, missing HTML documents, side effects, and external renderer calls. Preview generation still does not write files, render videos, call ComfyUI, or touch Telegram.

Run the same deterministic preview locally with:

```bash
python -m autoshorts.cli.demo_render_preview
```

It prints preview metadata first, then the HTML document. Redirect stdout to a local `.html` file if you want to inspect it in a browser; the CLI itself still writes nothing.

`autoshorts.rendering.local_preview.build_local_preview_plan()` turns a validated `RenderManifest` into a deterministic `LocalPreviewPlan` for later frame/video generation. The default plan uses reduced local preview settings `540x960` at `24fps`, creates one `LocalPreviewFrame` per manifest timeline item, converts scene timing to milliseconds, and assigns deterministic placeholder image paths under `data/previews/<script_id>/`.

`validate_local_preview_plan()` rejects non-vertical preview sizes, non-positive fps, blank output paths, empty frame lists, missing frame fields, bad frame durations, non-zero first-frame start time, overlapping frames, side effects, and external tool calls. This is still a plan only: it writes no PNGs, calls no FFmpeg, and renders no MP4.

`autoshorts.rendering.local_frame_writer.write_local_preview_frames()` is the first explicit artifact-writing boundary. It consumes a validated `LocalPreviewPlan` and writes deterministic PNG scene cards using Pillow. Each card uses manifest-derived frame data: scene purpose, caption, label, timing, asset mode, and motion instruction. It returns `LocalFrameWriteResult` with `side_effects=("write_png",)` and `external_calls=()`.

Approval-preview cards default to German copy (`approval_language="de"`) so the concept is easier to review before final English production. Text wrapping is pixel-width based rather than fixed character-count based, which keeps long German lines inside the vertical card bounds.

Generated preview frames should stay under runtime preview directories such as `data/previews/<script_id>/` or temporary test directories. PNG media is ignored by Git.

`autoshorts.rendering.ffmpeg_plan.build_ffmpeg_concat_plan()` turns a `LocalPreviewPlan` plus `LocalFrameWriteResult` into a side-effect-free `FFmpegConcatPlan`. It records ordered PNG paths, per-frame durations, output `.mp4` path, derived `.concat.txt` path, preview dimensions, fps, and FFmpeg concat demuxer file content.

`validate_ffmpeg_concat_plan()` rejects mismatched or missing values, non-`.mp4` output paths, non-`.concat.txt` concat paths, non-positive dimensions/fps, missing entries, non-PNG frame paths, non-positive durations, side effects, and external tool calls. This layer still does not write the concat file and does not call FFmpeg.

`autoshorts.rendering.ffmpeg_renderer.render_ffmpeg_preview_video()` is the explicit local video-rendering boundary. It consumes a validated `FFmpegConcatPlan`, writes the `.concat.txt` file, calls `ffmpeg`, and writes the `.mp4` timing preview. It returns `FFmpegRenderResult` with `side_effects=("write_concat", "call_ffmpeg", "write_mp4")` and `external_calls=("ffmpeg",)`.

The renderer exports `yuv420p` MP4 with `+faststart`. Tests skip if `ffmpeg`/`ffprobe` are unavailable and otherwise smoke-probe width, height, frame rate, and approximate duration.

Run the deterministic local MP4 timing preview with:

```bash
python -m autoshorts.cli.demo_local_preview_video --out-dir data/previews/demo-local-preview
```

The command creates German approval-preview PNG scene cards under `frames/`, writes `preview.concat.txt`, renders `preview.mp4`, and prints script/output metadata. It performs no Telegram calls, no platform calls, and no AI/API calls. Final social-media videos can still be produced in English later; this preview layer is German for concept review.

## Content preview package

`autoshorts.preview.package.build_content_preview_approval_package()` combines an existing MP4 timing preview with the social media draft review text into a side-effect-free `ContentPreviewApprovalPackage`. It records approval language `de`, final video language `en`, approval commands, preview video path, and requires human approval.

`render_content_preview_approval_text()` creates a Telegram-safe text block that references the MP4 preview and embeds the social media draft review. The package layer does not send Telegram messages, publish to platforms, call renderers, or access credentials.

Research notes for external content-automation patterns are tracked in `docs/research/content_automation_research.md`. Growth strategy notes are tracked in `docs/research/content_growth_strategy_research.md`. TrueTraceShorts branding recommendations are tracked in `docs/branding_truetrace_strategy.md`. The operating business plan for a JARVIS-run, human-approved content machine is tracked in `docs/businessplan_jarvis_content_machine.md`. Together they emphasize series/queues, editable previews, versioned approval, originality gates, synthetic-content disclosure metadata, follower-conversion psychology, variety inside a stable promise, manual phase-1 uploads with prepared metadata, and avoiding blind auto-posting.

## Social media draft

`autoshorts.social.draft.build_social_media_draft()` turns a validated `VideoCandidate` plus `RenderPreview` into an approval-first `SocialMediaDraft` containing:

- candidate id;
- target platforms and human-readable platform labels;
- title variants;
- caption, hashtags, CTA, and hook;
- planned duration;
- quality/risk summary;
- preview reference and preview type;
- `requires_human_approval=True`;
- `side_effects=()`.

`validate_social_media_draft()` rejects unsupported platforms, blank required fields, missing titles/hashtags, invalid durations, missing human approval, and any side effects. This is the first platform-facing post draft, but still performs no upload, no Telegram call, no rendering, and no credential access.

`autoshorts.social.review.render_social_media_draft_review()` turns a valid `SocialMediaDraft` into a Telegram-safe approval message with candidate id, platforms, duration, hook, title variants, caption, hashtags, CTA, preview reference, quality/risk summary, explicit human-approval status, and approval commands:

- `Freigabe YouTube`
- `Freigabe TikTok`
- `Freigabe Instagram`
- `Freigabe alle`
- `Ablehnen`
- `Ändern: <requested change>`

The renderer avoids publish/post language and keeps approval semantics separate from any future platform action.

`autoshorts.social.delivery.prepare_social_draft_delivery()` wraps social draft review text in a side-effect-free `SocialDraftDelivery` object with delivery type `social_draft_review`, topic metadata, `requires_human_approval=True`, and `side_effects=()`. It validates non-empty text, Telegram's 4096-character limit, and the same no publish/post language boundary.

`autoshorts.social.manual_posting.build_manual_posting_pack()` converts an approved `SocialMediaDraft` plus final video path into a phase-1 manual upload pack. It contains platform-specific YouTube/TikTok/Instagram copy, descriptions/captions, hashtags, YouTube tags, and copy instructions. It performs no upload, no scheduling, no platform API calls, and returns `side_effects=()` / `external_calls=()`.

Preview the complete social draft delivery locally with:

```bash
python -m autoshorts.cli.demo_social_draft
```

It prints delivery metadata first, then the social draft review text. It still sends nothing and does not call platform APIs.

## Human approval commands

Supported review responses:

- `Freigabe alle` — approve for YouTube, TikTok, and Instagram.
- `Freigabe YouTube`
- `Freigabe TikTok`
- `Freigabe Instagram`
- `Ablehnen`
- `Ändern: <requested change>`

Ambiguous messages such as `passt schon` intentionally return `needs_clarification` and must not trigger posting.

## Quality gate

A script candidate only proceeds to rendering when:

- average of hook strength, novelty, clarity, and retention is at least `8.0`;
- AI-slop risk is not above `5`;
- policy risk is not `high`.

This keeps rendering capacity for candidates that might actually deserve to exist. A rare mercy.

## Review package

`autoshorts.review.package.render_telegram_review_package()` produces the human approval message for one candidate. It includes:

- candidate id, title, pillar, target platforms, and duration;
- hook, script summary, visual concept, caption, and hashtags;
- average quality score, AI-slop risk, policy notes, and render-gate status;
- optional preview path;
- only the relevant platform-specific approval commands.

A blocked quality gate is rendered as `Render gate: BLOCKED — nicht automatisch rendern`.

## Review workflow

`build_candidate_review_item()` classifies one candidate as:

- `ready_for_review` — valid and renderable; includes a review package;
- `blocked` — valid but blocked by quality gate; still includes a review package with blocked gate status;
- `invalid` — fails candidate validation; does not create a review package.

`build_review_batch()` processes a `TestBatch` into `ready_for_review`, `blocked`, and `invalid` buckets while preserving input order inside each bucket. Optional preview paths are attached by candidate id.

`render_review_batch_summary()` turns the complete `ReviewBatch` into one Telegram-safe text block with summary counts, full ready-for-review packages, and compact blocked/invalid reason lists. It deliberately avoids publish/post language; approval and publishing remain separate later stages.

## Sample review demo

`autoshorts.demo.sample_batch.build_sample_ai_life_systems_batch()` creates a deterministic AI-life-systems sample with:

- one ready candidate;
- one blocked candidate that fails the quality gate;
- one invalid candidate missing its hook.

`render_sample_review_batch()` builds that sample, runs it through the review workflow, and returns the Telegram-safe batch summary. This gives the later Telegram sender one boring, repeatable fixture to wire against.

Run the same fixture locally with:

```bash
python -m autoshorts.cli.demo_review_batch
```

## Telegram review delivery preparation

`autoshorts.telegram.review_sender.prepare_review_delivery()` wraps rendered review text in a side-effect-free `ReviewDelivery` object. It does not call Telegram. It validates that:

- review text is not blank;
- text fits Telegram's 4096-character message limit;
- review deliveries do not contain publish/post language;
- the delivery still requires human approval.

Actual Telegram I/O remains a later explicit boundary.

Preview the prepared delivery locally with:

```bash
python -m autoshorts.cli.demo_telegram_delivery
```

It prints delivery metadata first, then the review text. It still sends nothing.

## Idea candidates and testbatches

`VideoCandidate` is the structured unit that moves through the early pipeline. It carries:

- candidate id, pillar, title, target platforms, duration, and hypothesis;
- hook, script outline, visual concept, caption, CTA, and hashtags;
- quality score and policy notes.

`validate_candidate()` rejects missing strategic fields, unsupported platforms, and durations outside `10..180` seconds.

`TestBatch` groups candidates for one experiment. `validate_testbatch()` rejects empty batches and duplicate ids. `renderable_candidates()` returns only candidates that are both valid and allowed by the quality gate.

## Candidate factory

`CandidateDraft` represents a raw idea before it becomes a validated `VideoCandidate`.

`create_candidate()` turns a draft into a candidate by:

- generating a stable id from pillar, title, and duration;
- adding default pillar hashtags when no hashtags are supplied;
- classifying duration as `growth_short`, `monetization_candidate`, or `experiment`;
- appending the duration class to policy notes;
- enforcing candidate validation and pillar/platform fit validation.

Duration classes:

- `growth_short`: 20–45 seconds;
- `monetization_candidate`: 60–75 seconds;
- `experiment`: all other valid durations.

Missing hypothesis, unknown pillar, or unfit platform raises `ValueError`.

## Content pillars

`ContentPillar` keeps strategy separate from rendering. The default registry currently contains:

- `ai_life_systems` — AI as a servant for ordinary life systems, never as values or authority.

A pillar defines audience, positioning, tone, hook patterns, visual rules, no-go topics, platform fit, and monetization angle.

`validate_pillar_registry()` rejects duplicate pillar ids and incomplete pillar definitions. `validate_candidate_against_pillars()` rejects candidates with unknown pillars or platforms that are not configured for that pillar.

## Development

Run tests:

```bash
python -m pytest tests -q
```

Runtime dependencies currently include Pillow for deterministic local PNG preview frames. FFmpeg is used only by the explicit local preview renderer boundary and remains an external system prerequisite.

## Planned architecture

```text
autoshorts/
  config/       # niches, platforms, workflow settings
  ideas/        # idea generation and scoring
  scripting/    # script drafts, quality gates, retention checks
  rendering/    # local/AI-assisted preview rendering
  review/       # Telegram review package and approval parser
  publishing/   # platform-specific publishing metadata and later APIs
  analytics/    # performance imports and feedback loop
```

## Non-negotiables

- No credentials in git.
- No generated media in git unless explicitly intended.
- No automatic publishing without explicit approval.
- No public content about JARVIS/Hermes, the user, or their collaboration.
- No politics, legally sensitive/morally objectionable topics, rule-bypassing, private-data misuse, or lawbreaking content.
- Quality over speed; avoid generic AI-slop.
