|
|
@@ -27,26 +27,29 @@
|
|
|
|
|
|
**Interfaces:** Preserve manifest fields `id`, `text`, `wav`, `duration`, `synthesis`. Normalize scene text for identity using `" ".join(text.split())`, without dropping Unicode or punctuation. Resolve each manifest WAV relative to the narration directory. Transcript comparison is a separate, tolerant operation. Existing movie scenes retain their own source audio and omit narration offsets.
|
|
|
|
|
|
-- [ ] Add failing tests before code: accepted two-scene render, forced rejection of first scene, exception in second, normal retry never reuses rejected bytes; strict unavailable verification withdraws acceptance; unchanged accepted settings still cache. Inject failures in synthesis and duration and assert published entries cannot point at rejected replacements. Preserve failed bytes as evidence.
|
|
|
-- [ ] Publish manifest atomically (`temporary.write_text(..., encoding="utf-8"); temporary.replace(manifest_path)`) and withdraw acceptance before overwriting any referenced WAV. Publish each accepted scene only after transcript/ASR gates and duration succeed. Preserve the existing bounded attempts and no-narration CLI behavior. Do not silently create a fallback acceptance record.
|
|
|
-- [ ] Add unsupported-comparison tests for unrelated Chinese/Japanese (including short and mixed-script text), symbols-only scripts, multiline text, accented Latin, and spaced Cyrillic. Use Unicode casefold/normalization and whitespace-preserving tokenization. Explicitly detect scripts requiring segmentation; do not infer support from average word length or introduce CJK character thresholds. Unsupported comparisons report unavailable/nonzero under `--drift-check` and `--verify on`; `auto` warns/allows unavailable ASR, `off` bypasses ASR. The mandatory chat transcript gate never accepts unsupported comparison. Preserve supported-word thresholds and empty/missing speech rejection.
|
|
|
-- [ ] Preflight required ffprobe before synthesis, with a meaningful missing-tool test. Keep existing mocked tests portable by mocking this boundary.
|
|
|
-- [ ] Add safe assembly tests: removed narration ignores leftover WAV and creates no offset; required narration with missing manifest/entry/WAV or changed text fails before encoding; accepted referenced WAV is selected even when named differently; movie scenes retain own audio and no narration offset. Validate all narration requirements before encoding the first segment. Update existing media fixture declarations/manifests to reflect the contract without running those media suites.
|
|
|
-- [ ] Correct movie segment inputs: probe audio-stream presence, supply anullsrc only for silent source movies, explicitly map selected source video/audio, and fit both width and requested inner height before padding. Test input selection and computed geometry with mocked probes/encoder, including 2560x1080 into 1920x1080. No real encoding.
|
|
|
-- [ ] Correct percent-bearing sequence paths in assembly and checker: escape only literal directory percent signs (or use controlled cwd plus fixed basename), retaining the intended `%08d`/numbering placeholder. Test the path helper/selected input-output target with byte sentinels; never sample media.
|
|
|
-- [ ] Run safe narration and new assembly/path contract tests; retain existing cache/drift regressions. Self-review and commit.
|
|
|
+- [x] Add failing tests before code: accepted two-scene render, forced rejection of first scene, exception in second, normal retry never reuses rejected bytes; strict unavailable verification withdraws acceptance; unchanged accepted settings still cache. Inject failures in synthesis and duration and assert published entries cannot point at rejected replacements. Preserve failed bytes as evidence.
|
|
|
+- [x] Publish manifest atomically (`temporary.write_text(..., encoding="utf-8"); temporary.replace(manifest_path)`) and withdraw acceptance before overwriting any referenced WAV. Publish each accepted scene only after transcript/ASR gates and duration succeed. Preserve the existing bounded attempts and no-narration CLI behavior. Do not silently create a fallback acceptance record.
|
|
|
+- [x] Add unsupported-comparison tests for unrelated Chinese/Japanese (including short and mixed-script text), symbols-only scripts, multiline text, accented Latin, and spaced Cyrillic. Use Unicode casefold/normalization and whitespace-preserving tokenization. Explicitly detect scripts requiring segmentation; do not infer support from average word length or introduce CJK character thresholds. Unsupported comparisons report unavailable/nonzero under `--drift-check` and `--verify on`; `auto` warns/allows unavailable ASR, `off` bypasses ASR. The mandatory chat transcript gate never accepts unsupported comparison, including existing cached chat clips under off/auto. Preserve supported-word thresholds and empty/missing speech rejection.
|
|
|
+- [x] Preflight required ffprobe before synthesis, with a meaningful missing-tool test. Keep existing mocked tests portable by mocking this boundary.
|
|
|
+- [x] Add safe assembly tests: removed narration ignores leftover WAV and creates no offset; required narration with missing manifest/entry/WAV or changed text fails before encoding; accepted referenced WAV is selected even when named differently; movie scenes retain own audio and no narration offset. Validate all narration requirements before encoding the first segment. Update existing media fixture declarations/manifests to reflect the contract without running those media suites.
|
|
|
+- [x] Correct movie segment inputs: probe audio-stream presence, supply anullsrc only for silent source movies, explicitly map selected source video/audio, and fit both width and requested inner height before padding. Test input selection and computed geometry with mocked probes/encoder, including 2560x1080 into 1920x1080. No real encoding.
|
|
|
+- [x] Correct percent-bearing sequence paths in assembly and checker: escape only literal directory percent signs (or use controlled cwd plus fixed basename), retaining the intended `%08d`/numbering placeholder. Test the path helper/selected input-output target with byte sentinels; never sample media.
|
|
|
+- [x] Run safe narration and new assembly/path contract tests; retain existing cache/drift regressions. Self-review and commit.
|
|
|
|
|
|
### Task 2: Keep every subtitle inside its scene and select the supplied track
|
|
|
|
|
|
-**Files:** `skills/proving-it-works-with-a-movie/scripts/make-subtitles`, `scripts/burn-subtitles`; `tests/proving-it-works-with-a-movie/test_subtitles.py` or a separate safe subtitle contract module.
|
|
|
+**Files:** `skills/proving-it-works-with-a-movie/scripts/make-subtitles`, `scripts/burn-subtitles`, `scripts/check-movie` (SRT text parser only); `tests/proving-it-works-with-a-movie/test_subtitles.py` or a separate safe subtitle contract module, safe checker policy/parser regressions, and `run-tests.py`.
|
|
|
|
|
|
**Interfaces:** Manifest schema stays unchanged. Assembly offsets select membership and start times; manual offsets retime selected scenes without reintroducing omitted scenes. Task 1 makes assembly offsets refer only to accepted narration.
|
|
|
|
|
|
-- [ ] Add failing timing tests by parsing emitted SRT: five chunks in 0.5 seconds followed immediately by another scene; one chunk in 12 seconds; mixed-length chunks; submillisecond/invalid duration handling; empty cut; nonzero manual offsets. Assert every word survives, ordered positive millisecond cue intervals stay within the measured scene, the final cue covers the narration end within rounding, and reported end agrees with emitted cues.
|
|
|
-- [ ] Allocate proportional durations over the entire scene. Readability limits can guide splitting/allocation but cannot overflow or truncate the measured interval. Coalesce chunks if there are fewer representable milliseconds than chunks; reject unrepresentable/nonpositive durations clearly rather than emit invalid cues. Remove the serialization fallback that extends collapsed cues by one second.
|
|
|
-- [ ] Preserve assembly membership selection and partial manual offsets. Validate offsets keys that have no manifest entry with a named nonzero error; do not reject manifest entries omitted from the assembled cut. Add a failing mismatch regression before this change.
|
|
|
-- [ ] Add safe replacement-track tests for explicit soft mode and hard-burn fallback by inspecting selected stream maps, including an input already containing subtitles and a video without audio. Explicitly select `0:v:0`, optional source audio, and `1:s:0` from the supplied SRT. Preserve truthful fallback diagnostics.
|
|
|
-- [ ] Run only safe subtitle classes (existing offset/path tests and BOM/fallback cases plus new contract tests). Self-review and commit.
|
|
|
+- [x] Add failing timing tests by parsing emitted SRT: five chunks in 0.5 seconds followed immediately by another scene; one chunk in 12 seconds; mixed-length chunks; submillisecond/invalid duration handling; empty cut; nonzero manual offsets. Assert every word survives, ordered positive millisecond cue intervals stay within the measured scene, the final cue covers the narration end within rounding, and reported end agrees with emitted cues.
|
|
|
+- [x] Allocate proportional durations over the entire scene. Readability limits can guide splitting/allocation but cannot overflow or truncate the measured interval. Coalesce chunks if there are fewer representable milliseconds than chunks; reject unrepresentable/nonpositive durations clearly rather than emit invalid cues. Remove the serialization fallback that extends collapsed cues by one second.
|
|
|
+- [x] Preserve assembly membership selection as the manifest/offset intersection, including unknown offset keys producing no cues, and partial manual offsets. Enforce accepted membership in Task 1's assembly handoff tests rather than changing this existing subtitle CLI contract.
|
|
|
+- [x] Add one safe producer/consumer regression that invokes narrate, assemble, and make-subtitles sequentially using their real files and mocked synthesis/probing/encoding. Remove an opening scene's narration on rerun: its old WAV survives as evidence, assembly omits that audio/offset, and the remaining scene's caption starts at its measured assembly offset. Assert emitted manifest/offset/SRT data and chosen inputs, not full commands.
|
|
|
+- [x] Add safe replacement-track tests for explicit soft mode and hard-burn fallback by inspecting selected stream maps, including an input already containing subtitles and a video without audio. Explicitly select `0:v:0`, optional source audio, and `1:s:0` from the supplied SRT. Preserve truthful fallback diagnostics.
|
|
|
+- [x] Repair `subtitle_end` to read cue timing lines rather than any caption text containing an arrow. Root reproduced a valid cue with `Follow source --> destination.` raising ValueError. Add text-only parser tests for literal arrows, fake timestamps in caption text, actual malformed cue timing, empty subtitles, and multiple cues; keep the checker's existing last-cue policy unchanged.
|
|
|
+- [x] Register a `contracts` test-runner suite for `test_*contract*.py`, so the new safe regression files run through the normal entrypoint and are included in `all`. Keep only mocked/text-based tests in those modules. Verify by executing `--suite contracts`, never `--suite all` in this pass.
|
|
|
+- [x] Run only safe subtitle classes (existing offset/path tests and BOM/fallback cases plus new contract tests). Self-review and commit.
|
|
|
|
|
|
### Task 3: Own recorder resources from acquisition through shutdown
|
|
|
|
|
|
@@ -54,27 +57,39 @@
|
|
|
|
|
|
**Interfaces:** Preserve `serve/run/key/watch/close`, prompt markers, session files, exit 1 on failure and exit 2 only for a live unfinished command, 5 fps timing, and 1600x900 viewport. Preserve logs; only remove the recorder's own profile and readiness state.
|
|
|
|
|
|
-- [ ] Add startup-failure tests with fake Popen handles and no processes: first/second log open, ttyd launch, browser launch, session metadata write, terminal log open, later connection failure. Verify each acquired process is cleaned, handles close, failed startup cannot remain ready, and profile cleanup is owned. Register resources immediately under an encompassing try/finally (or ExitStack); no general process framework.
|
|
|
-- [ ] Resolve session directory before child arguments, cwd, and profile construction. Test a relative path against the actual child argv/cwd relationship using fake processes.
|
|
|
-- [ ] Retire PID metadata after serve cleanup and remove stale ready state; test repeated close after cleanup kills nothing and retains logs. Make profile-removal failure truthful. Avoid creating a new cross-platform PID-identity protocol.
|
|
|
-- [ ] Add no-record observation tests for connection/session loss using fake CDP and log text. Poll connection/liveness while waiting; a dead session is failure, never `running`. A live timed-out command still returns 2. Do not consume prompt status incorrectly or lose completed native exit status.
|
|
|
-- [ ] Test timing using a fake clock, capture callback returning byte tokens, and mocked writes: a final capture crossing a one-second endpoint must fill exactly the bounded 5 fps slots; also cover hold endpoint, normal completion and mid-capture stalls. No real image/frame inspection or integration tests.
|
|
|
-- [ ] Fix ST-terminated OSC stripping and test both BEL/ST markers in actual visible-text parsing. Emit ASCII-escaped stdout JSON (or explicit UTF-8) and test a CP1252 stream with René and λ; keep UTF-8 JSON files.
|
|
|
-- [ ] Register real-session test cleanup immediately after Popen so failed setUp cannot leak it; do not run SessionTests in this pass. Run safe prompt, serve-argument, and new recorder contract tests; self-review and commit.
|
|
|
+- [x] Add startup-failure tests with fake Popen handles and no processes: first/second log open, ttyd launch, browser launch, session metadata write, terminal log open, later connection failure. Verify each acquired process is cleaned, handles close, failed startup cannot remain ready, and profile cleanup is owned. Register resources immediately under an encompassing try/finally (or ExitStack); no general process framework.
|
|
|
+- [x] Resolve session directory before child arguments, cwd, and profile construction. Test a relative path against the actual child argv/cwd relationship using fake processes.
|
|
|
+- [x] Make serve the cleanup owner: close writes the existing stop request and waits with one overall 30-second deadline for completed cleanup, instead of killing historical numeric PIDs. Honor stop requests inside startup pump/retry loops too. Retire PID metadata atomically only after confirmed process and profile cleanup and remove stale ready state; test repeated close after cleanup kills nothing and retains logs. A wait timeout, unreadable/missing metadata, unavailable serve, or failed profile removal is not successful cleanup and returns nonzero. The deadline accommodates an active bounded CDP call, both five-second child waits, and profile release. Avoid creating a new cross-platform PID-identity protocol.
|
|
|
+- [x] Add no-record observation tests for connection/session loss using fake CDP and log text. Poll connection/liveness while waiting; a dead session is failure, never `running`. A live timed-out command still returns 2. Do not consume prompt status incorrectly or lose completed native exit status.
|
|
|
+- [x] Test timing using a fake clock, capture callback returning byte tokens, and mocked writes: a final capture crossing a one-second endpoint must fill exactly the bounded 5 fps slots; also cover hold endpoint, normal completion and mid-capture stalls. No real image/frame inspection or integration tests.
|
|
|
+- [x] Fix ST-terminated OSC stripping and test both BEL/ST markers in actual visible-text parsing. Emit ASCII-escaped stdout JSON (or explicit UTF-8) and test a CP1252 stream with René and λ; keep UTF-8 JSON files.
|
|
|
+- [x] Register real-session test cleanup immediately after Popen so failed setUp cannot leak it; do not run SessionTests in this pass. Retain the tests' real owned-process assertions when shutdown clears PID metadata: snapshot owned IDs for assertions while the session is live rather than iterating an empty completed list. Run safe prompt, serve-argument, and new recorder contract tests; self-review and commit.
|
|
|
|
|
|
### Task 4: Make shipped recipes preserve failures and measured timing
|
|
|
|
|
|
-**Files:** `skills/proving-it-works-with-a-movie/SKILL.md`, `assembling.md`, `rendering-from-a-log.md`, `recording-motion.md`, `recording-a-terminal.md`, `narrating.md`; focused documentation test evidence under ignored review/SDD directories.
|
|
|
+**Files:** `skills/proving-it-works-with-a-movie/SKILL.md`, `assembling.md`, `rendering-from-a-log.md`, `recording-motion.md`, `recording-a-terminal.md`, `narrating.md`, `tests/proving-it-works-with-a-movie/README.md`; focused documentation test evidence under ignored review/SDD directories.
|
|
|
|
|
|
**Interfaces:** Documentation describes Tasks 1-3's existing formats and corrected behavior. Existing evidence standards and Windows shell recipes remain intact. This is a focused reference correction, not a broad skill-policy rewrite.
|
|
|
|
|
|
-- [ ] Use writing-skills. Preserve the before-change fresh-reader reference trial and execute the original recipes with fake producer commands and log fixtures to record failures. No real media or OS recording.
|
|
|
-- [ ] Put `set -euo pipefail` in the primary Unix pipeline's executing Bash scope, retaining all five commands and offsets. In the assembling subtitle example pass `--offsets-json segments/offsets.json` and stop if subtitle production fails. Explain current scene plus accepted manifest, relative WAV reference, and movie own-audio behavior in one paragraph.
|
|
|
-- [ ] Put the producer-to-tee logging pipeline under the shell that owns pipefail, preserving the real producer exit status and printed STARTED/FINISHED/EXIT_STATUS markers. Execute the recipe with failing and passing fake producers; assert shell status and log content without matching a large rendered command.
|
|
|
-- [ ] Restore the cursor transform on mouseup. Execute the documented JavaScript with a minimal fake DOM/event dispatcher and assert repeated press/release state changes; no browser or pixels.
|
|
|
-- [ ] State that session directories, like take directories, must be new or empty on retries. Document unsupported transcript verification and existing retry behavior accurately without adding a user approval gate.
|
|
|
+- [x] Use writing-skills. Preserve the before-change fresh-reader reference trial and execute the original recipes with fake producer commands and log fixtures to record failures. No real media or OS recording.
|
|
|
+- [x] Put `set -euo pipefail` in the primary Unix pipeline's executing Bash scope, retaining all five commands and offsets. In the assembling subtitle example pass `--offsets-json segments/offsets.json` and stop if subtitle production fails. Explain current scene plus accepted manifest, relative WAV reference, and movie own-audio behavior in one paragraph.
|
|
|
+- [x] Put the producer-to-tee logging pipeline under the shell that owns pipefail, preserving the real producer exit status and printed STARTED/FINISHED/EXIT_STATUS markers. Execute the recipe with failing and passing fake producers; assert shell status and log content without matching a large rendered command.
|
|
|
+- [x] Restore the cursor transform on mouseup. Execute the documented JavaScript with a minimal fake DOM/event dispatcher and assert repeated press/release state changes; no browser or pixels.
|
|
|
+- [x] State that session directories, like take directories, must be new or empty on retries. Explain that close requests cleanup from serve, waits up to 30 seconds, and reports failure when the owner is unavailable or cleanup fails; hard-killing serve can leave its children and stale readiness, so these signals cannot establish a live owner. Document unsupported transcript verification and existing retry behavior accurately without adding a user approval gate.
|
|
|
+- [x] Document the new `--suite contracts` entrypoint as safe mocked/text checks, distinct from existing media/session suites and live acceptance.
|
|
|
- [ ] Fresh-reader candidate trials use the same bounded scenarios as baseline, then execute supplied commands with fake boundaries. Preserve both failures and successes; do not call this full skill evaluation. Self-review and commit documentation plus concise results in this plan.
|
|
|
|
|
|
+Task 4 executable snippet result: the preserved baseline returned success after
|
|
|
+an assembly failure and a failed logged producer, emitted subtitles at zero
|
|
|
+instead of the measured two-second offset, and left the cursor pressed after
|
|
|
+mouseup. After the focused guide edits, the fake-boundary harness preserves
|
|
|
+assembly exit 41 and logger exit 23, stops later producers, retains prior
|
|
|
+outputs, runs all five stages on success, emits the subtitle interval at
|
|
|
+`00:00:02,000`, and restores the cursor on two releases. The safe `contracts`
|
|
|
+entrypoint passes 66 tests. Independent fresh-reader candidate trials remain
|
|
|
+pending after the documentation commit; these snippet checks are not full skill
|
|
|
+evaluation or live movie acceptance.
|
|
|
+
|
|
|
## Final verification and review
|
|
|
|
|
|
Run the safe accumulated contract selection once after all code changes. Have an independent reviewer read the full accumulated PR from `fd02874aa5c55ba3c2bca431253b48e0e4c8be5a` through the final head, including docs/spec and tests, and resolve concrete remaining findings. Push only to Ada's `import/proving-it-works-skill` branch after passing review, verify #2214's remote head, and reply to the four current external threads with exact evidence. Do not merge. Drew's viewing remains final acceptance.
|