Repository navigation
Open
Labels
Description
From a full audit of the tree at 47a962a (3.5.0 + #452) on 2026-11-12. Each finding was checked against the code, reproduced where it can be run, and then checked again by a second reviewer who tried to refute it. Findings that were refuted, already decided in docs/design-decisions.md, or already filed are left out. The severity is the second reviewer's. The reproduction and suggested fix for each one are in the audit record (ask on this issue to have one posted). render.py's output-is-input guard (any project input) is fixed in #456.
42 findings: 2 high, 16 medium, 24 low. Tick a box and name the PR when a fix is merged.
- high
scripts/batch.py:309(A79): batch.py project recipes resolve every relative path in the project against the item's temporary work directory - high
scripts/batch.py:555(A275): batch.py --watch processes a source that is still being copied, reports the truncated output ok (verified for TS and every project recipe), and once the source settles refuses every later pass with output_exists, so the truncated deliverable is never replaced - medium
references/scripts.md:1084(A86): references/scripts.md says a pack's -o names the directory, but render.py writes the pack into the parent of -o - medium
scripts/batch.py:62(A80): batch.py's cache key for a project recipe ignores the files the project names, so an edited cue/music/brand file is served from the stale cache - medium
scripts/batch.py:208(A83): batch.py names a .webm source's final output .webm, which the re-encoding steps cannot write (the J: dry-run honesty, process handling, faststart and batch/render orchestration (audit round 2) #415 default-name rule is not applied) - medium
scripts/batch.py:505(A81): batch.py --watch computes recipe_key once, so a project.json edited during the watch is still served from the cache - medium
scripts/batch.py:634(A276): batch.py keys every item at the start of a pass, so a source that finishes copying while an earlier item is processing is processed in full but cached under its partial key, and every later --watch pass then fails the correct output with output_exists - medium
scripts/render.py:359(A85): A template pack (--template a,b / all) silently drops --stop-after, --cache, --from, --work, --keep, --export-timeline and --audit-log - medium
scripts/render.py:983(A96): An executed plan reports its output relative to the plan's cwd (after os.chdir), not to where the caller is - medium
scripts/render.py:1240(A77): render.py's default work directory is named by PID only and reused with exist_ok, so a later run with the same PID deletes an earlier run's kept preview and --keep intermediates - medium
scripts/render.py:1352(A93): A clip's own snap.to is never validated: a typo ("beat") or an unsupported grid silently renders the cut unsnapped - medium
scripts/render.py:1392(A92): An audiogram project with several clips cuts all of them and renders only the first, without a word - medium
scripts/render.py:1399(A91): audiogram.image is passed to waveform.py unresolved, so a relative image resolves against the cwd instead of the project file - medium
scripts/render.py:1638(A84): render.py without an export stage copies an MP4 intermediate to a .webm/.mkv output and reports it verified - medium
scripts/render.py:1640(A87): --stop-after export does not stop: the chapters and check stages still run, and the validation that treats check as unread lets a non-object check crash - medium
scripts/render.py:1652(A260): render.py writes chapter titles raw into its line-per-chapter chapters.txt: a newline adds a chapter (still verified), and other line breaks fail the render in its last stage - medium
scripts/sequence.py:125(A108): sequence.py --dir . (run from inside the frames folder) is a traceback without -o - medium
templates/audiogram.json:10(A89): --template audiogram without --image silently drops the audiogram stage: the dry run completes and the real run fails at export with "input has no video stream" - low
examples/brand.json:24(A107): examples/brand.json carries a loudness block that no tool reads - low
examples/make_demo.sh:3(A106): The demo pipeline claims to run every script, but it runs 13 of the 42 - low
examples/make_demo.sh:55(A105): examples/make_demo.sh cannot be re-run: no tool call carries --overwrite and set -e aborts on the first existing output - low
references/scripts.md:975(A103): references/scripts.md misstates render's normalize default and says --codec is forwarded and keyed - low
scripts/_common/timeline.py:337(A266): EDL source timecodes run past 24:00:00:00 for a source whose start timecode is near midnight - low
scripts/_common/timeline.py:382(A265): EDL event numbers overflow the CMX 3600 three-digit field at 1000 events - low
scripts/_common/timeline.py:401(A261): timeline.to_edl writes caller strings raw into CMX 3600 lines: a newline in a chapter title, file name or output name adds lines or events, and parse_error() accepts the file - low
scripts/batch.py:53(A277): file_key, documented as a content hash, misses a same-size, same-second rewrite outside the first and last MiB, so batch serves an old output as cached and render.py --cache serves an old stage artifact - low
scripts/batch.py:442(A104): batch.py ignores unknown recipe keys: a misspelled output_dir/suffix/glob silently uses the default - low
scripts/batch.py:555(A82): batch.py's glob is case-sensitive, so camera files (GOPR0001.MP4) under the documented "*.mp4" glob complete as an empty batch with no note - low
scripts/render.py:407(A263): render.py --template a,b pack table writes file names raw into a Markdown row: a ' | ' in the input name shifts every column, and report.py --pack marks passing destinations as failed - low
scripts/render.py:681(A101): INTERMEDIATE is never reset in main(), so a second render in the same process encodes its delivery stages at superfast - low
scripts/render.py:1049(A267): --export-timeline runs ffprobe once per clip even when every clip is the same file - low
scripts/render.py:1073(A264): A lone surrogate in a project string (a JSON \ud83d escape) is a UnicodeEncodeError traceback with empty stdout, a 0-byte timeline (an --overwrite target truncated), or a failure after a whole render - low
scripts/render.py:1157(A102): render.py --init and --list-templates print plain text on stdout under --json - low
scripts/render.py:1240(A98): Re-running render.py with the same --work refuses the stage files the previous run left there - low
scripts/render.py:1261(A88): Sections that validate_project skips under --stop-after are still read before their stage, so a non-object export/check is a traceback - low
scripts/render.py:1377(A97): Under --dry-run a clip's speed stage is planned from an invented 10 s duration, and nothing says the number is a placeholder - low
scripts/render.py:1536(A95): Project text values beginning with '-' ("-30%") break the stage's argparse, because render passes them as a separate token - low
scripts/render.py:1653(A99): A dry run with --work or --keep creates the work directory and writes chapters.txt into it - low
scripts/render.py:1653(A100): With --cache, the chapters stage of an inline chapters list never hits, because chapters.txt is rewritten each run and its mtime is in the key - low
scripts/render.py:1655(A94): A chapters value that is neither a list nor a path string is not validated before the first stage, contrary to the reference - low
scripts/sequence.py:116(A109): sequence.py accepts --width/--height of 0 or below and silently renders at the source size - low
templates/audiogram.json:1(A90): The audiogram template ignores --brand and --title although the audiogram stage and its captions take both
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsTodo
Activity