Files
narratio/docs/roadmap/remediation.md

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.