# Behavior traces — harry0703/MoneyPrinterTurbo

> Canonical page: https://codevetter.com/unpack/moneyprinterturbo/behavior-traces

# Behavior traces — harry0703/MoneyPrinterTurbo

Scanned commit 3d5f4e421927d61f3eac729cf4b711ac0b69d688 (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Three flows were traced end-to-end. API startup goes main.py → asgi app construction → lifespan recovery. The primary action (video generation) is identical across frontends: a state record is created before scheduling, _run_pipeline walks preflight→script→terms→audio→subtitle→materials→video, and cross-posting is scheduled only after the task is COMPLETE. Persistence flows through two channels — task state (memory dict or Redis hashes) and task artifacts (atomic JSON writes into storage/tasks/<id>) — plus config.toml for settings.
- API startup trace: `python main.py` → uvicorn.run('app.asgi:app') → module-level get_application() builds routes/middleware/static mounts → parse_cors_allowed_origins(CORS_ALLOWED_ORIGINS) → lifespan logs startup, warns when app.api_key is empty, and calls task_service.recover_interrupted_cross_posts() to fail orphaned pending/processing cross-posts whose owner process no longer exists. — [main.py](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/main.py) [app/asgi.py#L21-47](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/asgi.py#L21-L47) [app/asgi.py#L255-288](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/asgi.py#L255-L288) [app/services/task.py#L1101-1147](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1101-L1147)
- First-run config trace: importing app.config.config → load_config() → if config.toml is a directory it is deleted, if missing it is copied from config.example.toml → _load_toml_config parses with a utf-8-sig BOM fallback → section dicts are wrapped in _SynchronizedConfig → ffmpeg_path (if set) is exported as IMAGEIO_FFMPEG_EXE for imageio/moviepy. — [app/config/config.py#L423-473](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/config/config.py#L423-L473) [app/config/config.py#L549-590](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/config/config.py#L549-L590)
- API video-generation trace: POST /api/v1/videos → verify_token dependency → create_task → utils.get_uuid() → sm.state.update_task(task_id) → task_manager.add_task(tm.start, ...) → TaskManager.execute_task spawns a thread running run_task → tm.start → _run_pipeline → on completion update_task(COMPLETE, progress=100, videos=...) → optional _schedule_cross_post. — [app/controllers/v1/video.py#L181-238](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/v1/video.py#L181-L238) [app/controllers/manager/base_manager.py#L54-96](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/manager/base_manager.py#L54-L96) [app/services/task.py#L1703-1740](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1703-L1740)
- Pipeline order inside _run_pipeline: (0) preflight — provider is_enabled() checks for seedance/ofox/metaso_minimax/muapi/openai_image, music-provider key+prompt-length+access validation, then utils.check_ffmpeg_ready() unless stop_at is script/terms; (1) generate_script → (2) generate_terms (skipped for local source) → save_script_data → (3) generate_audio → (4) generate_subtitle → (5) get_video_materials → (6) generate_final_videos → (7) mark COMPLETE + schedule cross-post. — [app/services/task.py#L1390-1700](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1390-L1700) [app/utils/utils.py#L189-235](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/utils/utils.py#L189-L235)
- stop-at truncation trace: each stage boundary checks stop_at and returns early with COMPLETE state — 'script' returns {script}, 'terms' returns {script,terms}, 'audio' returns {audio_file,audio_duration}, 'subtitle' returns {subtitle_path}, 'materials' returns {materials}; the API exposes this as the /subtitle and /audio endpoints and the CLI as --stop-at. — [app/services/task.py#L1512-1611](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1512-L1611) [app/controllers/v1/video.py#L188-199](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/v1/video.py#L188-L199) [cli.py#L360-364](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/cli.py#L360-L364)
- WebUI generation trace: Main.py button handler → _prepare_generation_task() → webui_task.submit_generation() writes state record before scheduling → InMemoryTaskManager(max_concurrent_tasks=1) → _run_generation attaches a thread-filtered loguru sink, acquires config.runtime_config_lock(), calls tm.start → a @st.fragment(run_every=0.5s) polls webui_task.get_task_logs() to stream logs to the page. — [app/services/webui_task.py#L19-29](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/webui_task.py#L19-L29) [app/services/webui_task.py#L53-195](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/webui_task.py#L53-L195) [webui/Main.py#L1932-2043](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/webui/Main.py#L1932-L2043) [webui/Main.py#L8181](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/webui/Main.py#L8181)
- CLI trace: `python cli.py ...` → _force_utf8_console() → run_cli() → parse_args() (custom argparse types validate colors, speeds, UUID task ids, subtitle enums) → params built by merging CLI flags over [ui] config defaults → tm.start(allow_server_file_input=True) → prints one JSON result object to stdout; batch mode merges each manifest object over CLI defaults and runs tasks sequentially. — [cli.py#L243-298](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/cli.py#L243-L298) [cli.py](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/cli.py)
- Failure trace: any unhandled exception inside _run_pipeline is caught in start(), logged, and converted by _mark_task_failed into state=-1 with failed_stage and error — visible via GET /tasks/{id}; the CLI maps a failed result to exit code 1, argument/manifest errors to exit code 2. — [app/services/task.py#L1720-1740](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1720-L1740) [app/services/task.py#L243-289](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L243-L289) [cli.py](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/cli.py)
- Task-deletion trace: DELETE /api/v1/tasks/{id} → sm.state.get_task → tm.is_task_busy refuses deletion while state==PROCESSING or cross_post_state in {pending,processing} (409) → shutil.rmtree(storage/tasks/<id>) → sm.state.delete_task. — [app/controllers/v1/video.py#L290-322](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/v1/video.py#L290-L322) [app/services/task.py#L106-123](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L106-L123)
- Cross-post recovery trace: each cross-post future is registered in _cross_post_futures keyed by task_id with owner 'hostname:pid:uuid' persisted in task state; on startup or deletion checks, _is_cross_post_owner_alive inspects the owner PID (Win32 OpenProcess on Windows, os.kill(pid,0) elsewhere, conservative-alive for foreign hosts) and stranded states are marked failed. — [app/services/task.py#L126-240](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L126-L240) [app/services/task.py#L1075-1147](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1075-L1147)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
