textflowkit 0.1.12__tar.gz → 0.1.13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. {textflowkit-0.1.12 → textflowkit-0.1.13}/.github/workflows/ci.yml +13 -2
  2. textflowkit-0.1.13/AGENTS.md +19 -0
  3. {textflowkit-0.1.12 → textflowkit-0.1.13}/CHANGELOG.md +35 -0
  4. {textflowkit-0.1.12 → textflowkit-0.1.13}/PKG-INFO +60 -25
  5. {textflowkit-0.1.12 → textflowkit-0.1.13}/README.md +59 -24
  6. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/adapters.md +9 -7
  7. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/architecture.md +21 -6
  8. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/assets/architecture-overview.svg +1 -1
  9. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/assets/whistle-resume.svg +5 -5
  10. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/index.html +15 -14
  11. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/install.md +10 -8
  12. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/release-checklist.md +45 -2
  13. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/roadmap.md +13 -1
  14. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/streaming.md +4 -4
  15. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/user-manual.md +41 -22
  16. textflowkit-0.1.13/docs/verification/whistle-coverage-20261019.md +77 -0
  17. textflowkit-0.1.13/docs/verification/windows-sources-20261019.md +51 -0
  18. {textflowkit-0.1.12 → textflowkit-0.1.13}/packaging/windows/README.md +12 -5
  19. {textflowkit-0.1.12 → textflowkit-0.1.13}/packaging/windows/THIRD-PARTY-NOTICES.txt +13 -1
  20. textflowkit-0.1.13/packaging/windows/source-materials.json +39 -0
  21. {textflowkit-0.1.12 → textflowkit-0.1.13}/pyproject.toml +5 -1
  22. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/prepare_windows_payload.py +18 -0
  23. textflowkit-0.1.13/scripts/run_deepseek_worker.py +110 -0
  24. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/__init__.py +1 -1
  25. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/checkpoint.py +1 -1
  26. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/whistle.py +220 -21
  27. textflowkit-0.1.13/tests/fixtures/whistle_seam_regressions.json +3767 -0
  28. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_sdist_allowlist.py +4 -0
  29. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_whistle_engine.py +13 -13
  30. textflowkit-0.1.13/tests/test_whistle_seams.py +187 -0
  31. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_windows_payload.py +70 -0
  32. textflowkit-0.1.12/packaging/windows/source-materials.json +0 -20
  33. {textflowkit-0.1.12 → textflowkit-0.1.13}/.dockerignore +0 -0
  34. {textflowkit-0.1.12 → textflowkit-0.1.13}/.env.example +0 -0
  35. {textflowkit-0.1.12 → textflowkit-0.1.13}/.gitattributes +0 -0
  36. {textflowkit-0.1.12 → textflowkit-0.1.13}/.github/dependabot.yml +0 -0
  37. {textflowkit-0.1.12 → textflowkit-0.1.13}/.github/workflows/publish-pypi.yml +0 -0
  38. {textflowkit-0.1.12 → textflowkit-0.1.13}/.gitignore +0 -0
  39. {textflowkit-0.1.12 → textflowkit-0.1.13}/.pre-commit-config.yaml +0 -0
  40. {textflowkit-0.1.12 → textflowkit-0.1.13}/CONTRIBUTING.md +0 -0
  41. {textflowkit-0.1.12 → textflowkit-0.1.13}/Dockerfile +0 -0
  42. {textflowkit-0.1.12 → textflowkit-0.1.13}/LEGAL.md +0 -0
  43. {textflowkit-0.1.12 → textflowkit-0.1.13}/LICENSE +0 -0
  44. {textflowkit-0.1.12 → textflowkit-0.1.13}/SECURITY.md +0 -0
  45. {textflowkit-0.1.12 → textflowkit-0.1.13}/compose.yaml +0 -0
  46. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/.nojekyll +0 -0
  47. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/404.html +0 -0
  48. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/assets/live-streaming-flow.svg +0 -0
  49. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/assets/local-ui-flow.svg +0 -0
  50. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/site-deployment.md +0 -0
  51. {textflowkit-0.1.12 → textflowkit-0.1.13}/docs/sources.md +0 -0
  52. {textflowkit-0.1.12 → textflowkit-0.1.13}/packaging/windows/assets.lock.json +0 -0
  53. {textflowkit-0.1.12 → textflowkit-0.1.13}/packaging/windows/launch.py +0 -0
  54. {textflowkit-0.1.12 → textflowkit-0.1.13}/packaging/windows/textflowkit.iss +0 -0
  55. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/build_windows_installer.py +0 -0
  56. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/fetch_published_fonts.py +0 -0
  57. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/smoke_installed_wheel.py +0 -0
  58. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/smoke_live_youtube.py +0 -0
  59. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/verify_readme_release.py +0 -0
  60. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/verify_release_ci.py +0 -0
  61. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/verify_release_versions.py +0 -0
  62. {textflowkit-0.1.12 → textflowkit-0.1.13}/scripts/write_release_manifest.py +0 -0
  63. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/adapters/__init__.py +0 -0
  64. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/adapters/http_server.py +0 -0
  65. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/adapters/mcp_server.py +0 -0
  66. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/adapters/streaming_ws.py +0 -0
  67. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/assets/README.md +0 -0
  68. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/assets/selftest-speech.wav +0 -0
  69. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/cli.py +0 -0
  70. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/__init__.py +0 -0
  71. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/batch.py +0 -0
  72. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/bind.py +0 -0
  73. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/cancel.py +0 -0
  74. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/diarize.py +0 -0
  75. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/engine.py +0 -0
  76. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/executor.py +0 -0
  77. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/jobs.py +0 -0
  78. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/model.py +0 -0
  79. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/paths.py +0 -0
  80. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/pipeline.py +0 -0
  81. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/retrieval.py +0 -0
  82. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/runner.py +0 -0
  83. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/service.py +0 -0
  84. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/sqlite_store.py +0 -0
  85. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/startup.py +0 -0
  86. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/stream_worker.py +0 -0
  87. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/streaming.py +0 -0
  88. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/streaming_assets.py +0 -0
  89. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/streaming_events.py +0 -0
  90. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/streaming_process.py +0 -0
  91. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/submission.py +0 -0
  92. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/timeutil.py +0 -0
  93. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/translate.py +0 -0
  94. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/whistle_assets.py +0 -0
  95. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/core/windows_process.py +0 -0
  96. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/__init__.py +0 -0
  97. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/_cue_layout.py +0 -0
  98. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/_cue_text.py +0 -0
  99. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/_rename_excl.py +0 -0
  100. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/_rename_noreplace.py +0 -0
  101. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/docx.py +0 -0
  102. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/markdown.py +0 -0
  103. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/pdf.py +0 -0
  104. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/srt.py +0 -0
  105. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/txt.py +0 -0
  106. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/render/vtt.py +0 -0
  107. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/sources/__init__.py +0 -0
  108. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/sources/acquire.py +0 -0
  109. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/sources/detect.py +0 -0
  110. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/sources/scratch.py +0 -0
  111. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/__init__.py +0 -0
  112. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/app.py +0 -0
  113. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/capabilities.py +0 -0
  114. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/cleanup.py +0 -0
  115. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/launcher.py +0 -0
  116. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/ownership.py +0 -0
  117. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/paths.py +0 -0
  118. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/security.py +0 -0
  119. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/static/app.css +0 -0
  120. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/static/app.js +0 -0
  121. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/static/cleanup.js +0 -0
  122. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/static/index.html +0 -0
  123. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/static/streaming-capture-worklet.js +0 -0
  124. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/static/streaming-example.html +0 -0
  125. {textflowkit-0.1.12 → textflowkit-0.1.13}/src/textflowkit/ui/uploads.py +0 -0
  126. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/__init__.py +0 -0
  127. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/ollama_stub.py +0 -0
  128. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_acquire.py +0 -0
  129. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_adapters.py +0 -0
  130. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_admission_ownership.py +0 -0
  131. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_atomic_resume.py +0 -0
  132. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_atomic_resume_aba.py +0 -0
  133. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_batch.py +0 -0
  134. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_batch_item_boundary.py +0 -0
  135. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_batch_resume_shared.py +0 -0
  136. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_bind.py +0 -0
  137. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cancellation_finalization.py +0 -0
  138. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_checkpoint.py +0 -0
  139. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_checkpoint_single_copy.py +0 -0
  140. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cli.py +0 -0
  141. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cli_batch_feedback.py +0 -0
  142. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cli_owning_recovery.py +0 -0
  143. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cli_resume_batch.py +0 -0
  144. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cli_stage_feedback.py +0 -0
  145. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cli_stdout_format.py +0 -0
  146. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_confined_decoder_boundary.py +0 -0
  147. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_confined_indirect_media.py +0 -0
  148. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_confined_resume_boundary.py +0 -0
  149. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_container_example.py +0 -0
  150. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_cue_layout.py +0 -0
  151. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_diarize.py +0 -0
  152. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_diarize_example_flags.py +0 -0
  153. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_diarize_token_docs.py +0 -0
  154. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_docx_publication_identity.py +0 -0
  155. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_done_output_integrity.py +0 -0
  156. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_empty_formats_resume.py +0 -0
  157. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_engine_adapters.py +0 -0
  158. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_engine_cache.py +0 -0
  159. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_engine_faster.py +0 -0
  160. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_engine_quiet.py +0 -0
  161. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_executor.py +0 -0
  162. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_executor_store_failure.py +0 -0
  163. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_export.py +0 -0
  164. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_export_file_mode.py +0 -0
  165. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_export_preflight.py +0 -0
  166. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_faster_whisper_docs.py +0 -0
  167. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_fetch_published_fonts.py +0 -0
  168. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_font_notices.py +0 -0
  169. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_http_host_boundary.py +0 -0
  170. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_http_trusted_proxy.py +0 -0
  171. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_job_progress.py +0 -0
  172. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_jobs.py +0 -0
  173. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_landing_commands.py +0 -0
  174. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_landing_page.py +0 -0
  175. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_legal_summary.py +0 -0
  176. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_linux_no_hardlink.py +0 -0
  177. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_live_smoke_script.py +0 -0
  178. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_macos_no_hardlink.py +0 -0
  179. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_mcp_batch_cookie_docs.py +0 -0
  180. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_mcp_http_boundary.py +0 -0
  181. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_mcp_protocol_cleanliness.py +0 -0
  182. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_mcp_terminal_guidance.py +0 -0
  183. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_mcp_tool_descriptions.py +0 -0
  184. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_mcp_work_root.py +0 -0
  185. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_model.py +0 -0
  186. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_partial_output_resume.py +0 -0
  187. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_partial_pdf_resume.py +0 -0
  188. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_paths.py +0 -0
  189. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_pipeline_integrity.py +0 -0
  190. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_pipeline_resume_setup.py +0 -0
  191. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_production_browser_cookies.py +0 -0
  192. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_publish_ci_gate.py +0 -0
  193. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_publish_fonts_wiring.py +0 -0
  194. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_publish_manifest_wiring.py +0 -0
  195. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_publish_workflow_gate.py +0 -0
  196. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_readme_layout.py +0 -0
  197. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_readme_release_guard.py +0 -0
  198. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_release_boundaries.py +0 -0
  199. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_release_manifest.py +0 -0
  200. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_release_surfaces.py +0 -0
  201. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_render.py +0 -0
  202. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_retrieval.py +0 -0
  203. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_service_profile.py +0 -0
  204. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_site_not_found.py +0 -0
  205. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_sources.py +0 -0
  206. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_stage_reuse_resume.py +0 -0
  207. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_startup_recovery.py +0 -0
  208. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_stdio_protocol.py +0 -0
  209. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_assets.py +0 -0
  210. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_browser_lifecycle.py +0 -0
  211. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_core.py +0 -0
  212. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_example.py +0 -0
  213. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_repairs.py +0 -0
  214. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_transport.py +0 -0
  215. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_u5_repairs.py +0 -0
  216. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_streaming_ui_integration.py +0 -0
  217. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_submission.py +0 -0
  218. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_submission_validation.py +0 -0
  219. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_translate.py +0 -0
  220. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_translate_completeness.py +0 -0
  221. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_assets_and_capabilities.py +0 -0
  222. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_cleanup.py +0 -0
  223. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_consoleless_logging.py +0 -0
  224. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_existing_routes_unchanged.py +0 -0
  225. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_launcher.py +0 -0
  226. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_ownership_and_shutdown.py +0 -0
  227. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_packaging.py +0 -0
  228. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_real_serve.py +0 -0
  229. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_security.py +0 -0
  230. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_submission_and_download.py +0 -0
  231. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_ui_uploads.py +0 -0
  232. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_verify_release_versions.py +0 -0
  233. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_whistle_assets.py +0 -0
  234. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_whistle_defaults.py +0 -0
  235. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_whistle_job_resume.py +0 -0
  236. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_windows_installer.py +0 -0
  237. {textflowkit-0.1.12 → textflowkit-0.1.13}/tests/test_windows_no_hardlink.py +0 -0
