From 3052f9d262636498637caa88a1c9c9416fe43a4c Mon Sep 17 00:00:00 2001 From: solodddd Date: Thu, 22 Oct 2026 22:56:40 +0800 Subject: [PATCH 1/2] fix(textstream): keep the authoritative text when a decode rewrites a stable prefix --- .../src/asr/local/experimental/textstream/worker.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/openless-all/app/src-tauri/src/asr/local/experimental/textstream/worker.py b/openless-all/app/src-tauri/src/asr/local/experimental/textstream/worker.py index 7677307fb..3369e6233 100644 --- a/openless-all/app/src-tauri/src/asr/local/experimental/textstream/worker.py +++ b/openless-all/app/src-tauri/src/asr/local/experimental/textstream/worker.py @@ -99,7 +99,17 @@ def update(self, finalized: str, full: str, terminal: bool = False) -> dict: if terminal: finalized = full if not full.startswith(finalized): - raise ValueError("decoder snapshot does not contain its finalized prefix") + # A decode may rewrite text that an earlier snapshot reported as + # stable (script or normalisation flips). The protocol carries whole + # previews, and the terminal snapshot is authoritative, so keep the + # authoritative text and re-commit only the prefix both agree on + # instead of failing the whole transcription. + agreed = 0 + for previous, current in zip(finalized, full): + if previous != current: + break + agreed += 1 + finalized = finalized[:agreed] self.finalized, self.draft = finalized, full[len(finalized) :] self.sequence += 1 return { From 7498cc5eef6766a60151a0d63e9b85f9ca5b5cba Mon Sep 17 00:00:00 2001 From: solodddd Date: Thu, 22 Oct 2026 22:56:43 +0800 Subject: [PATCH 2/2] fix(textstream): keep the authoritative text when a decode rewrites a stable prefix --- .../asr/local/experimental/textstream/test_worker.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openless-all/app/src-tauri/src/asr/local/experimental/textstream/test_worker.py b/openless-all/app/src-tauri/src/asr/local/experimental/textstream/test_worker.py index c4ac6997d..df9ce4efe 100644 --- a/openless-all/app/src-tauri/src/asr/local/experimental/textstream/test_worker.py +++ b/openless-all/app/src-tauri/src/asr/local/experimental/textstream/test_worker.py @@ -136,8 +136,16 @@ def test_draft_is_revisable_and_final_comes_from_decoder(self): self.assertEqual(snapshots.update("你好", "你好")["draft"], "") final = snapshots.update("你好", "你好!", terminal=True) self.assertEqual((final["finalized"], final["draft"]), ("你好!", "")) - with self.assertRaises(ValueError): - snapshots.update("cannot match", "different") + # A rewritten decode must re-commit only the agreed prefix instead of + # failing: audio is already captured and the terminal text wins. + recovered = snapshots.update("cannot match", "different") + self.assertEqual(recovered["finalized"], "") + self.assertEqual(recovered["finalized"] + recovered["draft"], "different") + partial = snapshots.update("我们去了Co", "我们去了科蒂纳。") + self.assertEqual( + (partial["finalized"], partial["draft"]), ("我们去了", "科蒂纳。") + ) + self.assertNotEqual(snapshots.sequence, 0) def run_fake(self, finish=True, gpu_available=True): FakeSession.calls = []