Refactor recording metadata to JSON sidecar
Replaces the `.transcript.txt` sidecar with a structured `.json` file for recording metadata. This change consolidates transcript text, duration, and other potential metadata into a single, extensible JSON object. This also refactors the `TranscriptState` enum to better represent the on-disk state (absence of file means pending) and the in-memory representation. The `Transcript` enum now specifically models the terminal outcomes of the transcriber (`Silent` or `Content`). The commit includes updates to documentation, data structures, path handling, and various tests to align with the new metadata format.
This commit is contained in:
@@ -236,7 +236,14 @@ async fn recovery_enqueues_only_pending_recordings() {
|
||||
std::fs::create_dir_all(&case_a).unwrap();
|
||||
std::fs::write(case_a.join("2026-04-10T10-00-00Z.m4a"), b"x").unwrap();
|
||||
std::fs::write(case_a.join("2026-04-11T10-00-00Z.m4a"), b"x").unwrap();
|
||||
std::fs::write(case_a.join("2026-04-11T10-00-00Z.transcript.txt"), b"done").unwrap();
|
||||
common::seed_recording_meta(
|
||||
&case_a,
|
||||
"2026-04-11T10-00-00Z",
|
||||
common::Transcript::Content {
|
||||
text: "done".into(),
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
// User 2, case with one pending .m4a.
|
||||
let case_b = root.join("dr_b/bbbb");
|
||||
@@ -380,14 +387,14 @@ async fn worker_leaves_m4a_intact_on_transient_whisper_error() {
|
||||
"transient error must not mark {} as failed",
|
||||
failed.display()
|
||||
);
|
||||
// And no transcript yet either (the 503 produced no text).
|
||||
let transcript = case_dir.join("2026-04-13T10-31-00Z.transcript.txt");
|
||||
assert!(!transcript.exists(), "no transcript expected on 503");
|
||||
// And no metadata sidecar yet either (the 503 produced no text).
|
||||
let meta = case_dir.join("2026-04-13T10-31-00Z.json");
|
||||
assert!(!meta.exists(), "no recording meta expected on 503");
|
||||
}
|
||||
|
||||
/// The worker must route the Whisper response through the Gazetteer
|
||||
/// before persisting. Mock returns the drift form "Zerebrum"; the
|
||||
/// persisted `.transcript.txt` must contain the canonical "Cerebrum".
|
||||
/// persisted `<stem>.json` must carry the canonical "Cerebrum".
|
||||
#[tokio::test]
|
||||
async fn transcribe_worker_normalizes_whisper_output() {
|
||||
let server = MockServer::start().await;
|
||||
@@ -438,10 +445,16 @@ async fn transcribe_worker_normalizes_whisper_output() {
|
||||
)
|
||||
.await;
|
||||
|
||||
let transcript_path = case_dir.join("2026-04-13T10-30-00Z.transcript.txt");
|
||||
assert!(transcript_path.exists(), "transcript missing");
|
||||
let transcript = std::fs::read_to_string(&transcript_path).unwrap();
|
||||
assert_eq!(transcript, "Patient mit Blutung im Cerebrum.");
|
||||
let meta_path = case_dir.join("2026-04-13T10-30-00Z.json");
|
||||
assert!(meta_path.exists(), "recording meta missing");
|
||||
let bytes = std::fs::read(&meta_path).unwrap();
|
||||
let meta: doctate_common::RecordingMeta = serde_json::from_slice(&bytes).unwrap();
|
||||
match meta.transcript {
|
||||
doctate_common::Transcript::Content { text } => {
|
||||
assert_eq!(text, "Patient mit Blutung im Cerebrum.");
|
||||
}
|
||||
other => panic!("expected Transcript::Content, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------- Ollama client --------------------
|
||||
|
||||
Reference in New Issue
Block a user