@@ -45,9 +45,20 @@ jobs:
45
45
  if: runner.os == 'Linux'
46
46
  run: sudo apt-get update && sudo apt-get install -y ffmpeg
47
47
 
48
- - name: Install ffmpeg (Windows)
48
+ - name: Install pinned ffmpeg (Windows)
49
49
  if: runner.os == 'Windows'
50
- run: choco install ffmpeg --no-progress -y
50
+ shell: python
51
+ run: |
52
+ import os, runpy
53
+ from pathlib import Path
54
+ ns = runpy.run_path('scripts/prepare_windows_payload.py')
55
+ spec = ns['load_asset_lock'](Path('packaging/windows/assets.lock.json'))['assets']['ffmpeg']
56
+ cache = Path(os.environ['RUNNER_TEMP']) / 'textflowkit-ci-ffmpeg'
57
+ archive = ns['_download_locked_asset'](cache, spec)
58
+ destination = cache / 'payload'
59
+ ns['prepare_ffmpeg_archive'](archive, destination)
60
+ with open(os.environ['GITHUB_PATH'], 'a', encoding='utf-8') as f:
61
+ f.write(str(destination / 'bin') + '\n')
51
62
 
52
63
  - name: Install ffmpeg (macOS)
53
64
  if: runner.os == 'macOS'
