5.4 KiB
Transcription Checkpoint Review Remediation
Status: Complete.
Reviewed commits 7b0bf99 through 96b4e73 against the speaker-checkpoint and
upload-replay roadmap and the original user request. No production changes were
made during review. The two failures below were reproduced with temporary tests
using the existing stage fixtures; those temporary tests were removed afterward.
1. Reconcile Aggregate State Even When No Speaker Needs HTTP Work
Priority: P2. Status: Complete.
Implemented read-only aggregate identity/evidence checks before resume skips. Regression tests cover removed inputs, missing/duplicate/mismatched outputs, repair without HTTP requests, downstream invalidation, and exclusion of removed speakers from merge without deleting their files. Equivalent path forms and output ordering remain reusable. Focused app/stage tests and documentation checks pass.
Location: internal/stage/transcribe_resume.go:21 and the reconciliation result
consumed there.
ValidateResume returns reusable whenever reconciliation.work is empty. That
only establishes that the remaining speakers need no transcription; it does
not establish that the stored speaker collection and aggregate outputs match
the current input set. Removing a speaker while the remaining inputs are
unchanged produces an empty work list, so a succeeded record can be skipped
without pruning the removed speaker. Its old aggregate output can then remain
available to merge. Likewise, missing/inconsistent aggregate output references
are not repaired when all individual checkpoints remain valid. A prepare rerun
may already stale transcribe in some workflows, but the resume validator cannot
rely on that to satisfy its own current-input/output checks.
Reproduction: create complete alice/bob checkpoint records and aggregate
outputs with the existing fixture, mark the stage succeeded, remove bob from
the manifest's audio inputs, and call ValidateResume. It returns reusable
despite still retaining bob in the stored collection and aggregate outputs.
Required change:
- Distinguish no HTTP work from no reconciliation work. Validate that the committed speaker set and aggregate transcript references represent the reconciled current set, including relevant identity/evidence, before skipping.
- When only collection/output repair is needed, return non-resumable and let normal execution checkpoint the pruned collection and rebuild aggregate outputs without retranscribing reusable speakers. Preserve existing dependent invalidation; do not force otherwise-current speaker jobs.
- Keep resume inspection read-only. Do not fix this by deleting incidental transcript files or changing stage selection rules.
Verification: add removed-only input coverage (not just removal combined with an added speaker), plus incomplete/inconsistent aggregate output coverage. Exercise the runner skip path and assert zero additional WhisperX requests, correct rebuilt outputs, and no removed speaker reaching merge.
2. Remove the Unrequested Positive Audio-Size Requirement
Priority: P2. Status: Complete.
Audio evidence now permits zero size while still rejecting negative values. Regression tests verify zero-size manifest round trips, successful service results being checkpointed and reused, and service rejection being propagated without creating a completion record. Nonempty valid-JSON output validation is unchanged. Both new success regressions failed before the fix.
Location: internal/manifest/transcribe_state.go:95.
The new record validator requires AudioSize > 0. Previously Narratio accepted
a regular .flac file and delegated transcription acceptance to WhisperX;
neither the user request nor the roadmap introduced minimum audio size or a new
audio-content validation policy. Zero-byte content still has a valid checksum
and can be represented by the checkpoint mechanism. The current check runs
after a successful response and output materialization, causing the entire
stage to fail instead of retaining the completed work.
Reproduction: prepare one speaker, replace its prepared audio with an empty
regular file, and use the existing successful fake WhisperX client. Stage
execution fails at checkpoint validation with audio_size must be positive.
This demonstrates the extra Narratio restriction; it does not assert that a
particular production WhisperX deployment accepts empty audio.
Required change:
- Permit zero audio size and reject negative sizes. Keep byte hashing and size equality checks. Let the downstream service decide whether the input can be transcribed, as before.
- Do not remove the nonempty valid-JSON output requirement, which has a separate existing justification. Do not add a new early empty-audio rejection instead.
- Update any new tests/documentation that promote strictly positive input size to a contract.
Verification: cover a zero-size record round-trip and successful adapter result being checkpointed/reused for that input; retain negative-size rejection and ordinary downstream-failure tests.
Verification After Remediation
Completed on 2026-09-22 with Go 1.26.8: focused stage/application tests,
changed-package race tests, go test ./..., go test -race ./...,
go vet ./..., go build ./..., go test ./internal/doccheck,
go test ./internal/config -run '^TestExamplesLoadAndValidate$', and
git diff --check all passed. Existing replay and cancellation regression
tests remain intact; the HTTP adapter required no changes.