← back to Codex Review 2026 04 30
AgentAbrams/review.md
36 lines
## Snapshot
- Public build-in-public media pipeline: Markdown devlogs → blog, podcast/audio, video, transcript, social copy, skills metadata.
- Stack: Python scripts, Bash, GitHub Actions, ffmpeg, Whisper CLI, ElevenLabs API, Google YouTube API; datastore: none.
- How it's run: manual `bin/aa`, plus GitHub Actions `workflow_dispatch`; no daemon observed.
- Status: stale; last dated content is `2026-02-24`.
## Top Risks (P0 — fix this week)
- `snippets/redact_lint.py:71-73`, `.github/workflows/ci.yml:34-40`: detected secrets are printed with surrounding snippet into CI logs. Fix by printing only pattern name + file/line, never matched content.
- `video/oauth_authorize.py:31-32`: refresh token is printed to stdout, making terminal logs/screen recordings a secret leak. Fix by writing only to a chmod-600 local file or clipboard prompt, not stdout.
- `video/upload_youtube.py:38`, `.github/workflows/youtube.yml:36-44`: uploads default to `privacy="public"` with no workflow privacy input; wrong artifact/path becomes public immediately. Default to `private`/`unlisted` and require explicit public promotion.
## Notable Issues (P1 — fix this month)
- `media/engine.py:67-69`, `media/engine.py:86-89`, `media/engine.py:103-104`: TTS/video/transcript failures are swallowed, then `BUILD COMPLETE` prints. Return a nonzero exit or summarize partial failure clearly.
- `media/engine.py:75-78`: `generate_chapters()` return value is never written; `media/output/chapters.json` promised by README is only created by `chapters.py` CLI. Write JSON in the engine path.
- `media/engine.py:28`: output path is relative to caller cwd, while imports are repo-root based. Running `aa` outside repo can write outputs into the wrong directory. Anchor outputs to `PROJECT_ROOT`.
- `README.md:47`, `media/md_to_blog.py:99-100`: docs reference ad hoc installs and `requirements.txt`, but no dependency manifest exists. Builds will drift across machines and CI.
- `podcast/rss_generator.py:42-47`: RSS enclosures omit `length`, `guid`, and escaped description content is hardcoded; many podcast clients behave poorly without stable GUIDs and enclosure lengths.
- `media/md_to_podcast.py:31-32`: truncates at 2000 characters mid-word/mid-section, causing malformed narration and possible loss of required safety context. Truncate by sentence/section budget.
- `media/social.py:21-32`: X post claims 280-char limit but never enforces it; long titles can generate invalid copy. Enforce length or fail loudly.
- `snippets/precommit.sh:30-35`: `.env` protection only checks staged files and only works inside a git repo; this checkout has no `.git`, so it reports pass. Fail closed or warn when git metadata is missing.
## Polish (P2 — when convenient)
- `media/cli.py:45-59`: `lint`, `validate`, and `check` do not use `check=True`; failed subprocesses may not propagate consistently through callers.
- `media/audio_mixer.py:15-16`, `media/video.py:19`: asset paths are cwd-relative. Use repo-root paths like the CLI.
- `video/tts_engine.py` and `podcast/tts_engine.py` duplicate ElevenLabs logic with different names/settings. Consolidate shared request/error handling.
- No tests observed for redaction patterns, chapter output, RSS generation, or build failure behavior.
## Strengths
- `.gitignore:1-7` correctly excludes common local secret files, OAuth client files, and pickles.
- GitHub Actions run redaction lint and skills validation on PR/push, so guardrails are at least wired into CI.
- Subprocess calls use argv arrays rather than shell interpolation in Python paths observed, reducing command injection risk.
## Open questions for the owner
- Is `youtube-upload` intended to publish directly, or should there be a human review/private-upload step?
- Is `media/output/` supposed to be committed/published somewhere, or always local artifact-only?
- Should this repo be a reusable public tool, or mainly Steve’s private operating pipeline with public examples?