@@ -0,0 +1,19 @@
1
+ # TextFlowKit agent instructions
2
+
3
+ Scott's current bounded completion contract governs this work. Follow the active task and repository-required CI; preserve unrelated work and credentials. Keep one concise execution record, reuse unaffected evidence, and distinguish prepared, executed, verified and delivered work. A documented blocker remains incomplete. Do not invent adjacent features or weaken checks.
4
+
5
+ ## Roles and delegation
6
+
7
+ The main assistant coordinates, plans and oversees. A worker invoked for an implementation unit performs that assigned unit directly; it is not another coordinator. Do not launch nested workers or automatic review/fan-out unless the owner or assignment explicitly authorizes it. Default to serial execution and one release candidate.
8
+
9
+ ## Model selection
10
+
11
+ Follow Scott's active task selection; do not impose a project-wide Ollama default. His normal substantial-work/coordination preference is gpt-6.1-sol at medium, with gpt-6-luna at xhigh for small bounded work when available. Do not spawn a worker merely to switch models or add providers without authorization.
12
+
13
+ For the explicitly authorized current Whistle release and issue #31 source-recovery work, Scott requested Ollama `deepseek-v4.1-flash:1017-cloud`, reasoning OFF. `scripts/run_deepseek_worker.py` is an explicit opt-in runner for those assigned DeepSeek units: it sends `think: false`, allows no model fallback, and records the actual response model. Ollama currently returns canonical ID `deepseek-v4.1-flash:1017` without the `-cloud` transport suffix. Do not confuse a worker's self-description with the transport receipts. Preserve existing DeepSeek integrations with reasoning off, but do not turn this task-specific instruction into the default for unrelated future work.
14
+
15
+ This does not change the application's transcription or AI-cleanup defaults. Whistle remains the default transcription engine.
16
+
17
+ ## Scope and delivery safeguards
18
+
19
+ Preserve unfinished work. Workers must not push, merge, tag, publish, release, stop unrelated processes, or change global configuration unless that unit is explicitly authorized to do so. The coordinating release task has Scott's push/merge/tag/publication authorization and separately his authorization to complete issue #31. Keep scratch, caches and build outputs outside the checkout. Verify process identity before acting on a PID; record ownership and terminal result for background jobs. Follow enforced controls rather than disguising a rejected action.
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.1.13 — 2026-10-19
4
+
5
+ Core: 0.1.13; unchanged optional fonts: 0.1.6. Whistle missing-speech fixes and a
6
+ native Windows installer distributed with matching FFmpeg sources and notices.
7
+
8
+ - Bound native Whistle decode inputs to 15 seconds with 11-second owned cores
9
+ and up to two seconds of context per side. The former 30-second inputs
10
+ reproducibly omitted passages recovered by shorter inputs. Window policy is
11
+ part of resume identity; partial progress from the old plan requires a fresh
12
+ run. The engine and pinned model remain Whistle.
13
+ - Check short gaps with a bounded, differently framed native decode. Add words
14
+ only between two matching timed anchors; retain original words/repetitions,
15
+ skip long pauses, and cap extra calls per core. Record recovery counts.
16
+ - Correct Whistle shared-context assembly when independently estimated word
17
+ timestamps cause both neighboring cores to keep or discard the same occurrence.
18
+ Match occurrences one-to-one; preserve real repeated speech and leave ambiguous
19
+ collapsed repetitions untouched rather than using global text deduplication.
20
+ - Persist raw boundary context in Whistle progress schema 2 so resumed assembly
21
+ matches uninterrupted output. Old schema-1 partial runs require a fresh start;
22
+ completed jobs remain unchanged. Default engine remains Whistle.
23
+ - The native 30-second omission cases remain reproducible upstream; shorter
24
+ input windows and anchored gap checks mitigate them in TextFlowKit without
25
+ changing the engine or model weights.
26
+ - Verification on one four-hour public meeting (1310 native cores, 18 min 34 s
27
+ native decode, 34,723 final words): the two long missing passages were
28
+ restored (2 to 50 and 0 to 47 words), 62 short-gap checks accepted 7 for 53
29
+ added words, resume after cores 350 and 700 reproduced exact word text and
30
+ timings, and no invalid bounds or backwards starts remained. Focused suite:
31
+ 113 passed. Full suite: 2,097 passed, 18 skipped; skips are not passes. This is
32
+ coverage evidence for one recording, not human WER or perfect accuracy; normal
33
+ spelling errors remain. See
34
+ [the verification note](docs/verification/whistle-coverage-20261019.md).
35
+
36
+ - Package matching FFmpeg sources, pinned build recipes, dependency archives and full notices alongside the Windows installer; record source hashes and preserve compatible DLL replacement. See [source verification](docs/verification/windows-sources-20261019.md).
37
+
3
38
  ## v0.1.12 — 2026-10-17
4
39
 
5
40
  Core: 0.1.12; unchanged optional fonts: 0.1.6. The native Windows installer has been built and tested locally. The installer recipe ships in v0.1.12; the EXE remains local-only until unresolved corresponding-source compliance review is cleared. No public installer download link is available.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: textflowkit
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Cross-platform media transcription toolkit: URL or file in, timestamped transcripts and subtitle files out.
5
5
  Project-URL: Homepage, https://www.textflowkit.org/
6
6
  Project-URL: Issues, https://github.com/scottconverse/textflowkit/issues
@@ -73,7 +73,7 @@ Cross-platform media transcription toolkit. **One core, one CLI, thin adapters.*
73
73
  [User manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md) ·
