textflowkit 0.1.7__tar.gz → 0.1.8__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.
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.github/workflows/publish-pypi.yml +17 -5
- {textflowkit-0.1.7 → textflowkit-0.1.8}/CHANGELOG.md +53 -4
- {textflowkit-0.1.7 → textflowkit-0.1.8}/PKG-INFO +12 -12
- {textflowkit-0.1.7 → textflowkit-0.1.8}/README.md +11 -11
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/adapters.md +10 -9
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/index.html +3 -3
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/install.md +1 -1
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/release-checklist.md +10 -4
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/roadmap.md +39 -20
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/user-manual.md +21 -5
- {textflowkit-0.1.7 → textflowkit-0.1.8}/pyproject.toml +1 -1
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/__init__.py +1 -1
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/cli.py +44 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/pipeline.py +44 -27
- textflowkit-0.1.8/tests/test_cli_owning_recovery.py +300 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_fetch_published_fonts.py +41 -2
- textflowkit-0.1.8/tests/test_mcp_batch_cookie_docs.py +98 -0
- textflowkit-0.1.8/tests/test_pipeline_resume_setup.py +266 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_publish_fonts_wiring.py +54 -4
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_publish_manifest_wiring.py +95 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.dockerignore +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.env.example +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.gitattributes +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.github/dependabot.yml +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.github/workflows/ci.yml +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.gitignore +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/.pre-commit-config.yaml +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/CONTRIBUTING.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/Dockerfile +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/LEGAL.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/LICENSE +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/SECURITY.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/compose.yaml +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/.nojekyll +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/404.html +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/architecture.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/site-deployment.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/docs/sources.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/fetch_published_fonts.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/smoke_installed_wheel.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/smoke_live_youtube.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/verify_readme_release.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/verify_release_ci.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/verify_release_versions.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/scripts/write_release_manifest.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/adapters/__init__.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/adapters/http_server.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/adapters/mcp_server.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/assets/README.md +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/assets/selftest-speech.wav +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/__init__.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/batch.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/bind.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/cancel.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/checkpoint.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/diarize.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/engine.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/executor.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/jobs.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/model.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/paths.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/retrieval.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/runner.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/service.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/sqlite_store.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/startup.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/submission.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/timeutil.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/core/translate.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/__init__.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/_cue_layout.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/_cue_text.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/_rename_excl.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/_rename_noreplace.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/docx.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/markdown.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/pdf.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/srt.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/txt.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/render/vtt.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/sources/__init__.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/sources/acquire.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/sources/detect.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/src/textflowkit/sources/scratch.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/__init__.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/ollama_stub.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_acquire.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_adapters.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_admission_ownership.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_atomic_resume.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_atomic_resume_aba.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_batch.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_batch_item_boundary.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_batch_resume_shared.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_bind.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cancellation_finalization.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_checkpoint.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_checkpoint_single_copy.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cli.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cli_batch_feedback.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cli_resume_batch.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cli_stage_feedback.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cli_stdout_format.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_confined_decoder_boundary.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_confined_indirect_media.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_confined_resume_boundary.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_container_example.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_cue_layout.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_diarize.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_diarize_example_flags.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_diarize_token_docs.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_docx_publication_identity.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_done_output_integrity.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_empty_formats_resume.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_engine_adapters.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_engine_cache.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_engine_faster.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_engine_quiet.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_executor.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_executor_store_failure.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_export.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_export_file_mode.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_export_preflight.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_faster_whisper_docs.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_font_notices.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_http_host_boundary.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_http_trusted_proxy.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_job_progress.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_jobs.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_landing_commands.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_landing_page.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_legal_summary.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_linux_no_hardlink.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_live_smoke_script.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_macos_no_hardlink.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_mcp_http_boundary.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_mcp_protocol_cleanliness.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_mcp_terminal_guidance.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_mcp_tool_descriptions.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_mcp_work_root.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_model.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_partial_output_resume.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_partial_pdf_resume.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_paths.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_pipeline_integrity.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_production_browser_cookies.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_publish_ci_gate.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_publish_workflow_gate.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_readme_layout.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_readme_release_guard.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_release_boundaries.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_release_manifest.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_release_surfaces.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_render.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_retrieval.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_sdist_allowlist.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_service_profile.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_site_not_found.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_sources.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_stage_reuse_resume.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_startup_recovery.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_stdio_protocol.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_submission.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_submission_validation.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_translate.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_translate_completeness.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_verify_release_versions.py +0 -0
- {textflowkit-0.1.7 → textflowkit-0.1.8}/tests/test_windows_no_hardlink.py +0 -0
|
@@ -149,12 +149,24 @@ jobs:
|
|
|
149
149
|
packages-dir: dist/main/
|
|
150
150
|
|
|
151
151
|
publish-github-release:
|
|
152
|
-
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
#
|
|
152
|
+
# The release exists only to advertise a core version that is on PyPI, so it
|
|
153
|
+
# runs exactly on a successful core upload and nothing else. The condition is
|
|
154
|
+
# written out rather than left implicit for the same reason as the core
|
|
155
|
+
# upload above: a status check function must defeat skip propagation. An
|
|
156
|
+
# implicit `success()` here is still subject to it, and on a reused fonts
|
|
157
|
+
# release the workflow-wide propagation from the *skipped* fonts job reaches
|
|
158
|
+
# this job through `publish-main` and its skipped fonts dependency - v0.1.7
|
|
159
|
+
# initially skipped the release even though core reached PyPI, and the
|
|
160
|
+
# recovery published it.
|
|
161
|
+
#
|
|
162
|
+
# `always()` would also defeat the propagation, but it runs the job in a
|
|
163
|
+
# cancelled run too, so it is not used. Only a `success` core upload reaches
|
|
164
|
+
# the release: a failed, skipped or cancelled core upload, a cancelled run,
|
|
165
|
+
# and a build that did not succeed all leave no public release, so the
|
|
166
|
+
# release can never advertise a core version that is not on PyPI.
|
|
157
167
|
needs: publish-main
|
|
168
|
+
if: >-
|
|
169
|
+
${{ !cancelled() && needs.publish-main.result == 'success' }}
|
|
158
170
|
runs-on: ubuntu-latest
|
|
159
171
|
permissions:
|
|
160
172
|
contents: write
|
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.1.8 — 2026-10-02
|
|
4
|
+
|
|
5
|
+
The 2026-10-02 audit-lite repair release. Core version: 0.1.8; unchanged optional fonts: 0.1.6. It carries the four fixes for the post-release audit-lite of 2026-10-01 (findings AL-001 – AL-004). Release artifacts and publication status are recorded on [GitHub Releases](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8). Local source-candidate verification does not establish installed-package or individual harness compatibility.
|
|
6
|
+
|
|
7
|
+
### Engineering fixes
|
|
8
|
+
|
|
9
|
+
- **AL-001 — CLI owning-process startup recovery.** A CLI invocation that was
|
|
10
|
+
interrupted left its PENDING/RUNNING row active; because the CLI submits with
|
|
11
|
+
`background=False` it never started the recovering executor, so a later
|
|
12
|
+
`--resume` read the orphan as "already active" and refused a job whose expensive
|
|
13
|
+
work was saved. Recovery now runs once per owning process at the CLI's
|
|
14
|
+
process/store boundary (`cli.main`), before single or batch resume selection,
|
|
15
|
+
through the shared per-store owner. It is deliberately **not** an unconditional
|
|
16
|
+
reap in every `submit_request(background=False)`: an embedding process can hold
|
|
17
|
+
genuinely live work. A recovery write failure is reported as a clear error with
|
|
18
|
+
a nonzero exit, not a false success or a raw traceback. The documented
|
|
19
|
+
one-owning-process-per-database model is unchanged.
|
|
20
|
+
- **AL-002 — preserve the completed transcript across resume setup failures.** The
|
|
21
|
+
source checkpoint serialized the local transcript (still `None`) before
|
|
22
|
+
hydrating the previous transcript, so a directory/`mkdtemp` failure replaced a
|
|
23
|
+
durable completed transcript with `null` while still listing `transcribe` as
|
|
24
|
+
finished. Reuse is now hydrated and validated **before** any directory setup,
|
|
25
|
+
and a replacement snapshot can no longer drop a still-finished transcript. A
|
|
26
|
+
changed local source is still refused, stages are never falsely marked complete,
|
|
27
|
+
and a healthy retry reuses the recognized work.
|
|
28
|
+
|
|
29
|
+
### Documentation corrections
|
|
30
|
+
|
|
31
|
+
- **AL-003 — MCP batch cookie capability.** The adapter guide said
|
|
32
|
+
`submit_batch_media` has no `cookies_from_browser` parameter. It does: the tool
|
|
33
|
+
accepts one shared value and forwards it to every request, and the production
|
|
34
|
+
refusal is enforced by the same shared guard as the other surfaces. The matrix
|
|
35
|
+
and paragraph (and the historical DOC-003 changelog text) were corrected, with a
|
|
36
|
+
schema-consistency regression test that reads the real SDK-generated tool schema.
|
|
37
|
+
- **AL-004 — roadmap evidence.** The POSIX file-mode and fonts-reuse follow-ups
|
|
38
|
+
are marked done against their exact receipts: current-main CI run 36961982098
|
|
39
|
+
(12 OS/Python test jobs + three installed-wheel jobs + Ruff) verifies POSIX modes
|
|
40
|
+
on Linux/macOS, and release-workflow run 36961162844 built the reused 0.1.6
|
|
41
|
+
fonts, skipped the fonts upload, and published core to PyPI. The GitHub-release
|
|
42
|
+
job skip, its manual recovery, and the PR #23 condition repair are recorded
|
|
43
|
+
without claiming the original workflow was all green or the repaired automatic
|
|
44
|
+
path has been live-tested. The v0.1.7 history and version are preserved.
|
|
45
|
+
|
|
3
46
|
## v0.1.7 — 2026-10-01
|
|
4
47
|
|
|
5
48
|
The 2026-10-01 audit repair release. Core version: 0.1.7; unchanged optional fonts: 0.1.6. Release artifacts and publication status are recorded on [GitHub Releases](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.7). Local source-candidate verification does not establish installed-package or individual harness compatibility.
|
|
@@ -63,12 +106,17 @@ The 2026-10-01 audit repair release. Core version: 0.1.7; unchanged optional fon
|
|
|
63
106
|
overlapping rather than clipped.
|
|
64
107
|
- **DOC-003** — "same options" is replaced with a per-surface parameter matrix
|
|
65
108
|
(HTTP `formats` array vs MCP comma-separated string; HTTP batch options are
|
|
66
|
-
**per item**, MCP batch options are shared and
|
|
67
|
-
|
|
68
|
-
means admission, not completion, with per-item indexed errors. MCP
|
|
109
|
+
**per item**, MCP batch options are shared), and the batch contract now states
|
|
110
|
+
that 202 means admission, not completion, with per-item indexed errors. MCP
|
|
69
111
|
`sources` is documented as a list of **strings**: a non-string entry (including
|
|
70
112
|
a nested object or a number) is that entry's own error, not a whole-call
|
|
71
113
|
refusal, while a string remains valid.
|
|
114
|
+
*Correction (2026-10-01, audit-lite AL-003):* the v0.1.7 text of this entry
|
|
115
|
+
claimed the MCP batch tool exposes **no** `cookies_from_browser` parameter.
|
|
116
|
+
That was wrong. `submit_batch_media` accepts `cookies_from_browser` and
|
|
117
|
+
forwards the one shared value to every request it builds; the production
|
|
118
|
+
refusal is enforced by the same shared guard as the other surfaces. The
|
|
119
|
+
adapter guide was corrected to match the generated tool schema.
|
|
72
120
|
- **DOC-004** — a full production settings reference (names, defaults, units,
|
|
73
121
|
required fields) is added to the adapter guide, and the production refusal of
|
|
74
122
|
browser-cookie submissions is stated across the adapter guide, the sources
|
|
@@ -96,5 +144,6 @@ for the complete list and completion criteria. The current repair goal still
|
|
|
96
144
|
covers decoder confinement, job lifecycle, publication/resume, translation and
|
|
97
145
|
batch correctness, major terminal guidance/documentation, and its final gate.
|
|
98
146
|
|
|
99
|
-
This changelog starts with the v0.1.
|
|
147
|
+
This changelog starts with the v0.1.8 release notes, followed by the v0.1.7
|
|
148
|
+
release notes; published historical
|
|
100
149
|
release notes remain on [GitHub Releases](https://github.com/scottconverse/textflowkit/releases).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: textflowkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
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
|
|
@@ -64,7 +64,7 @@ Cross-platform media transcription toolkit. **One core, one CLI, thin adapters.*
|
|
|
64
64
|
[GitHub releases](https://github.com/scottconverse/textflowkit/releases) ·
|
|
65
65
|
[User manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md)
|
|
66
66
|
|
|
67
|
-
**Current release: [v0.1.
|
|
67
|
+
**Current release: [v0.1.8](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8).**
|
|
68
68
|
|
|
69
69
|
The [static site deployment](https://github.com/scottconverse/textflowkit/blob/main/docs/site-deployment.md) is hosted on Cloudflare
|
|
70
70
|
Pages. GitHub remains the source and CI host; the website does not run the
|
|
@@ -338,14 +338,14 @@ web frontend share the job contract without blocking a request.
|
|
|
338
338
|
|
|
339
339
|
## Status
|
|
340
340
|
|
|
341
|
-
**v0.1.
|
|
342
|
-
coverage. This release
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
341
|
+
**v0.1.8 release.** Core, CLI, MCP, and HTTP have automated
|
|
342
|
+
coverage. This release carries the four fixes for the 2026-10-01 post-release
|
|
343
|
+
audit-lite (findings AL-001 – AL-004): CLI owning-process startup recovery so an
|
|
344
|
+
interrupted run's saved work can be resumed instead of being refused as
|
|
345
|
+
"already active", preservation of the completed transcript across resume setup
|
|
346
|
+
failures, a correction to the MCP batch cookie capability, and corrected roadmap
|
|
347
|
+
evidence receipts. It builds on the v0.1.7 audit repair set and the v0.1.6
|
|
348
|
+
review repairs that precede it. The preceding v0.1.7 source candidate was verified with real CLI, HTTP and MCP speech, seven-format exports and completed resume. The v0.1.8 runtime fixes were independently checked through fresh-process CLI restart probes, real SQLite setup-failure tests, and the full Windows test suite; those checks are not new individual-harness receipts. Release publication uses the tag workflow, which requires successful exact-commit main CI before PyPI uploads and creates the public GitHub release only afterward. Check the linked release for artifacts and workflow status; local source verification is not a fresh PyPI-install or individual-harness receipt.
|
|
349
349
|
|
|
350
350
|
The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
|
|
351
351
|
for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
|
|
@@ -362,9 +362,9 @@ The v0.1.6 release is public: the
|
|
|
362
362
|
[v0.1.6 GitHub release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.6)
|
|
363
363
|
and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
|
|
364
364
|
[fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
|
|
365
|
-
live — that is the previous release's evidence, not a receipt for v0.1.
|
|
365
|
+
live — that is the previous release's evidence, not a receipt for v0.1.8.
|
|
366
366
|
Everything from here to the end of this section is the v0.1.6 release's
|
|
367
|
-
historical record as published: it is not re-verified for v0.1.
|
|
367
|
+
historical record as published: it is not re-verified for v0.1.8, whose separate release evidence is not supplied by these historical paragraphs.
|
|
368
368
|
Merged-main CI passed 16/16 on the tagged commit; the published wheel and
|
|
369
369
|
sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
|
|
370
370
|
Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
|
|
@@ -7,7 +7,7 @@ Cross-platform media transcription toolkit. **One core, one CLI, thin adapters.*
|
|
|
7
7
|
[GitHub releases](https://github.com/scottconverse/textflowkit/releases) ·
|
|
8
8
|
[User manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md)
|
|
9
9
|
|
|
10
|
-
**Current release: [v0.1.
|
|
10
|
+
**Current release: [v0.1.8](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8).**
|
|
11
11
|
|
|
12
12
|
The [static site deployment](https://github.com/scottconverse/textflowkit/blob/main/docs/site-deployment.md) is hosted on Cloudflare
|
|
13
13
|
Pages. GitHub remains the source and CI host; the website does not run the
|
|
@@ -281,14 +281,14 @@ web frontend share the job contract without blocking a request.
|
|
|
281
281
|
|
|
282
282
|
## Status
|
|
283
283
|
|
|
284
|
-
**v0.1.
|
|
285
|
-
coverage. This release
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
284
|
+
**v0.1.8 release.** Core, CLI, MCP, and HTTP have automated
|
|
285
|
+
coverage. This release carries the four fixes for the 2026-10-01 post-release
|
|
286
|
+
audit-lite (findings AL-001 – AL-004): CLI owning-process startup recovery so an
|
|
287
|
+
interrupted run's saved work can be resumed instead of being refused as
|
|
288
|
+
"already active", preservation of the completed transcript across resume setup
|
|
289
|
+
failures, a correction to the MCP batch cookie capability, and corrected roadmap
|
|
290
|
+
evidence receipts. It builds on the v0.1.7 audit repair set and the v0.1.6
|
|
291
|
+
review repairs that precede it. The preceding v0.1.7 source candidate was verified with real CLI, HTTP and MCP speech, seven-format exports and completed resume. The v0.1.8 runtime fixes were independently checked through fresh-process CLI restart probes, real SQLite setup-failure tests, and the full Windows test suite; those checks are not new individual-harness receipts. Release publication uses the tag workflow, which requires successful exact-commit main CI before PyPI uploads and creates the public GitHub release only afterward. Check the linked release for artifacts and workflow status; local source verification is not a fresh PyPI-install or individual-harness receipt.
|
|
292
292
|
|
|
293
293
|
The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
|
|
294
294
|
for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
|
|
@@ -305,9 +305,9 @@ The v0.1.6 release is public: the
|
|
|
305
305
|
[v0.1.6 GitHub release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.6)
|
|
306
306
|
and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
|
|
307
307
|
[fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
|
|
308
|
-
live — that is the previous release's evidence, not a receipt for v0.1.
|
|
308
|
+
live — that is the previous release's evidence, not a receipt for v0.1.8.
|
|
309
309
|
Everything from here to the end of this section is the v0.1.6 release's
|
|
310
|
-
historical record as published: it is not re-verified for v0.1.
|
|
310
|
+
historical record as published: it is not re-verified for v0.1.8, whose separate release evidence is not supplied by these historical paragraphs.
|
|
311
311
|
Merged-main CI passed 16/16 on the tagged commit; the published wheel and
|
|
312
312
|
sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
|
|
313
313
|
Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Adapters and integration
|
|
2
2
|
|
|
3
|
-
Current published release: [v0.1.
|
|
3
|
+
Current published release: [v0.1.8](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8).
|
|
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.
|
|
@@ -105,16 +105,17 @@ HTTP batch item by hand.
|
|
|
105
105
|
| Input | `source: string`, required | `source: string`, required | `sources: list[string]`, required |
|
|
106
106
|
| `formats` | **list** of strings (e.g. `["json","srt"]`); default `json`,`srt`,`txt` | **comma-separated string** `"json,srt,txt"` | **comma-separated string** |
|
|
107
107
|
| `language`, `output_dir`, `model`, `device`, `engine`, `diarize`, `translate_to` | same fields on the single item; on HTTP batch each item carries its **own** copy, applied only to that item | same | shared across all sources |
|
|
108
|
-
| `cookies_from_browser` | accepted on the HTTP single `POST /jobs` and on each HTTP batch item | accepted |
|
|
108
|
+
| `cookies_from_browser` | accepted on the HTTP single `POST /jobs` and on each HTTP batch item | accepted | accepted (shared across all sources) |
|
|
109
109
|
| Resume | batch wrapper `resume: bool`; single `POST /jobs/{id}/resume` | `resume_job` tool | `resume: bool` |
|
|
110
110
|
|
|
111
|
-
The
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
The `cookies_from_browser` value is accepted on every surface. On `transcribe_media`
|
|
112
|
+
and `submit_batch_media` it is one shared value applied to each request the call
|
|
113
|
+
builds; on HTTP it is **per item**: each entry of `jobs` is a full
|
|
114
|
+
`TranscribeRequest`, so two items can name different models or languages. The MCP
|
|
115
|
+
batch tool instead takes its options **once** and applies them to every source.
|
|
116
|
+
Whichever surface supplies it, a cookie request is refused by the shared
|
|
117
|
+
production guard when `TEXTFLOWKIT_PROFILE=production` (see the production
|
|
118
|
+
settings reference below); it is honoured only in the developer/owner profile.
|
|
118
119
|
|
|
119
120
|
`output_dir` omitted writes no rendered files, but a durable transcript is still
|
|
120
121
|
kept: with `TEXTFLOWKIT_DB` set the transcript survives the process, so "no
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
<main id="main">
|
|
189
189
|
<div class="wrap hero">
|
|
190
190
|
<div>
|
|
191
|
-
<span class="eyebrow">Open source · Apache 2.0 · v0.1.
|
|
191
|
+
<span class="eyebrow">Open source · Apache 2.0 · v0.1.8</span>
|
|
192
192
|
<h1>Media in.<br><em>Useful text</em> out.</h1>
|
|
193
193
|
<p class="lead">Transcribe video and audio into timestamped, searchable text. One shared core for your command line, AI harness, and application.</p>
|
|
194
194
|
<div class="actions">
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
<a class="button secondary" href="https://pypi.org/project/textflowkit/">Install from PyPI <span aria-hidden="true"> ↗</span></a>
|
|
197
197
|
</div>
|
|
198
198
|
<p class="micro">Self-hosted toolkit · Native Windows, macOS, Linux · No account required</p>
|
|
199
|
-
<p class="micro">Latest verified release: <a href="https://github.com/scottconverse/textflowkit/releases/tag/v0.1.
|
|
199
|
+
<p class="micro">Latest verified release: <a href="https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8">v0.1.8</a> · <a href="https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md">User manual</a></p>
|
|
200
200
|
</div>
|
|
201
201
|
<div class="terminal" aria-label="Example transcription command and output">
|
|
202
202
|
<div class="terminal-top"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="terminal-label">textflowkit / terminal</span></div>
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
<li>Find the right setup for AMD ROCm in the install guide before installing dependencies.</li>
|
|
277
277
|
</ul>
|
|
278
278
|
<a class="button secondary" href="https://github.com/scottconverse/textflowkit/blob/main/docs/install.md">Read install guide ↗</a>
|
|
279
|
-
<p class="note">New here? Follow the <a href="https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md">v0.1.
|
|
279
|
+
<p class="note">New here? Follow the <a href="https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md">v0.1.8 user manual</a> for CLI, MCP, HTTP, export, and troubleshooting examples.</p>
|
|
280
280
|
</div>
|
|
281
281
|
<div>
|
|
282
282
|
<pre class="codebox"><span class="prompt">$ </span>python -m pip install "textflowkit[mcp,http]"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Install notes
|
|
2
2
|
|
|
3
|
-
Current release: [v0.1.
|
|
3
|
+
Current release: [v0.1.8](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8).
|
|
4
4
|
Use `textflowkit --version` to confirm the installed version. For everyday
|
|
5
5
|
commands and outputs, start with the [user manual](user-manual.md).
|
|
6
6
|
|
|
@@ -75,7 +75,7 @@ receipt. It does not upload cookies, media, or transcripts to GitHub.
|
|
|
75
75
|
## PyPI publication
|
|
76
76
|
|
|
77
77
|
After merged-main CI and the local release checks pass, push an annotated final
|
|
78
|
-
version tag (for example `v0.1.
|
|
78
|
+
version tag (for example `v0.1.8` for a future release) on that verified
|
|
79
79
|
`main` commit. Do **not**
|
|
80
80
|
create or publish a GitHub release manually. The tag push triggers
|
|
81
81
|
[`publish-pypi.yml`](../.github/workflows/publish-pypi.yml). It verifies the
|
|
@@ -147,9 +147,15 @@ the version declared in `packages/textflowkit-fonts/pyproject.toml` and asks
|
|
|
147
147
|
and the resolution reported a reuse, and it refuses to continue for a failed
|
|
148
148
|
or cancelled fonts upload, a failed build, a cancelled run, or a skipped
|
|
149
149
|
fonts job that was not a reuse. So a core release can never be published
|
|
150
|
-
against a fonts version that is not on PyPI. The GitHub release job
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
against a fonts version that is not on PyPI. The GitHub release job also
|
|
151
|
+
carries its own condition, for the same reason: the skip propagation from the
|
|
152
|
+
reused fonts job reaches it through `publish-main` and its skipped fonts
|
|
153
|
+
dependency, so an implicit `success()` would suppress the release on the reuse
|
|
154
|
+
path — v0.1.7 initially skipped the release even though core reached PyPI, and
|
|
155
|
+
the recovery published it. It runs only on a `success` core upload, using a
|
|
156
|
+
status check function so the reuse path is not suppressed, while a failed,
|
|
157
|
+
skipped or cancelled core upload or a cancelled run still leaves the release
|
|
158
|
+
uncreated.
|
|
153
159
|
- **Anything else stops the release before it builds or uploads.** A transient
|
|
154
160
|
or 5xx answer, a response that is not JSON or has no file list, a release whose
|
|
155
161
|
files are not exactly one wheel and one sdist for that version (a partial
|
|
@@ -105,27 +105,46 @@ matched, and a fresh install passed self-test, transcription, and PDF export.
|
|
|
105
105
|
identity, per-request completed-stage reuse, an aggregate export preflight,
|
|
106
106
|
translation completeness and per-item batch validation, live terminal
|
|
107
107
|
feedback, and the DOC-001 – DOC-006 documentation corrections. Implementation verification is complete; publication and its exact-commit CI are tracked by the [v0.1.7 release workflow](https://github.com/scottconverse/textflowkit/actions/workflows/publish-pypi.yml). Fonts remain 0.1.6 and are reused without republishing. Historical release evidence above remains scoped to its stated version.
|
|
108
|
-
- [
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
108
|
+
- [x] Ship v0.1.8 review follow-ups: the 2026-10-01 post-release audit-lite
|
|
109
|
+
follow-ups (AL-001 – AL-004). AL-001 gives the CLI owning-process startup
|
|
110
|
+
recovery at its process/store boundary, so an interrupted job's saved work can
|
|
111
|
+
be resumed instead of being refused as "already active"; AL-002 validates and
|
|
112
|
+
rehydrates reusable work **before** publishing a checkpoint, so a resume setup
|
|
113
|
+
failure can no longer replace a durable completed transcript with an empty one;
|
|
114
|
+
AL-003 corrects the MCP batch cookie-capability documentation and its
|
|
115
|
+
schema-consistency test; AL-004 corrects roadmap evidence receipts. These are
|
|
116
|
+
the four fixes recorded for [v0.1.8](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8),
|
|
117
|
+
whose publication and exact-commit CI are tracked by the [release workflow](https://github.com/scottconverse/textflowkit/actions/workflows/publish-pypi.yml).
|
|
118
|
+
Fonts remain 0.1.6 and are reused without republishing. This entry does not
|
|
119
|
+
restate or rewrite the historical v0.1.7 achievements below, whose evidence
|
|
120
|
+
remains scoped to its stated version.
|
|
121
|
+
- [x] Normalize exported file permissions on POSIX to respect the process
|
|
122
|
+
umask. The mode is measured and applied before publication, with regression
|
|
123
|
+
tests for it. The POSIX behaviour is now verified on live POSIX hosts: the
|
|
124
|
+
Linux/macOS jobs of the current-main [CI run 36961982098](https://github.com/scottconverse/textflowkit/actions/runs/36961982098)
|
|
125
|
+
run the full suite (12 OS/Python test jobs plus three installed-wheel jobs
|
|
126
|
+
and Ruff) on the audited commit, and `tests/test_export_file_mode.py` carries
|
|
127
|
+
the six umask/publication cases (Windows-only excluded). This is no longer
|
|
128
|
+
unverified.
|
|
129
|
+
- [x] Decouple the fonts package's version from core releases so unchanged font
|
|
130
|
+
wheels are not rebuilt/uploaded every patch. The publish workflow resolves the
|
|
131
|
+
fonts version against PyPI before it builds: an unpublished version is built
|
|
132
|
+
and uploaded, and a published one is fetched from PyPI with its recorded
|
|
133
|
+
SHA-256 and size verified and is never rebuilt, re-uploaded, or hidden behind
|
|
134
|
+
`skip-existing`. A changed fonts package must carry a new version, and the
|
|
135
|
+
fonts upload and the core upload are conditional so the reuse path still
|
|
136
|
+
publishes the core release. See the
|
|
123
137
|
[release checklist](release-checklist.md#the-fonts-version-contract-issue-15).
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
The reuse path is now exercised by a live release: the v0.1.7 build
|
|
139
|
+
([release workflow run 36961162844](https://github.com/scottconverse/textflowkit/actions/runs/36961162844))
|
|
140
|
+
resolved the unchanged 0.1.6 fonts for reuse, **skipped** the fonts upload,
|
|
141
|
+
and published core to PyPI successfully. One nuance stays recorded rather than
|
|
142
|
+
papered over: that same run's GitHub-release job was skipped by a transitive
|
|
143
|
+
condition, and GitHub publication was recovered manually from the original
|
|
144
|
+
verified artifacts; PR #23 repaired the condition on main, so the repaired
|
|
145
|
+
future automatic GitHub-release path has deterministic tests, **not** a second
|
|
146
|
+
live tag run. This entry does not claim the original workflow was all green, nor
|
|
147
|
+
that the repaired publication path has been live-tested.
|
|
129
148
|
|
|
130
149
|
The 13 listed media platforms are recognised through `yt-dlp`; **only YouTube**
|
|
131
150
|
has an opt-in [live URL transcription release gate](release-checklist.md), not
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# TextFlowKit user manual — v0.1.
|
|
1
|
+
# TextFlowKit user manual — v0.1.8
|
|
2
2
|
|
|
3
3
|
TextFlowKit turns a local audio/video file or a supported media URL into a
|
|
4
4
|
timestamped transcript. It is a **self-hosted developer tool**, not a hosted
|
|
@@ -12,7 +12,7 @@ Install Python 3.10 or later and `ffmpeg`/`ffprobe` on `PATH`. For a standard
|
|
|
12
12
|
CPU setup, install the current release from PyPI:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
python -m pip install 'textflowkit[export,mcp,http]==0.1.
|
|
15
|
+
python -m pip install 'textflowkit[export,mcp,http]==0.1.8'
|
|
16
16
|
textflowkit --version
|
|
17
17
|
textflowkit doctor
|
|
18
18
|
textflowkit selftest
|
|
@@ -105,6 +105,22 @@ match. Without `TEXTFLOWKIT_DB`, jobs are in memory and cannot survive a
|
|
|
105
105
|
process restart. The job executor bounds concurrent work; consult
|
|
106
106
|
[adapter and production settings](adapters.md) before running a service.
|
|
107
107
|
|
|
108
|
+
The durable store assumes **one owning process per database**. A CLI invocation
|
|
109
|
+
owns its store for the length of the command, so before it selects work to
|
|
110
|
+
resume it recovers rows left `pending` or `running` by a process that died:
|
|
111
|
+
those orphans have no worker, and without recovery a `--resume` reads them as
|
|
112
|
+
"already active" and refuses a job whose expensive work was saved. Run only one
|
|
113
|
+
process against a given `TEXTFLOWKIT_DB`; a second one would recover the first
|
|
114
|
+
one's live jobs. A recovery write that fails stops the command with an error
|
|
115
|
+
rather than continuing.
|
|
116
|
+
|
|
117
|
+
Resume preserves the completed transcript. Reusable work is validated and
|
|
118
|
+
rehydrated **before** any working-directory setup, so a setup failure (an
|
|
119
|
+
unusable work directory, a scratch directory that cannot be created) leaves the
|
|
120
|
+
previous durable checkpoint — including its finished transcript — intact for a
|
|
121
|
+
later retry instead of replacing it with an empty one. A changed local source is
|
|
122
|
+
still refused, and a stage is only ever listed as finished when it really is.
|
|
123
|
+
|
|
108
124
|
## 4. Export or inspect a saved transcript
|
|
109
125
|
|
|
110
126
|
```bash
|
|
@@ -244,11 +260,11 @@ See the [adapter guide](adapters.md#input-paths-unconfined-by-default) and
|
|
|
244
260
|
|
|
245
261
|
## 7. Release and help
|
|
246
262
|
|
|
247
|
-
- [v0.1.
|
|
248
|
-
- [Core package 0.1.
|
|
263
|
+
- [v0.1.8 GitHub release](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.8)
|
|
264
|
+
- [Core package 0.1.8 on PyPI](https://pypi.org/project/textflowkit/0.1.8/) and [unchanged optional font package 0.1.6](https://pypi.org/project/textflowkit-fonts/0.1.6/)
|
|
249
265
|
- [Release verification procedure](release-checklist.md), [security policy](../SECURITY.md), and [issues](https://github.com/scottconverse/textflowkit/issues)
|
|
250
266
|
|
|
251
|
-
|
|
267
|
+
The preceding v0.1.7 source-candidate verification covered real CLI/HTTP/MCP speech, exports and completed resume. The v0.1.8 runtime fixes were independently checked through fresh-process CLI restart probes, real SQLite setup-failure tests, and the full Windows test suite. See release artifacts and workflow results for publication evidence. The following paragraphs retain historical evidence for v0.1.6 and v0.1.5; they do not establish v0.1.8 installed-package or harness verification.
|
|
252
268
|
|
|
253
269
|
The v0.1.6 release passed the Windows/Linux/macOS CI matrix on the tagged
|
|
254
270
|
commit, and a fresh Windows Python 3.12 install of
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "textflowkit"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.8"
|
|
8
8
|
description = "Cross-platform media transcription toolkit: URL or file in, timestamped transcripts and subtitle files out."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
from textflowkit.core.model import Segment, Transcript, WordTiming
|
|
4
4
|
from textflowkit.core.pipeline import PipelineError, transcribe
|
|
5
5
|
|
|
6
|
-
__version__ = "0.1.
|
|
6
|
+
__version__ = "0.1.8"
|
|
7
7
|
|
|
8
8
|
__all__ = ["PipelineError", "Segment", "Transcript", "WordTiming", "__version__", "transcribe"]
|
|
@@ -18,6 +18,7 @@ from textflowkit.core.model import Transcript
|
|
|
18
18
|
from textflowkit.core.paths import default_input_root, output_root
|
|
19
19
|
from textflowkit.core.pipeline import TranscribeResult
|
|
20
20
|
from textflowkit.core.runner import transcript_for
|
|
21
|
+
from textflowkit.core.startup import StartupRecoveryError, recover_startup
|
|
21
22
|
from textflowkit.core.submission import SubmissionRequest, submit_request
|
|
22
23
|
from textflowkit.render import (
|
|
23
24
|
BINARY_FORMATS,
|
|
@@ -170,6 +171,38 @@ def _store_is_durable() -> bool:
|
|
|
170
171
|
return bool(os.environ.get("TEXTFLOWKIT_DB"))
|
|
171
172
|
|
|
172
173
|
|
|
174
|
+
def _recover_owned_store() -> int:
|
|
175
|
+
"""Recover orphaned rows once for the store this CLI process owns.
|
|
176
|
+
|
|
177
|
+
A CLI invocation owns its store for the duration of the command: the jobs
|
|
178
|
+
this process runs are created after this call, so any PENDING/RUNNING row
|
|
179
|
+
already in a durable store is an orphan from a process that died - it has no
|
|
180
|
+
worker, and without recovery a ``--resume`` reads it as "already active" and
|
|
181
|
+
refuses to reuse the saved work (audit finding AL-001).
|
|
182
|
+
|
|
183
|
+
This belongs at the CLI's process/store ownership boundary, *not* inside
|
|
184
|
+
``submit_request(background=False)``: an embedding process can hold
|
|
185
|
+
genuinely live work, so an unconditional reap there would fail rows it does
|
|
186
|
+
not own. Recovery is delegated to the shared per-store owner, so a single
|
|
187
|
+
CLI process reaps exactly once even if both the transcribe and batch paths
|
|
188
|
+
were to ask. It runs only against a durable store; an in-memory store is
|
|
189
|
+
fresh per process and has no orphans to recover.
|
|
190
|
+
|
|
191
|
+
Returns 0 when recovery ran or was unnecessary, and 1 (with a clear message
|
|
192
|
+
on stderr, no traceback) when the store rejected the recovery write: the
|
|
193
|
+
command must fail rather than proceed over a store whose orphans still read
|
|
194
|
+
``running``.
|
|
195
|
+
"""
|
|
196
|
+
if not _store_is_durable():
|
|
197
|
+
return 0
|
|
198
|
+
try:
|
|
199
|
+
recover_startup(get_default_store())
|
|
200
|
+
except StartupRecoveryError as exc:
|
|
201
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
202
|
+
return 1
|
|
203
|
+
return 0
|
|
204
|
+
|
|
205
|
+
|
|
173
206
|
def _preflight_engine(name: str) -> str | None:
|
|
174
207
|
"""Reject an unusable ``--engine`` before any work is submitted.
|
|
175
208
|
|
|
@@ -569,8 +602,19 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
569
602
|
parser = _build_parser()
|
|
570
603
|
args = parser.parse_args(argv)
|
|
571
604
|
if args.command == "transcribe":
|
|
605
|
+
# Recover the durable store this process owns before resume selection,
|
|
606
|
+
# so an interrupted job from a dead process is reusable rather than
|
|
607
|
+
# refused as "already active". Only the commands that submit and resume
|
|
608
|
+
# work need this; `export`, `sources`, `doctor` and `selftest` neither
|
|
609
|
+
# own nor select jobs and are left with their existing side effects.
|
|
610
|
+
recovery = _recover_owned_store()
|
|
611
|
+
if recovery != 0:
|
|
612
|
+
return recovery
|
|
572
613
|
return _cmd_transcribe(args)
|
|
573
614
|
if args.command == "batch":
|
|
615
|
+
recovery = _recover_owned_store()
|
|
616
|
+
if recovery != 0:
|
|
617
|
+
return recovery
|
|
574
618
|
return _cmd_batch(args)
|
|
575
619
|
if args.command == "export":
|
|
576
620
|
return _cmd_export(args)
|