Document resumable transcription and replay

This commit is contained in:
2026-09-22 00:31:32 +00:00
parent 6e6054f744
commit 96b4e73f53
8 changed files with 299 additions and 43 deletions

View File

@@ -50,6 +50,43 @@ The model admits these stage states:
- `stale`
- `interrupted`
### Transcribe-owned speaker state
A `transcribe` stage record may carry `transcribe_state_version: 1` and a
`transcribe_speakers` map keyed by the existing derived speaker ID. The version
is the authority marker: a versioned empty map means that no earlier speaker
completion is reusable. Absence of both fields is accepted as legacy
aggregate-only state so current Narratio can read older manifests.
Each map entry represents one completed speaker only. It binds a versioned
fingerprint to the session-relative audio path, audio SHA-256 and size, one
canonical `transcript_raw` output with its path, SHA-256 and size, and the
producer run ID. Paths must be canonical and session-relative, checksums must
be lowercase SHA-256 values, and the record and output producer identities
must agree. Other stages cannot carry this transcribe-owned state.
Transcribe reconciles this collection against the current prepared audio set
and observable WhisperX semantics. Missing or corrupt regular outputs become
work; unsafe or non-regular evidence is rejected. It saves the reconciled
collection before HTTP dispatch and saves a detached candidate after each
validated completion. Only after a save succeeds is the candidate installed as
live authority. Canonical bytes produced before an unsuccessful save are not a
completion record.
Aggregate transcribe status still describes the whole invocation. A failed,
running, stale, or interrupted aggregate may therefore retain reusable speaker
records, while aggregate outputs are declared only after the current
collection is complete. Ordinary retry reconciles and reuses those records.
Force first checkpoints an empty current collection, preventing later retries
from reviving pre-force results.
Older aggregate-only transcribe success is conservatively regenerated once
when transcribe is selected because it does not bind individual outputs to the
audio bytes used. The session-manifest schema identifier remains
`narratio.session-manifest.v1`; this additive state is accepted by current
Narratio, but older strict-decoding binaries may reject manifests after these
fields have been written.
### Analyze-owned artifact state
Every `analyze` stage record carries `analyze_state_version: 1` and an
@@ -156,10 +193,10 @@ establish a current immutable snapshot.
Manifest replacement provides atomic visibility, not a crash- or power-loss
durability guarantee. Callers reload after a returned save error before retrying.
An analyze checkpoint error leaves the prior manifest as per-artifact authority.
The runner then attempts to persist the bounded failed/stale retry collection;
if that terminal save also fails, its error is joined with the originating
failure and the next invocation must reconcile from the last readable manifest.
A transcribe or analyze checkpoint error leaves the prior manifest collection
as authority. The runner then attempts to persist the aggregate failure; if
that terminal save also fails, its error is joined with the originating failure
and the next invocation must reconcile from the last readable manifest.
## Execution Semantics
@@ -193,11 +230,11 @@ only fields returned by the new result. Marking a record stale does not clear
those details because resume validation and diagnosis may still require them
before execution begins.
Aggregate lifecycle clearing deliberately preserves the analyze-owned
per-artifact collection. This lets later reconciliation replace only evaluated
entries without erasing unrelated current results. Other stages retain their
existing aggregate-only lifecycle behavior and are forbidden from carrying the
analyze-specific fields.
Aggregate lifecycle clearing deliberately preserves both the transcribe-owned
speaker collection and the analyze-owned per-artifact collection. This lets
later reconciliation replace only non-current entries without erasing durable
completions. Other stages retain aggregate-only lifecycle behavior and are
forbidden from carrying either collection.
A stage may explicitly return a skipped disposition and stable reason. The
runner persists that outcome in the session manifest, clears older outputs,
@@ -228,7 +265,7 @@ evidence and focused durable validators:
| Work | Reuse authority | Focused owners |
| --- | --- | --- |
| prepare | aggregate semantic fingerprint | [prepare](stage-prepare.md) |
| transcribe | aggregate semantic fingerprint | [transcribe](stage-transcribe.md), [WhisperX](../integrations/whisperx.md) |
| transcribe speakers | aggregate semantic fingerprint plus per-speaker input/output reconciliation | [transcribe](stage-transcribe.md), [WhisperX](../integrations/whisperx.md) |
| merge | aggregate semantic fingerprint | [merge](stage-merge.md), [Seriatim](../integrations/seriatim.md) |
| polish | aggregate semantic fingerprint | [polish](stage-polish.md), [Audita](../integrations/audita.md) |
| normalize | aggregate semantic fingerprint | [normalize](stage-normalize.md), [Seriatim](../integrations/seriatim.md) |
@@ -310,6 +347,7 @@ where the last session transition can require operator interpretation.
- Remote commit model and readers: `internal/artifacts/remote_commit.go`,
`internal/artifacts/current_state_commit.go`,
- Persistence and validation: `internal/manifest/store.go`
- Transcribe speaker state: `internal/manifest/transcribe_state.go`
- Package tests: `internal/manifest/*_test.go`
- Assembled execution behavior: `internal/app/runner_test.go`,
`internal/app/run_stage_test.go`