74
74
  [Developer and integration manual](https://github.com/scottconverse/textflowkit/blob/main/docs/adapters.md)
75
75
 
76
- **Current release: [v0.1.12](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.12).**
76
+ **Current release: [v0.1.13](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13).**
77
77
 
78
78
  The [static site deployment](https://github.com/scottconverse/textflowkit/blob/main/docs/site-deployment.md) is hosted on Cloudflare
79
79
  Pages. GitHub remains the source and CI host; the website does not run the
@@ -134,7 +134,7 @@ DOCX and PDF are available through the optional `export` extra.
134
134
 
135
135
  ## Architecture
136
136
 
137
- ![TextFlowKit shared-core architecture: five thin entry points feed one core. The CLI, Python API, MCP, HTTP API, and the local browser UI (a fifth door that mounts the existing HTTP app under /api and shares the same job store, adding transport only, not a new pipeline) sit above one core that acquires and decodes media, transcribes with the default Whistle engine or an explicitly selected openai-whisper, keeps job state and resume checkpoints in an optional SQLite store, adds optional speaker or translation postprocessing, and publishes TXT, SRT, VTT, JSON, Markdown, and optional DOCX/PDF exports.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.12/docs/assets/architecture-overview.svg)
137
+ ![TextFlowKit shared-core architecture: five thin entry points feed one core. The CLI, Python API, MCP, HTTP API, and the local browser UI (a fifth door that mounts the existing HTTP app under /api and shares the same job store, adding transport only, not a new pipeline) sit above one core that acquires and decodes media, transcribes with the default Whistle engine or an explicitly selected openai-whisper, keeps job state and resume checkpoints in an optional SQLite store, adds optional speaker or translation postprocessing, and publishes TXT, SRT, VTT, JSON, Markdown, and optional DOCX/PDF exports.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.13/docs/assets/architecture-overview.svg)
138
138
 
139
139
  The design principle is **one shared core, thin doors**. Everything of substance
140
140
  lives in the core; the interfaces are thin — the local browser UI is a fifth door
@@ -158,7 +158,7 @@ see [docs/architecture.md](https://github.com/scottconverse/textflowkit/blob/mai
158
158
 
159
159
  ## Live microphone streaming (opt-in)
160
160
 
161
- In v0.1.12, live streaming supports **Windows x86_64 only**. When
161
+ In v0.1.13, live streaming supports **Windows x86_64 only**. When
162
162
  `TEXTFLOWKIT_STREAMING=1` is set, the developer HTTP app serves a `/stream`
163
163
  WebSocket and the local UI serves `/api/stream`, both transcribing a live microphone
164
164
  as you speak. A **runnable, self-hosted browser example** ships at
@@ -167,7 +167,7 @@ as you speak. A **runnable, self-hosted browser example** ships at
167
167
  No CDN, no analytics, no external fetch. Requires the `streaming` extra:
168
168
 
169
169
  ```bash
170
- python -m pip install "textflowkit[streaming]==0.1.12"
170
+ python -m pip install "textflowkit[streaming]==0.1.13"
171
171
  ```
172
172
 
173
173
  It is **off by default** — with the switch unset the endpoint does not exist — and
@@ -233,11 +233,13 @@ installs `textflowkit-fonts` for offline multilingual PDF rendering:
233
233
  python -m pip install 'textflowkit[export]'
234
234
  ```
235
235
 
236
- ## Windows desktop installer (v0.1.12; public EXE pending)
236
+ ## Windows desktop installer (v0.1.13)
237
237
 
238
- An installer for the existing local browser workspace accompanies core v0.1.12. The native Windows installer has been built and tested locally. The installer recipe ships in v0.1.12; the EXE remains local-only until unresolved corresponding-source compliance review is cleared. No public installer download link is available. The Python package remains supported for developers and integrations.
238
+ [Download Windows x64 setup](https://github.com/scottconverse/textflowkit/releases/download/v0.1.13/TextFlowKit-0.1.13-windows-x64-setup.exe) · [Matching sources and notices](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13)
239
239
 
240
- The candidate is designed to run without a separately installed Python, WSL, or
240
+ An installer for the existing local browser workspace accompanies core v0.1.13. The Windows installer and its matching FFmpeg source and notice bundles are distributed together through the [v0.1.13 release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13). The Python package remains supported for developers and integrations.
241
+
242
+ The installer is designed to run without a separately installed Python, WSL, or
241
243
  Docker. Its bundle includes a private embeddable CPython runtime, the
242
244
  browser UI and HTTP, export, and streaming dependencies, the pinned Whistle model
243
245
  and runtime, and ffmpeg, ffprobe, and Node. The setup installs per user,
@@ -254,16 +256,16 @@ bundled; those features remain documented for the Python package when separately
254
256
  installed and configured. Streaming dependencies are bundled, but live streaming
255
257
  remains opt-in and physical browser microphone capture has not been verified.
256
258
 
257
- The candidate is designed to keep UI data outside the application install
259
+ The installer is designed to keep UI data outside the application install
258
260
  directory and preserve it on upgrades and uninstall. Stop the UI server with
259
261
  **Stop server** and wait for it to exit before upgrading or uninstalling; the
260
262
  installer will block while it is running rather than force-killing active jobs.
261
263
  Cancel a job first if it should not drain to completion. The bundle also
262
264
  includes third-party license and notice files, including FFmpeg's LGPL notices
263
265
  and corresponding-source information. Check exact notices and source-distribution
264
- details against the final bundled binaries before publication. The candidate is
266
+ details in the matching source bundles distributed with this release. The installer is
265
267
  unsigned, so Windows may show a SmartScreen warning. See the [installer candidate
266
- notes](docs/install.md#windows-desktop-installer-v0112-public-exe-pending).
268
+ notes](https://github.com/scottconverse/textflowkit/blob/main/docs/install.md#windows-desktop-installer-v0113).
267
269
 
268
270
  ## Python API
269
271
 
@@ -360,7 +362,7 @@ textflowkit export ./transcript.json --format vtt
360
362
  needs no PyTorch, so a fresh `pip install textflowkit` stays small and pulls no
361
363
  torch; `openai-whisper` is an explicitly selectable opt-in engine.
362
364
 
363
- ![Whistle bounded block run and durable resume: a decoded PCM WAV is split into 26-second cores with up to 2 seconds of context (each clip ≤ 30 s), each core runs as one owned child with forced telemetry-off flags, a partial checkpoint is written after each core, and a resume validates the source and decoded-WAV hashes then re-runs only the unfinished cores.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.12/docs/assets/whistle-resume.svg)
365
+ ![Whistle bounded block run and durable resume: a decoded PCM WAV is split into 11-second cores with up to 2 seconds of context (each clip ≤ 15 s), each core runs as one owned child with forced telemetry-off flags, a partial checkpoint is written after each core, and a resume validates the source and decoded-WAV hashes then re-runs only the unfinished cores.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.13/docs/assets/whistle-resume.svg)
364
366
 
365
367
  - **CPU only, no torch.** It runs a pinned native binary and downloads one pinned
366
368
  model on first use. Naming a GPU device is refused rather than silently
@@ -373,16 +375,26 @@ torch; `openai-whisper` is an explicitly selectable opt-in engine.
373
375
  Apple Silicon. **Intel Macs are not supported**; a request there is refused
374
376
  with a message that names the explicit `whisper` engine instead. No WSL layer
375
377
  is involved.
376
- - **How it works:** long audio is split into 26-second cores with up to 2 seconds
377
- of context on each side, so every standalone clip is ≤ 30 seconds (the native
378
- CLI's limit). Overlap words are selected by core midpoint rather than text
379
- deduplication, so repeated spoken phrases are preserved.
378
+ - **How it works:** long audio is split into 11-second cores with up to 2 seconds
379
+ of context on each side, so every standalone clip is ≤ 15 seconds. This conservative
380
+ ceiling avoids reproduced omissions on 30-second inputs. Midpoints provide initial ownership; shared-context matching
381
+ reconciles duplicate or dropped occurrences when neighboring timestamps
382
+ disagree. This is not global text deduplication: real repetitions and ambiguous
383
+ recognition are preserved. The 15-second ceiling and this assembly behavior ship
384
+ in v0.1.13; neither recovers speech the native recognizer never emits.
385
+ - **Speech-gap check (v0.1.13).** Short gaps between recognized words receive a
386
+ bounded second listen with different clip boundaries. Extra words are accepted
387
+ only between matching words on both sides at nearby times. Existing words and
388
+ repetitions stay intact; long pauses do not trigger this check. The model is
389
+ still Whistle, with the same pinned weights and telemetry settings.
380
390
  - **Standalone streaming is not used.** The native `--audio-stream` mode failed its
381
391
  coverage and is never passed; only the committed standalone output is parsed.
382
392
  - **Durable block resume.** With `TEXTFLOWKIT_DB` set, a long run writes partial
383
393
  per-block checkpoints; a resume checks the source and decoded-WAV hashes and the
384
394
  config, then re-runs only the blocks that were not finished. The durable store
385
- still assumes one owning process.
395
+ still assumes one owning process. The v0.1.13 assembly policy saves raw
396
+ boundary context with schema 2; old schema-1 partial runs must be restarted,
397
+ not resumed under the new assembly policy. Existing completed jobs are unchanged.
386
398
  - **Cancellation.** A running Whistle run terminates its exact owned child
387
399
  process bounded by a per-clip timeout. A single long `openai-whisper` model call
388
400
  is still only cancellable at its next stage boundary, as documented for the
@@ -471,7 +483,7 @@ its own beyond the `http` extra. It ships with the core package as of v0.1.10:
471
483
  a regular install of the current release carries it.
472
484
 
473
485
  ```bash
474
- python -m pip install 'textflowkit[http,export]==0.1.12'
486
+ python -m pip install 'textflowkit[http,export]==0.1.13'
475
487
  textflowkit-ui
476
488
  ```
477
489
 
@@ -542,9 +554,16 @@ browser interface share the job contract without blocking a request.
542
554
 
543
555
  ## Status
544
556
 
545
- **v0.1.12 release.** Adds optional UI-only local Ollama proofreading and native
546
- Windows installer packaging; public EXE distribution remains gated on unresolved
547
- corresponding-source compliance review, with no public installer download link.
557
+ **v0.1.13 release.** Fixes reproduced Whistle speech omissions. Native decode
558
+ inputs are now bounded to 15 seconds (11-second owned cores with up to 2 seconds
559
+ of context per side), short interior speech gaps get a bounded second listen that
560
+ accepts words only between matching timed anchors, and shared-context words are
561
+ reconciled one-to-one before durable resume. Whistle remains the default engine
562
+ with the same pinned model and runtime; fonts remain 0.1.6. Progress schema 2
563
+ stores raw boundary context, so an unfinished partial job from the previous
564
+ 26-second-core plan (schema 1) must be restarted instead of resumed; completed
565
+ records are unchanged. The native Windows installer is rebuilt at v0.1.13 and
566
+ distributed with matching FFmpeg sources, notices, hashes and build instructions.
548
567
  Existing optional live streaming provides a transport-neutral
549
568
  `StreamingSession` Python API, incremental transcript events, and authenticated
550
569
  loopback WebSockets (`/stream` on the developer HTTP API and `/api/stream` on the
@@ -567,6 +586,22 @@ Linux/macOS, and the six other accepted languages were not verified. The public
567
586
  website remains static documentation and serves no streaming endpoint. Local source
568
587
  validation does not establish published-package or exact-commit CI results.
569
588
 
589
+ **v0.1.12 cleanup (historical).** The opt-in local Ollama proofreading path remains
590
+ as introduced in v0.1.12, covering the local browser UI only; it was not changed by
591
+ v0.1.13. It keeps the published 39-segment cleanup proof from v0.1.12 with no
592
+ audio-accuracy claim: that proof records segment/format handling, not recognition
593
+ accuracy.
594
+
595
+ **v0.1.13 Whistle coverage, omission, and resume.** The 15-second bound (11-second
596
+ cores plus up to 2 s context per side) fixes reproduced speech omissions on
597
+ 30-second inputs; the interior speech-gap second listen accepts extra words only
598
+ between matching timed anchors; shared-context words are reconciled one-to-one
599
+ before durable resume so a partial run rejoins without double ownership. Recognized
600
+ language coverage remains the same accepted set, and nothing here recovers speech
601
+ the native recognizer never emits. See
602
+ [docs/verification/whistle-coverage-20261019.md](https://github.com/scottconverse/textflowkit/blob/main/docs/verification/whistle-coverage-20261019.md)
603
+ for the run-by-run coverage, omission, and resume evidence.
604
+
570
605
  **Verification limit.** The local browser interface is covered by an automated
571
606
  suite, and the UI's behavior was proved on a **native Windows** machine in a real
572
607
  browser. No live optional-backend (translation/diarization) run through the UI is
@@ -589,7 +624,7 @@ MCP speech, seven-format exports and completed resume; the v0.1.8 runtime fixes
589
624
  were independently checked through fresh-process CLI restart probes, real SQLite
590
625
  setup-failure tests, and the full Windows test suite. Those checks are not new
591
626
  individual-harness receipts. That is the previous releases' record, not evidence
592
- for v0.1.12.
627
+ for v0.1.13.
593
628
 
594
629
  The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
595
630
  for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
@@ -608,7 +643,7 @@ and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
608
643
  [fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
609
644
  live — that is the v0.1.6 release's evidence, not a receipt for a later release.
610
645
  Everything from here to the end of this section is the v0.1.6 release's
611
- historical record as published: it is not re-verified for v0.1.12, whose separate release evidence is not supplied by these historical paragraphs.
646
+ historical record as published: it is not re-verified for v0.1.13, whose separate release evidence is not supplied by these historical paragraphs.
612
647
  Merged-main CI passed 16/16 on the tagged commit; the published wheel and
613
648
  sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
614
649
  Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
@@ -647,9 +682,9 @@ Issues and PRs welcome. Please read [LEGAL.md](https://github.com/scottconverse/
647
682
  adapter.
648
683
 
649
684
 
650
- ## Optional local AI transcript cleanup (v0.1.12)
685
+ ## Optional local AI transcript cleanup (introduced in v0.1.12)
651
686
 
652
- v0.1.12 adds **opt-in proofreading in the local browser UI only**. After a transcription finishes, choose an
687
+ v0.1.12 adds **opt-in proofreading in the local browser UI only** (introduced in v0.1.12; unchanged in v0.1.13). After a transcription finishes, choose an
653
688
  installed local Ollama model and click **Proofread with local AI**. Cleanup never
654
689
  runs automatically. Ollama and cleanup models are not bundled in the installer.
655
690
  The optional default preference is `qwen3.5:9b` only if already installed; its
@@ -8,7 +8,7 @@ Cross-platform media transcription toolkit. **One core, one CLI, thin adapters.*
8
8
  [User manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md) ·
9
9
  [Developer and integration manual](https://github.com/scottconverse/textflowkit/blob/main/docs/adapters.md)
10
10
 
11
- **Current release: [v0.1.12](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.12).**
11
+ **Current release: [v0.1.13](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13).**
12
12
 
13
13
  The [static site deployment](https://github.com/scottconverse/textflowkit/blob/main/docs/site-deployment.md) is hosted on Cloudflare
14
14
  Pages. GitHub remains the source and CI host; the website does not run the
@@ -69,7 +69,7 @@ DOCX and PDF are available through the optional `export` extra.
69
69
 
70
70
  ## Architecture
71
71
 
72
- ![TextFlowKit shared-core architecture: five thin entry points feed one core. The CLI, Python API, MCP, HTTP API, and the local browser UI (a fifth door that mounts the existing HTTP app under /api and shares the same job store, adding transport only, not a new pipeline) sit above one core that acquires and decodes media, transcribes with the default Whistle engine or an explicitly selected openai-whisper, keeps job state and resume checkpoints in an optional SQLite store, adds optional speaker or translation postprocessing, and publishes TXT, SRT, VTT, JSON, Markdown, and optional DOCX/PDF exports.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.12/docs/assets/architecture-overview.svg)
72
+ ![TextFlowKit shared-core architecture: five thin entry points feed one core. The CLI, Python API, MCP, HTTP API, and the local browser UI (a fifth door that mounts the existing HTTP app under /api and shares the same job store, adding transport only, not a new pipeline) sit above one core that acquires and decodes media, transcribes with the default Whistle engine or an explicitly selected openai-whisper, keeps job state and resume checkpoints in an optional SQLite store, adds optional speaker or translation postprocessing, and publishes TXT, SRT, VTT, JSON, Markdown, and optional DOCX/PDF exports.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.13/docs/assets/architecture-overview.svg)
73
73
 
74
74
  The design principle is **one shared core, thin doors**. Everything of substance
75
75
  lives in the core; the interfaces are thin — the local browser UI is a fifth door
@@ -93,7 +93,7 @@ see [docs/architecture.md](https://github.com/scottconverse/textflowkit/blob/mai
93
93
 
94
94
  ## Live microphone streaming (opt-in)
95
95
 
96
- In v0.1.12, live streaming supports **Windows x86_64 only**. When
96
+ In v0.1.13, live streaming supports **Windows x86_64 only**. When
97
97
  `TEXTFLOWKIT_STREAMING=1` is set, the developer HTTP app serves a `/stream`
98
98
  WebSocket and the local UI serves `/api/stream`, both transcribing a live microphone
99
99
  as you speak. A **runnable, self-hosted browser example** ships at
@@ -102,7 +102,7 @@ as you speak. A **runnable, self-hosted browser example** ships at
102
102
  No CDN, no analytics, no external fetch. Requires the `streaming` extra:
103
103
 
104
104
  ```bash
105
- python -m pip install "textflowkit[streaming]==0.1.12"
105
+ python -m pip install "textflowkit[streaming]==0.1.13"
106
106
  ```
107
107
 
108
108
  It is **off by default** — with the switch unset the endpoint does not exist — and
@@ -168,11 +168,13 @@ installs `textflowkit-fonts` for offline multilingual PDF rendering:
168
168
  python -m pip install 'textflowkit[export]'
169
169
  ```
170
170
 
171
- ## Windows desktop installer (v0.1.12; public EXE pending)
171
+ ## Windows desktop installer (v0.1.13)
172
172
 
173
- An installer for the existing local browser workspace accompanies core v0.1.12. The native Windows installer has been built and tested locally. The installer recipe ships in v0.1.12; the EXE remains local-only until unresolved corresponding-source compliance review is cleared. No public installer download link is available. The Python package remains supported for developers and integrations.
173
+ [Download Windows x64 setup](https://github.com/scottconverse/textflowkit/releases/download/v0.1.13/TextFlowKit-0.1.13-windows-x64-setup.exe) · [Matching sources and notices](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13)
174
174
 
175
- The candidate is designed to run without a separately installed Python, WSL, or
175
+ An installer for the existing local browser workspace accompanies core v0.1.13. The Windows installer and its matching FFmpeg source and notice bundles are distributed together through the [v0.1.13 release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13). The Python package remains supported for developers and integrations.
176
+
177
+ The installer is designed to run without a separately installed Python, WSL, or
176
178
  Docker. Its bundle includes a private embeddable CPython runtime, the
177
179
  browser UI and HTTP, export, and streaming dependencies, the pinned Whistle model
178
180
  and runtime, and ffmpeg, ffprobe, and Node. The setup installs per user,
@@ -189,16 +191,16 @@ bundled; those features remain documented for the Python package when separately
189
191
  installed and configured. Streaming dependencies are bundled, but live streaming
190
192
  remains opt-in and physical browser microphone capture has not been verified.
191
193
 
192
- The candidate is designed to keep UI data outside the application install
194
+ The installer is designed to keep UI data outside the application install
193
195
  directory and preserve it on upgrades and uninstall. Stop the UI server with
194
196
  **Stop server** and wait for it to exit before upgrading or uninstalling; the
195
197
  installer will block while it is running rather than force-killing active jobs.
196
198
  Cancel a job first if it should not drain to completion. The bundle also
197
199
  includes third-party license and notice files, including FFmpeg's LGPL notices
198
200
  and corresponding-source information. Check exact notices and source-distribution
199
- details against the final bundled binaries before publication. The candidate is
201
+ details in the matching source bundles distributed with this release. The installer is
200
202
  unsigned, so Windows may show a SmartScreen warning. See the [installer candidate
201
- notes](docs/install.md#windows-desktop-installer-v0112-public-exe-pending).
203
+ notes](https://github.com/scottconverse/textflowkit/blob/main/docs/install.md#windows-desktop-installer-v0113).
202
204
 
203
205
  ## Python API
204
206
 
@@ -295,7 +297,7 @@ textflowkit export ./transcript.json --format vtt
295
297
  needs no PyTorch, so a fresh `pip install textflowkit` stays small and pulls no
296
298
  torch; `openai-whisper` is an explicitly selectable opt-in engine.
297
299
 
298
- ![Whistle bounded block run and durable resume: a decoded PCM WAV is split into 26-second cores with up to 2 seconds of context (each clip ≤ 30 s), each core runs as one owned child with forced telemetry-off flags, a partial checkpoint is written after each core, and a resume validates the source and decoded-WAV hashes then re-runs only the unfinished cores.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.12/docs/assets/whistle-resume.svg)
300
+ ![Whistle bounded block run and durable resume: a decoded PCM WAV is split into 11-second cores with up to 2 seconds of context (each clip ≤ 15 s), each core runs as one owned child with forced telemetry-off flags, a partial checkpoint is written after each core, and a resume validates the source and decoded-WAV hashes then re-runs only the unfinished cores.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.13/docs/assets/whistle-resume.svg)
299
301
 
300
302
  - **CPU only, no torch.** It runs a pinned native binary and downloads one pinned
301
303
  model on first use. Naming a GPU device is refused rather than silently
@@ -308,16 +310,26 @@ torch; `openai-whisper` is an explicitly selectable opt-in engine.
308
310
  Apple Silicon. **Intel Macs are not supported**; a request there is refused
309
311
  with a message that names the explicit `whisper` engine instead. No WSL layer
310
312
  is involved.
311
- - **How it works:** long audio is split into 26-second cores with up to 2 seconds
312
- of context on each side, so every standalone clip is ≤ 30 seconds (the native
313
- CLI's limit). Overlap words are selected by core midpoint rather than text
314
- deduplication, so repeated spoken phrases are preserved.
313
+ - **How it works:** long audio is split into 11-second cores with up to 2 seconds
314
+ of context on each side, so every standalone clip is ≤ 15 seconds. This conservative
315
+ ceiling avoids reproduced omissions on 30-second inputs. Midpoints provide initial ownership; shared-context matching
316
+ reconciles duplicate or dropped occurrences when neighboring timestamps
317
+ disagree. This is not global text deduplication: real repetitions and ambiguous
318
+ recognition are preserved. The 15-second ceiling and this assembly behavior ship
319
+ in v0.1.13; neither recovers speech the native recognizer never emits.
320
+ - **Speech-gap check (v0.1.13).** Short gaps between recognized words receive a
321
+ bounded second listen with different clip boundaries. Extra words are accepted
322
+ only between matching words on both sides at nearby times. Existing words and
323
+ repetitions stay intact; long pauses do not trigger this check. The model is
324
+ still Whistle, with the same pinned weights and telemetry settings.
315
325
  - **Standalone streaming is not used.** The native `--audio-stream` mode failed its
316
326
  coverage and is never passed; only the committed standalone output is parsed.
317
327
  - **Durable block resume.** With `TEXTFLOWKIT_DB` set, a long run writes partial
318
328
  per-block checkpoints; a resume checks the source and decoded-WAV hashes and the
319
329
  config, then re-runs only the blocks that were not finished. The durable store
320
- still assumes one owning process.
330
+ still assumes one owning process. The v0.1.13 assembly policy saves raw
331
+ boundary context with schema 2; old schema-1 partial runs must be restarted,
332
+ not resumed under the new assembly policy. Existing completed jobs are unchanged.
321
333
  - **Cancellation.** A running Whistle run terminates its exact owned child
322
334
  process bounded by a per-clip timeout. A single long `openai-whisper` model call
323
335
  is still only cancellable at its next stage boundary, as documented for the
@@ -406,7 +418,7 @@ its own beyond the `http` extra. It ships with the core package as of v0.1.10:
406
418
  a regular install of the current release carries it.
407
419
 
408
420
  ```bash
409
- python -m pip install 'textflowkit[http,export]==0.1.12'
421
+ python -m pip install 'textflowkit[http,export]==0.1.13'
410
422
  textflowkit-ui
411
423
  ```
412
424
 
@@ -477,9 +489,16 @@ browser interface share the job contract without blocking a request.
477
489
 
478
490
  ## Status
479
491
 
480
- **v0.1.12 release.** Adds optional UI-only local Ollama proofreading and native
481
- Windows installer packaging; public EXE distribution remains gated on unresolved
482
- corresponding-source compliance review, with no public installer download link.
492
+ **v0.1.13 release.** Fixes reproduced Whistle speech omissions. Native decode
493
+ inputs are now bounded to 15 seconds (11-second owned cores with up to 2 seconds
494
+ of context per side), short interior speech gaps get a bounded second listen that
495
+ accepts words only between matching timed anchors, and shared-context words are
496
+ reconciled one-to-one before durable resume. Whistle remains the default engine
497
+ with the same pinned model and runtime; fonts remain 0.1.6. Progress schema 2
498
+ stores raw boundary context, so an unfinished partial job from the previous
499
+ 26-second-core plan (schema 1) must be restarted instead of resumed; completed
500
+ records are unchanged. The native Windows installer is rebuilt at v0.1.13 and
501
+ distributed with matching FFmpeg sources, notices, hashes and build instructions.
483
502
  Existing optional live streaming provides a transport-neutral
484
503
  `StreamingSession` Python API, incremental transcript events, and authenticated
485
504
  loopback WebSockets (`/stream` on the developer HTTP API and `/api/stream` on the
@@ -502,6 +521,22 @@ Linux/macOS, and the six other accepted languages were not verified. The public
502
521
  website remains static documentation and serves no streaming endpoint. Local source
503
522
  validation does not establish published-package or exact-commit CI results.
504
523
 
524
+ **v0.1.12 cleanup (historical).** The opt-in local Ollama proofreading path remains
525
+ as introduced in v0.1.12, covering the local browser UI only; it was not changed by
526
+ v0.1.13. It keeps the published 39-segment cleanup proof from v0.1.12 with no
527
+ audio-accuracy claim: that proof records segment/format handling, not recognition
528
+ accuracy.
529
+
530
+ **v0.1.13 Whistle coverage, omission, and resume.** The 15-second bound (11-second
531
+ cores plus up to 2 s context per side) fixes reproduced speech omissions on
532
+ 30-second inputs; the interior speech-gap second listen accepts extra words only
533
+ between matching timed anchors; shared-context words are reconciled one-to-one
534
+ before durable resume so a partial run rejoins without double ownership. Recognized
535
+ language coverage remains the same accepted set, and nothing here recovers speech
536
+ the native recognizer never emits. See
537
+ [docs/verification/whistle-coverage-20261019.md](https://github.com/scottconverse/textflowkit/blob/main/docs/verification/whistle-coverage-20261019.md)
538
+ for the run-by-run coverage, omission, and resume evidence.
539
+
505
540
  **Verification limit.** The local browser interface is covered by an automated
506
541
  suite, and the UI's behavior was proved on a **native Windows** machine in a real
507
542
  browser. No live optional-backend (translation/diarization) run through the UI is
@@ -524,7 +559,7 @@ MCP speech, seven-format exports and completed resume; the v0.1.8 runtime fixes
524
559
  were independently checked through fresh-process CLI restart probes, real SQLite
525
560
  setup-failure tests, and the full Windows test suite. Those checks are not new
526
561
  individual-harness receipts. That is the previous releases' record, not evidence
527
- for v0.1.12.
562
+ for v0.1.13.
528
563
 
529
564
  The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
530
565
  for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
@@ -543,7 +578,7 @@ and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
543
578
  [fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
544
579
  live — that is the v0.1.6 release's evidence, not a receipt for a later release.
545
580
  Everything from here to the end of this section is the v0.1.6 release's
546
- historical record as published: it is not re-verified for v0.1.12, whose separate release evidence is not supplied by these historical paragraphs.
581
+ historical record as published: it is not re-verified for v0.1.13, whose separate release evidence is not supplied by these historical paragraphs.
547
582
  Merged-main CI passed 16/16 on the tagged commit; the published wheel and
548
583
  sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
549
584
  Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
@@ -582,9 +617,9 @@ Issues and PRs welcome. Please read [LEGAL.md](https://github.com/scottconverse/
582
617
  adapter.
583
618
 
584
619
 
585
- ## Optional local AI transcript cleanup (v0.1.12)
620
+ ## Optional local AI transcript cleanup (introduced in v0.1.12)
586
621
 
587
- v0.1.12 adds **opt-in proofreading in the local browser UI only**. After a transcription finishes, choose an
622
+ v0.1.12 adds **opt-in proofreading in the local browser UI only** (introduced in v0.1.12; unchanged in v0.1.13). After a transcription finishes, choose an
588
623
  installed local Ollama model and click **Proofread with local AI**. Cleanup never
589
624
  runs automatically. Ollama and cleanup models are not bundled in the installer.
590
625
  The optional default preference is `qwen3.5:9b` only if already installed; its
@@ -1,6 +1,6 @@
1
1
  # Developer and integration manual
2
2
 
3
- Current release: [v0.1.12](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.12).
3
+ Current release: [v0.1.13](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13).
4
4
  Start with the [user manual](user-manual.md) for everyday use. Harness versions
5
5
  in the compatibility table below identify **historical test sessions**, not
6
6
  the version of TextFlowKit currently published.
@@ -22,9 +22,11 @@ API and WebSockets are ephemeral and bypass durable job submission.
22
22
  HTTP ───────────►└──────────────────────┘
23
23
  ```
24
24
 
25
- ## Windows desktop installer (v0.1.12; public EXE pending)
25
+ ## Windows desktop installer (v0.1.13)
26
26
 
27
- The Windows x86_64 installer packages the existing browser interface for core v0.1.12. The native Windows installer has been built and tested locally. The installer recipe ships in v0.1.12; the EXE remains local-only until unresolved corresponding-source compliance review is cleared. No public installer download link is available. Its bundle includes private embeddable CPython, the UI and HTTP, export, and streaming dependencies, the pinned Whistle model and runtime, and ffmpeg, ffprobe, and Node. It requires no separately installed Python, WSL, or Docker. The Python package remains supported for developers and integrations; Docker remains a separate operator deployment example.
27
+ [Download Windows x64 setup](https://github.com/scottconverse/textflowkit/releases/download/v0.1.13/TextFlowKit-0.1.13-windows-x64-setup.exe) · [Matching sources and notices](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13)
28
+
29
+ The Windows x86_64 installer packages the existing browser interface for core v0.1.13. The Windows installer and its matching FFmpeg source and notice bundles are distributed together through the [v0.1.13 release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13). Its bundle includes private embeddable CPython, the UI and HTTP, export, and streaming dependencies, the pinned Whistle model and runtime, and ffmpeg, ffprobe, and Node. It requires no separately installed Python, WSL, or Docker. The Python package remains supported for developers and integrations; Docker remains a separate operator deployment example.
28
30
 
29
31
  The setup installs per user, adds a Start Menu entry, and offers an
30
32
  optional desktop shortcut. Launching it will start the local server and open the
@@ -551,7 +553,7 @@ observation rather than forwarding the caller's header, and keep
551
553
 
552
554
  ## Live microphone streaming (`/stream`, opt-in)
553
555
 
554
- In v0.1.12, native live streaming supports **Windows x86_64 only**. Other live
556
+ In v0.1.13, native live streaming (introduced in v0.1.11) supports **Windows x86_64 only**. Other live
555
557
  platforms are unsupported; existing standalone defaults and platform support are
556
558
  unchanged. Physical browser microphone capture was not verified. The public site
557
559
  is static documentation and serves no streams. Both local server surfaces can
@@ -562,7 +564,7 @@ exist and a connection is refused before any session is allocated - and it needs
562
564
  `streaming` extra (`websockets`).
563
565
 
564
566
  ```powershell
565
- python -m pip install "textflowkit[streaming]==0.1.12"
567
+ python -m pip install "textflowkit[streaming]==0.1.13"
566
568
  # Native Windows PowerShell:
567
569
  $env:TEXTFLOWKIT_API_TOKEN="choose-a-long-random-token"
568
570
  $env:TEXTFLOWKIT_STREAMING="1"
@@ -602,7 +604,7 @@ supplies FastAPI and uvicorn, and adds no new dependency). It has no public site
602
604
  of its own: it is a local app, not a hosted service.
603
605
 
604
606
  ```bash
605
- python -m pip install 'textflowkit[http,export]==0.1.12'
607
+ python -m pip install 'textflowkit[http,export]==0.1.13'
606
608
  textflowkit-ui # serve on 127.0.0.1 and open a browser
607
609
  textflowkit-ui --no-browser --port 8901
608
610
  ```
@@ -986,7 +988,7 @@ By default the job store is in-memory and bounded (`max_jobs=200`, terminal
986
988
  jobs evicted first). Set `TEXTFLOWKIT_DB` to use the durable SQLite store for
987
989
  restart-safe jobs and checkpoints. The SQLite store assumes one owning process.
988
990
 
989
- ## UI-only proofreading routes (v0.1.12)
991
+ ## UI-only proofreading routes (introduced in v0.1.12)
990
992
 
991
993
  These routes belong to the local UI session gate, not the developer HTTP or MCP
992
994
  API. POST requires the existing `x-textflowkit-ui-capability` header. Host, peer
@@ -1,4 +1,4 @@
1
- # Architecture and job lifecycle — v0.1.12
1
+ # Architecture and job lifecycle — v0.1.13
2
2
 
3
3
  This guide describes how textflowkit is put together and how a job moves through
4
4
  it. It is orientation for maintainers and integrators; it is not a deployment
@@ -26,9 +26,9 @@ a streamed upload, and a capability endpoint. It **ships in the core package as
26
26
  of v0.1.10** and adds no new dependency beyond the `http` extra. It is a local
27
27
  app: the published website is static documentation and never runs the pipeline.
28
28
 
29
- ### Windows desktop installer (v0.1.12; public EXE pending)
29
+ ### Windows desktop installer (v0.1.13)
30
30
 
31
- The Windows x86_64 installer for core v0.1.12 provisions this same browser door without adding a second pipeline or hosted service. The native Windows installer has been built and tested locally. The installer recipe ships in v0.1.12; the EXE remains local-only until unresolved corresponding-source compliance review is cleared. No public installer download link is available. The bundle contains private embeddable CPython, the existing UI and HTTP, export, and streaming dependencies, the pinned Whistle model and runtime, and ffmpeg, ffprobe, and Node. Per-user setup creates a Start Menu entry and offers an optional desktop shortcut. Launching it starts the loopback server and opens the browser at localhost. Normal use needs no administrator rights or global PATH changes; there is no automatic update mechanism.
31
+ The Windows x86_64 installer for core v0.1.13 provisions this same browser door without adding a second pipeline or hosted service. The Windows installer and its matching FFmpeg source and notice bundles are distributed together through the [v0.1.13 release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.13). The bundle contains private embeddable CPython, the existing UI and HTTP, export, and streaming dependencies, the pinned Whistle model and runtime, and ffmpeg, ffprobe, and Node. Per-user setup creates a Start Menu entry and offers an optional desktop shortcut. Launching it starts the loopback server and opens the browser at localhost. Normal use needs no administrator rights or global PATH changes; there is no automatic update mechanism.
32
32
 
33
33
  ```mermaid
34
34
  flowchart LR
@@ -297,7 +297,7 @@ saved transcript for the same URL/options and does **not** prove the remote byte
297
297
  are unchanged.
298
298
 
299
299
  **Whistle block resume.** The Whistle engine's long-audio run emits a
300
- serializable progress snapshot after each 26-second core; the runner persists it as
300
+ serializable progress snapshot after each 11-second core; the runner persists it as
301
301
  a **partial** checkpoint body (no transcript yet). Resuming validates that body
302
302
  against the requested configuration — schema, window policy, duration, the
303
303
  full-content decoded-WAV SHA-256, and the model/binary/language identity — and then
@@ -307,6 +307,21 @@ engine cannot carry partial block progress. This reuses the existing single
307
307
  persistence mechanism and the one-owning-process store model; it adds no second
308
308
  store and no new process-sharing model.
309
309
 
310
+ The v0.1.13 seam-reconciliation policy records progress schema 2, including
311
+ the previous native window's raw tail words. The next core uses one-to-one
312
+ time/text alignment to retain a matched occurrence once even if its two midpoint
313
+ estimates disagree. Collapsed repeated-token ambiguity is preserved, not globally
314
+ deduplicated. Schema-1 partial progress is rejected by the engine and requires a
315
+ fresh run; the checkpoint envelope can still parse historical records. Existing
316
+ completed transcripts are not rewritten. This does not recover speech absent
317
+ from the native model output.
318
+
319
+ The window policy is a 15-second decode ceiling: 11-second owned cores with at most 2 seconds
320
+ of context each side, so no native call exceeds 15 seconds. A short-gap check after a core
321
+ may reframe an interior gap once, but only when both a left and a right timed anchor match,
322
+ and it adds at most two extra native calls per core; long pauses, missing anchors and empty
323
+ retries add no words.
324
+
310
325
  **Ownership.** The reopen of a terminal row for resume is an atomic claim
311
326
  (`JobStore.claim` / `prepare_resume`), pinned to the attempt the caller observed.
312
327
  Two callers racing the same job id cannot both reopen it; one transitions the row
@@ -477,7 +492,7 @@ an isolated environment and inspect a real local job's status and outputs. Live
477
492
  gated providers, ROCm execution, and platform URLs each need separate evidence;
478
493
  see the [release checklist](release-checklist.md) for those boundaries.
479
494
 
480
- ## Local UI cleanup sidecar (v0.1.12)
495
+ ## Local UI cleanup sidecar (introduced in v0.1.12)
481
496
 
482
497
  `ui.cleanup` owns the optional proofreading worker and separate SQLite sidecar
483
498
  next to the effective job database. The UI shell's existing loopback peer/Host,
@@ -503,4 +518,4 @@ three chunks at 2026-10-16 17:39:52 UTC, with four changed segments. The canonic
503
518
  SQLite JSON/source and segment IDs/timestamps matched, and the browser comparison
504
519
  and TXT save were verified. This confirms the local persistence/export path for
505
520
  that run only, not correction accuracy; human audio review remains required.
506
- The optional UI-only cleanup ships with core v0.1.12; models are not bundled.
521
+ The optional UI-only cleanup ships with core v0.1.12 (introduced in v0.1.12; unchanged in v0.1.13); models are not bundled.