utterplan 0.6.3__tar.gz → 0.6.5__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.
- utterplan-0.6.5/MANIFEST.in +2 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/PKG-INFO +72 -2
- {utterplan-0.6.3 → utterplan-0.6.5}/README.md +71 -1
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/architecture.md +53 -11
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/changelog.md +26 -1
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/cli.md +44 -2
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/index.md +2 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/python-api.md +23 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/ssmdbook.md +2 -0
- utterplan-0.6.5/docs/ssmdoc.md +80 -0
- utterplan-0.6.5/tests/fixtures/ssmdoc-v1/story.ssmdoc/document.ssmd.md +6 -0
- utterplan-0.6.5/tests/fixtures/ssmdoc-v1/story.ssmdoc/manifest.json +21 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_book_api.py +26 -1
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_cli.py +52 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_cli_render_book.py +60 -1
- utterplan-0.6.5/tests/test_cli_render_document.py +354 -0
- utterplan-0.6.5/tests/test_cli_ssmdoc.py +298 -0
- utterplan-0.6.5/tests/test_document_render.py +119 -0
- utterplan-0.6.5/tests/test_document_workspace.py +255 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_import_boundaries.py +1 -1
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderplan_export.py +133 -0
- utterplan-0.6.5/tests/test_role_coverage.py +126 -0
- utterplan-0.6.5/tests/test_source_input.py +104 -0
- utterplan-0.6.5/tests/test_ssmdoc.py +297 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/__init__.py +36 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/_version.py +3 -3
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/book.py +34 -28
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/cli.py +232 -60
- utterplan-0.6.5/utterplan/document_workspace.py +460 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/renderplan_export.py +3 -2
- utterplan-0.6.5/utterplan/renderplan_workspace.py +23 -0
- utterplan-0.6.5/utterplan/role_coverage.py +99 -0
- utterplan-0.6.5/utterplan/source_input.py +123 -0
- utterplan-0.6.5/utterplan/ssmdoc.py +212 -0
- utterplan-0.6.5/utterplan/workspace_paths.py +27 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/PKG-INFO +72 -2
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/SOURCES.txt +16 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/scm_file_list.json +41 -1
- utterplan-0.6.5/utterplan.egg-info/scm_version.json +8 -0
- utterplan-0.6.3/MANIFEST.in +0 -1
- utterplan-0.6.3/utterplan.egg-info/scm_version.json +0 -8
- {utterplan-0.6.3 → utterplan-0.6.5}/.codecrate.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/.github/workflows/codecov.yml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/.github/workflows/pre-commit.yml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/.github/workflows/python-publish.yml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/.github/workflows/tests.yml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/.gitignore +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/.pre-commit-config.yaml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/AGENTS.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/LICENSE +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/NOTICE +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/Makefile +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/conf.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/consumer-guide.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/coordinate-spaces.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/debugging.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/format.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/getting-started.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/make.bat +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/phase-a-completion.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/pykokoro-integration.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/docs/requirements.txt +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/examples/basic.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/examples/chapter.ssmd +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/examples/compile_file.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/examples/inspect_plan.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/examples/multilingual.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/examples/ssmd_example.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/pyproject.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/setup.cfg +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/spec/schemas/v1.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/spec/schemas/v2.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/spec/schemas/v3.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/spec/schemas/v4.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/spec/utterplan.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/compiler_helpers.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/fixtures/canonical_consumer_contract.expected.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/fixtures/canonical_consumer_contract.ssmd +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/fixtures/ssmd_09_comprehensive.ssmd +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/basic_en.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/directives.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/markers.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/multilingual.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/parenthetical.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/spokenform_offsets.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/ssmd_09_comprehensive.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/golden/ssmd_breaks.utterplan.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/cases.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/basic_en.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/directives.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/markers.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/multilingual.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/parenthetical.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/spokenform_offsets.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/ssmd_09_comprehensive.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/fixtures/v4/ssmd_breaks.utterplan.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/goldens/multilingual_preparation.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/goldens/spokenform_numbers.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/goldens/ssmd_break.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/goldens/ssmd_language_detection.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/goldens/ssmd_marker.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/goldens/ssmd_pronunciation.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/test_legacy_json_import.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/migration/test_semantic_migration_regressions.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/README.md +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/basic.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/directives.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/markers.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/multilingual.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/parenthetical.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/spokenform_offsets.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v1/ssmd_breaks.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v2/directives.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v3/multilingual.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v3/ssmd_09_comprehensive.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/schema_history/v5/canonical_consumer_contract.toml +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_atomic_io.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_batch.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_book_replan.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_boundaries.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_cli_batch.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_cli_replan_book.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_cli_ssmdbook.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_compiler.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_consumer_contract.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_consumer_readiness.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_coordinates.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_dependency_architecture.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_directives.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_explain.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_fake_renderer.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_flow_compilation.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_format.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_golden.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_identity_units.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_language.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_linguistics.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_migration_framework.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_migration_v3_to_v4.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_migration_v4_to_v5.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_pauses.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_planner.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_preparation.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_preview.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_progress.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_public_identity.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderability.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderability_repair.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderplan_batch.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderplan_dependency_contract.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderplan_replan.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_renderplan_v7_contract.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_replacement_provenance.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_schema_history.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_schema_registry.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_schema_strict.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_schema_v6_source.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_schema_v7.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_segment_topology.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_segmentation_adapter.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_segmentation_recovery.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_semantic_boundaries.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_sentence_topology.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_ssmd_09_parser.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_ssmd_substitution_preparation.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_ssmdbook.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_token_topology.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_toml_format.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_ttsready_preparation_adapter.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/tests/test_version.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/__main__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/atomic_io.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/attempt_serialization.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/attempts.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/batch.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/book_replan.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/boundaries.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/codecs/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/codecs/v4_toml.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/codecs/v5_toml.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/codecs/v6_toml.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/codecs/v7_toml.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/compiler.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/config.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/diagnostics.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/directives.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/exceptions.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/explain.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/flow_projection.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/format.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/hashing.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/language.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/linguistics.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migration.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/registry.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/v1_to_v2.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/v2_to_v3.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/v3_to_v4.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/v4_to_v5.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/v5_to_v6.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/migrations/v6_to_v7.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/model.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/parsers.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/pauses.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/planner.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/preparation.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/preview.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/progress.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/py.typed +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/renderability.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/renderplan_batch.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/renderplan_grouping.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/renderplan_projection.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/renderplan_replan.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/schema_registry.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/schemas/v1.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/schemas/v2.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/schemas/v3.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/schemas/v4.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/segmentation.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/serialization.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/spacy_models.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/spans.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/ssmdbook.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/document/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/document/plain.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/document/ssmd.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/preparation/__init__.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/preparation/identity.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/preparation/ssmd.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/preparation/ttsready.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/stages/protocols.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/token_topology.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/toml_codec.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/trace_codec.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/units.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/utterplan.schema.json +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan/versioning.py +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/dependency_links.txt +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/entry_points.txt +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/requires.txt +0 -0
- {utterplan-0.6.3 → utterplan-0.6.5}/utterplan.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: utterplan
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.5
|
|
4
4
|
Summary: Engine-independent text-to-speech planning compiler and interchange format
|
|
5
5
|
Author-email: Holger Nahrstaedt <nahrstaedt@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -253,7 +253,7 @@ UtterPlan is the canonical, engine-independent semantic compiler from one SSMD
|
|
|
253
253
|
document (or explicitly selected plain-text document) to an executable speech
|
|
254
254
|
plan. It produces deterministic prepared text, paragraph-local flow units, safe boundary opportunities, authored pause intents, and segment-local
|
|
255
255
|
semantics, portable document metadata, and typed directives for
|
|
256
|
-
independent downstream
|
|
256
|
+
independent downstream FlowPlan consumers. Its book commands read the SSMDBook manifest only for chapter discovery, never modify the manifest or source chapters, and write derived plans to separate directories. It uses TTSReady for written-to-spoken preparation and stops before G2P, synthesis, and audio.
|
|
257
257
|
|
|
258
258
|
## CLI
|
|
259
259
|
|
|
@@ -285,6 +285,24 @@ utterplan compile-many examples/*.ssmd --output-dir build/plans
|
|
|
285
285
|
|
|
286
286
|
This writes one `.utterplan.toml` per source plus an atomically refreshed `compile-report.toml`. Terminal diagnostics default to warnings; `--diagnostics all` also prints informational records, while `--diagnostics none` suppresses non-failure details. Failures are always reported, and the operational report retains every diagnostic. Use `--fail-fast` to skip later inputs after a failure, `--force` to replace existing plans, or `--report PATH` to choose another report location.
|
|
287
287
|
|
|
288
|
+
## Compile an SSMDDoc workspace
|
|
289
|
+
|
|
290
|
+
Compile one editable `.ssmdoc` directory as one SSMD document and one FlowPlan:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
utterplan compile-document story.ssmdoc
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
By default this writes `story.ssmdoc/utterplan/document.utterplan.toml` and `story.ssmdoc/utterplan/compile-report.toml`. The current `document.ssmd.md` is authoritative even if its manifest digest is stale; UtterPlan leaves the source and manifest untouched. This is separate from the multi-chapter SSMDBook workflow below. See the [SSMDDoc workspace guide](docs/ssmdoc.md) for manifest safety, output options, and the Python API.
|
|
297
|
+
|
|
298
|
+
Project the saved plan with an explicit RenderProfile:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
utterplan render-document story.ssmdoc --profile narration.renderprofile.toml
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
The profile-specific RenderPlan is written to a matching variant directly under `story.ssmdoc/renderplan/`.
|
|
305
|
+
|
|
288
306
|
Compile a selected chapter range directly from an editable SSMDBook workspace:
|
|
289
307
|
|
|
290
308
|
```bash
|
|
@@ -306,6 +324,58 @@ utterplan/
|
|
|
306
324
|
|
|
307
325
|
Omit `--chapters` to compile all manifest chapters. Use comma-separated source-number selections for non-contiguous ranges, for example `utterplan compile-book chapters --chapters 1,3-5`. `--diagnostics warnings|all|none` defaults to warnings; failures are always shown and reports retain complete diagnostics. The book root itself is also accepted as input; see the [SSMDBook guide](docs/ssmdbook.md).
|
|
308
326
|
|
|
327
|
+
## Logical roles and complete RenderProfiles
|
|
328
|
+
|
|
329
|
+
An SSMD `voice` reference is a **logical role**: a renderer-independent name such as `narrator`, `host`, or `guest`. A **role binding** is the concrete renderer configuration for that name in a RenderProfile. One RenderProfile is the complete cast for one render variant, together with shared planning and pause policy; it may bind different roles to different engines. UtterPlan accepts one `--profile` per projection, not one profile per role, and does not discover engines or voices.
|
|
330
|
+
|
|
331
|
+
A profile can define a default for speech without an explicit role reference and explicit bindings for other roles:
|
|
332
|
+
|
|
333
|
+
In SSMD, the source remains renderer-independent; for example:
|
|
334
|
+
|
|
335
|
+
```markdown
|
|
336
|
+
:::{voice="host"}
|
|
337
|
+
Host line.
|
|
338
|
+
:::
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
```toml
|
|
342
|
+
default_role = "narrator"
|
|
343
|
+
|
|
344
|
+
[roles.narrator]
|
|
345
|
+
language = "en-US"
|
|
346
|
+
|
|
347
|
+
[roles.narrator.binding]
|
|
348
|
+
renderer = "kokoro"
|
|
349
|
+
target_id = "v1.0"
|
|
350
|
+
voice = "af_heart"
|
|
351
|
+
|
|
352
|
+
[roles.host]
|
|
353
|
+
language = "en-US"
|
|
354
|
+
|
|
355
|
+
[roles.host.binding]
|
|
356
|
+
renderer = "kitten"
|
|
357
|
+
target_id = "mini-0.8"
|
|
358
|
+
voice = "Jasper"
|
|
359
|
+
|
|
360
|
+
[roles.guest]
|
|
361
|
+
language = "en-US"
|
|
362
|
+
|
|
363
|
+
[roles.guest.binding]
|
|
364
|
+
renderer = "piper"
|
|
365
|
+
target_id = "en_US-amy-medium"
|
|
366
|
+
voice = "en_US-amy-medium"
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Inspect symbolic role usage without a profile, then project a document or selected book chapters with the same complete cast:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
utterplan inspect story.utterplan.toml --roles
|
|
373
|
+
utterplan render-document story.ssmdoc --profile printer-cast.renderprofile.toml
|
|
374
|
+
utterplan render-book novel.ssmdbook --profile novel-cast.renderprofile.toml
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Projection reports required and available roles and rejects incomplete coverage before writing the RenderPlan variant. The profile and its concrete role bindings remain separate from the source SSMD.
|
|
378
|
+
|
|
309
379
|
## From an SSMDBook to RenderPlans
|
|
310
380
|
|
|
311
381
|
UtterPlan keeps one canonical semantic plan per chapter. A RenderProfile is a
|
|
@@ -9,7 +9,7 @@ UtterPlan is the canonical, engine-independent semantic compiler from one SSMD
|
|
|
9
9
|
document (or explicitly selected plain-text document) to an executable speech
|
|
10
10
|
plan. It produces deterministic prepared text, paragraph-local flow units, safe boundary opportunities, authored pause intents, and segment-local
|
|
11
11
|
semantics, portable document metadata, and typed directives for
|
|
12
|
-
independent downstream
|
|
12
|
+
independent downstream FlowPlan consumers. Its book commands read the SSMDBook manifest only for chapter discovery, never modify the manifest or source chapters, and write derived plans to separate directories. It uses TTSReady for written-to-spoken preparation and stops before G2P, synthesis, and audio.
|
|
13
13
|
|
|
14
14
|
## CLI
|
|
15
15
|
|
|
@@ -41,6 +41,24 @@ utterplan compile-many examples/*.ssmd --output-dir build/plans
|
|
|
41
41
|
|
|
42
42
|
This writes one `.utterplan.toml` per source plus an atomically refreshed `compile-report.toml`. Terminal diagnostics default to warnings; `--diagnostics all` also prints informational records, while `--diagnostics none` suppresses non-failure details. Failures are always reported, and the operational report retains every diagnostic. Use `--fail-fast` to skip later inputs after a failure, `--force` to replace existing plans, or `--report PATH` to choose another report location.
|
|
43
43
|
|
|
44
|
+
## Compile an SSMDDoc workspace
|
|
45
|
+
|
|
46
|
+
Compile one editable `.ssmdoc` directory as one SSMD document and one FlowPlan:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
utterplan compile-document story.ssmdoc
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
By default this writes `story.ssmdoc/utterplan/document.utterplan.toml` and `story.ssmdoc/utterplan/compile-report.toml`. The current `document.ssmd.md` is authoritative even if its manifest digest is stale; UtterPlan leaves the source and manifest untouched. This is separate from the multi-chapter SSMDBook workflow below. See the [SSMDDoc workspace guide](docs/ssmdoc.md) for manifest safety, output options, and the Python API.
|
|
53
|
+
|
|
54
|
+
Project the saved plan with an explicit RenderProfile:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
utterplan render-document story.ssmdoc --profile narration.renderprofile.toml
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The profile-specific RenderPlan is written to a matching variant directly under `story.ssmdoc/renderplan/`.
|
|
61
|
+
|
|
44
62
|
Compile a selected chapter range directly from an editable SSMDBook workspace:
|
|
45
63
|
|
|
46
64
|
```bash
|
|
@@ -62,6 +80,58 @@ utterplan/
|
|
|
62
80
|
|
|
63
81
|
Omit `--chapters` to compile all manifest chapters. Use comma-separated source-number selections for non-contiguous ranges, for example `utterplan compile-book chapters --chapters 1,3-5`. `--diagnostics warnings|all|none` defaults to warnings; failures are always shown and reports retain complete diagnostics. The book root itself is also accepted as input; see the [SSMDBook guide](docs/ssmdbook.md).
|
|
64
82
|
|
|
83
|
+
## Logical roles and complete RenderProfiles
|
|
84
|
+
|
|
85
|
+
An SSMD `voice` reference is a **logical role**: a renderer-independent name such as `narrator`, `host`, or `guest`. A **role binding** is the concrete renderer configuration for that name in a RenderProfile. One RenderProfile is the complete cast for one render variant, together with shared planning and pause policy; it may bind different roles to different engines. UtterPlan accepts one `--profile` per projection, not one profile per role, and does not discover engines or voices.
|
|
86
|
+
|
|
87
|
+
A profile can define a default for speech without an explicit role reference and explicit bindings for other roles:
|
|
88
|
+
|
|
89
|
+
In SSMD, the source remains renderer-independent; for example:
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
:::{voice="host"}
|
|
93
|
+
Host line.
|
|
94
|
+
:::
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```toml
|
|
98
|
+
default_role = "narrator"
|
|
99
|
+
|
|
100
|
+
[roles.narrator]
|
|
101
|
+
language = "en-US"
|
|
102
|
+
|
|
103
|
+
[roles.narrator.binding]
|
|
104
|
+
renderer = "kokoro"
|
|
105
|
+
target_id = "v1.0"
|
|
106
|
+
voice = "af_heart"
|
|
107
|
+
|
|
108
|
+
[roles.host]
|
|
109
|
+
language = "en-US"
|
|
110
|
+
|
|
111
|
+
[roles.host.binding]
|
|
112
|
+
renderer = "kitten"
|
|
113
|
+
target_id = "mini-0.8"
|
|
114
|
+
voice = "Jasper"
|
|
115
|
+
|
|
116
|
+
[roles.guest]
|
|
117
|
+
language = "en-US"
|
|
118
|
+
|
|
119
|
+
[roles.guest.binding]
|
|
120
|
+
renderer = "piper"
|
|
121
|
+
target_id = "en_US-amy-medium"
|
|
122
|
+
voice = "en_US-amy-medium"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Inspect symbolic role usage without a profile, then project a document or selected book chapters with the same complete cast:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
utterplan inspect story.utterplan.toml --roles
|
|
129
|
+
utterplan render-document story.ssmdoc --profile printer-cast.renderprofile.toml
|
|
130
|
+
utterplan render-book novel.ssmdbook --profile novel-cast.renderprofile.toml
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Projection reports required and available roles and rejects incomplete coverage before writing the RenderPlan variant. The profile and its concrete role bindings remain separate from the source SSMD.
|
|
134
|
+
|
|
65
135
|
## From an SSMDBook to RenderPlans
|
|
66
136
|
|
|
67
137
|
UtterPlan keeps one canonical semantic plan per chapter. A RenderProfile is a
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Architecture Documentation"
|
|
3
|
-
version:
|
|
3
|
+
version: 3
|
|
4
4
|
generator: "archledger 0.4.0"
|
|
5
5
|
arc42_template_version: "9.0-EN"
|
|
6
6
|
---
|
|
@@ -50,7 +50,7 @@ FlowPlan v7 (paragraph-local units, segments, boundaries, authored pauses)
|
|
|
50
50
|
Downstream chunking / token-budget / pause choices
|
|
51
51
|
|
|
|
52
52
|
v
|
|
53
|
-
|
|
53
|
+
Downstream FlowPlan consumers
|
|
54
54
|
|
|
|
55
55
|
v
|
|
56
56
|
G2P / synthesis / audio (downstream)
|
|
@@ -60,6 +60,10 @@ The compiler still handles one document at a time; the CLI's explicit SSMDBook
|
|
|
60
60
|
commands (`compile-book`, `render-book`) discover chapters and orchestrate per-file
|
|
61
61
|
workspaces without changing book content.
|
|
62
62
|
|
|
63
|
+
## Document workspaces
|
|
64
|
+
|
|
65
|
+
An editable `ssmdconvert.document` v1 workspace (`.ssmdoc`) is another source path for the one-document compiler. `compile-document` discovers its canonical current SSMD document and writes one FlowPlan plus an operational report under `<workspace>/utterplan/`; `render-document` projects that saved plan with an explicit profile into `<workspace>/renderplan/<label>--<profile-id-prefix>/`. Neither command creates book-set semantics or alters workspace source material.
|
|
66
|
+
|
|
63
67
|
## Requirements Overview
|
|
64
68
|
|
|
65
69
|
<!-- archledger: no accepted records for this section yet -->
|
|
@@ -121,7 +125,7 @@ TTSReady
|
|
|
121
125
|
^
|
|
122
126
|
UtterPlan
|
|
123
127
|
^
|
|
124
|
-
|
|
128
|
+
Downstream FlowPlan consumers
|
|
125
129
|
```
|
|
126
130
|
|
|
127
131
|
UtterPlan depends directly on SSMD, PhraseSplit, and TTSReady:
|
|
@@ -136,9 +140,9 @@ UtterPlan depends directly on SSMD, PhraseSplit, and TTSReady:
|
|
|
136
140
|
- **spaCy** optionally enriches tokens (best effort, `sm`/`md`/`lg`/`trf` preference;
|
|
137
141
|
UtterPlan never downloads models and falls back to deterministic tokens).
|
|
138
142
|
- **RenderPlan** defines the shared profile/plan contract used by the optional
|
|
139
|
-
projection;
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
projection; downstream renderers consume portable RenderProfiles and RenderPlans,
|
|
144
|
+
while other downstream consumers consume FlowPlans. Engine selection, preflight,
|
|
145
|
+
and speech execution are outside UtterPlan.
|
|
142
146
|
|
|
143
147
|
## In scope
|
|
144
148
|
|
|
@@ -164,6 +168,12 @@ UtterPlan depends directly on SSMD, PhraseSplit, and TTSReady:
|
|
|
164
168
|
- Renderer chunking, token-budget, and pause-realization choices.
|
|
165
169
|
- Consumer-specific compatibility testing.
|
|
166
170
|
|
|
171
|
+
## SSMDDoc source workspace
|
|
172
|
+
|
|
173
|
+
- An editable `.ssmdoc` directory is discovered by its `ssmdconvert.document` v1 manifest, not by its directory suffix. Its canonical `document.ssmd.md` is the current compiler input.
|
|
174
|
+
- The workspace remains one document to one FlowPlan. Manifest digests are provenance only for editable directories: UtterPlan compiles current content and never refreshes the manifest or edits the source.
|
|
175
|
+
- `compile-document` is single-document convenience, not book orchestration. ZIP bundles, fake chapters, and an `ssmdconvert` runtime dependency are outside the contract.
|
|
176
|
+
|
|
167
177
|
## Business Context
|
|
168
178
|
|
|
169
179
|
<!-- archledger: no accepted records for this section yet -->
|
|
@@ -253,6 +263,10 @@ provenance, diagnostics, and renderability evidence in a separate versioned TOML
|
|
|
253
263
|
sidecar. Trace state is not renderer input and does not affect plan identity or
|
|
254
264
|
TOML.
|
|
255
265
|
|
|
266
|
+
## Document workspace orchestration
|
|
267
|
+
|
|
268
|
+
`ssmdoc.py` performs read-only manifest discovery and canonical path safety checks; `source_input.py` centralizes standalone-file and `.ssmdoc` source loading; and `document_workspace.py` delegates one stable `document-0001` CompileRequest to the existing batch persistence/report path. The CLI and public package API expose `compile-document` and `compile_ssmdoc()` without shadowing the in-memory `compile_document()` compiler.
|
|
269
|
+
|
|
256
270
|
<!-- archledger: no accepted records for this section yet -->
|
|
257
271
|
|
|
258
272
|
# Runtime View
|
|
@@ -327,6 +341,28 @@ accepts TOML only and rejects JSON.
|
|
|
327
341
|
RenderPlan and its matching preflight report are required together; UtterPlan does
|
|
328
342
|
not calculate renderer-specific metrics.
|
|
329
343
|
|
|
344
|
+
## Scenario: compile an editable SSMDDoc workspace
|
|
345
|
+
|
|
346
|
+
```text
|
|
347
|
+
ssmdconvert.document v1 manifest + current document.ssmd.md
|
|
348
|
+
-> utterplan compile-document
|
|
349
|
+
-> one FlowPlan at utterplan/document.utterplan.toml
|
|
350
|
+
+ one compile-report.toml
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
The manifest validates the workspace contract and safe canonical path; SSMD 0.9 content is compiled by the existing single-document path. A stale stored digest does not block editable-directory compilation, and UtterPlan does not modify source material or model the document as a chapter.
|
|
354
|
+
|
|
355
|
+
## Scenario: project a RenderPlan from an editable SSMDDoc workspace
|
|
356
|
+
|
|
357
|
+
```text
|
|
358
|
+
saved FlowPlan + explicit RenderProfile
|
|
359
|
+
-> utterplan render-document
|
|
360
|
+
-> one profile-specific RenderPlan at renderplan/<label>--<profile-id-prefix>/document.renderplan.toml
|
|
361
|
+
+ canonical renderprofile.toml snapshot + render-report.toml
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
The command projects the existing plan without compiling source or invoking a renderer. Profile identity is embedded in the variant path, and a mismatched or ambiguous profile snapshot is rejected; source files and the SSMDDoc manifest remain unchanged.
|
|
365
|
+
|
|
330
366
|
<!-- archledger: no accepted records for this section yet -->
|
|
331
367
|
|
|
332
368
|
# Deployment View
|
|
@@ -338,8 +374,8 @@ or audio dependencies:
|
|
|
338
374
|
dynamically derived from Git tags by setuptools-scm and is independent of the
|
|
339
375
|
plan schema version.
|
|
340
376
|
- **Installation shapes.** Installed as a library (`pip install utterplan`) for
|
|
341
|
-
|
|
342
|
-
workflows. Development installs use `pip install -e '.[dev,docs]'`.
|
|
377
|
+
downstream FlowPlan consumers, or with the `utterplan` CLI for direct SSMDBook and
|
|
378
|
+
SSMDDoc workflows. Development installs use `pip install -e '.[dev,docs]'`.
|
|
343
379
|
- **Optional linguistic enrichment.** spaCy models are preferred in `sm`, `md`,
|
|
344
380
|
`lg`, `trf` order when already installed; UtterPlan never downloads models and
|
|
345
381
|
continues with deterministic fallback tokens when spaCy or every compatible local
|
|
@@ -347,14 +383,16 @@ or audio dependencies:
|
|
|
347
383
|
- **No runtime services.** Everything runs in-process; there is no server, daemon,
|
|
348
384
|
network fetch, or audio device access. Media references and extension names in
|
|
349
385
|
plans are data only.
|
|
350
|
-
- **Downstream placement.** Consumers
|
|
351
|
-
|
|
352
|
-
|
|
386
|
+
- **Downstream placement.** Consumers of UtterPlan's portable FlowPlan and optional
|
|
387
|
+
RenderPlan contracts add engines, model runtimes, G2P, synthesis, and audio on their
|
|
388
|
+
side of the boundary; UtterPlan does not import those packages.
|
|
353
389
|
- **Documentation.** Sphinx docs build from `docs/` with
|
|
354
390
|
`sphinx-build -W --keep-going -b html docs docs/_build/html`.
|
|
355
391
|
- **Quality gate.** `python -m pytest -q`, `ruff check .`, and `mypy utterplan` run
|
|
356
392
|
against the self-contained repository test suite.
|
|
357
393
|
|
|
394
|
+
- **Editable document workspaces.** `.ssmdoc` v1 is consumed as a stable file-format contract with the standard library; `ssmdconvert` is not a runtime dependency. `compile-document` writes semantic plans and its report directly under `<workspace>/utterplan/`; `render-document` writes profile-specific artifacts directly under `<workspace>/renderplan/` without changing source files.
|
|
395
|
+
|
|
358
396
|
<!-- archledger: no accepted records for this section yet -->
|
|
359
397
|
|
|
360
398
|
# Cross-cutting Concepts
|
|
@@ -484,6 +522,8 @@ drafts and never become canonical plans.
|
|
|
484
522
|
compiled plan; replanning is a separate operation. _Rationale:_ schema evolution
|
|
485
523
|
must not force package-version coupling or silent replans.
|
|
486
524
|
|
|
525
|
+
- **AD: SSMDDoc is one document, not a book.** An `ssmdconvert.document` v1 workspace resolves to its current canonical SSMD source and the existing one-document compiler, producing one FlowPlan. Editable directory digests do not override current source content; UtterPlan neither refreshes nor mutates the workspace. _Rationale:_ preserve one-document/one-plan semantics and keep source-workspace ownership in `ssmdconvert`.
|
|
526
|
+
|
|
487
527
|
<!-- archledger: no accepted records for this section yet -->
|
|
488
528
|
|
|
489
529
|
# Quality Requirements
|
|
@@ -584,4 +624,6 @@ drafts and never become canonical plans.
|
|
|
584
624
|
| Planning attempt | Inspect-only `utterplan.planning-attempt.v1` artifact for reviewing blocked renderability outcomes; never a canonical plan. |
|
|
585
625
|
| plan_id | Deterministic renderer-independent plan identity; v7 `utterplan-flow-v3` includes boundaries and never hashes TOML formatting. |
|
|
586
626
|
|
|
627
|
+
| SSMDDoc | Editable single-document workspace using the `ssmdconvert.document` v1 manifest; `compile-document` compiles the current canonical SSMD file to one FlowPlan without mutating source. |
|
|
628
|
+
|
|
587
629
|
<!-- archledger: no accepted records for this section yet -->
|
|
@@ -4,7 +4,32 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
-
## [v0.6.
|
|
7
|
+
## [v0.6.5] - 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added render-document for projecting compiled SSMDDoc FlowPlans into profile-specific RenderPlans
|
|
12
|
+
- Added logical role coverage inspection and complete-profile validation for document and book rendering
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Changed editable SSMDDoc workspaces to use stable utterplan and renderplan output directories
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Fixed documentation links for logical role and profile coverage guidance
|
|
21
|
+
|
|
22
|
+
<!-- generated by releaseledger -->
|
|
23
|
+
|
|
24
|
+
## [v0.6.4] - 2026-10-19
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- Added compile-document for editable SSMDDoc workspaces with safe source loading and plan reports
|
|
29
|
+
|
|
30
|
+
<!-- generated by releaseledger -->
|
|
31
|
+
|
|
32
|
+
## [v0.6.3] - 2026-10-15
|
|
8
33
|
|
|
9
34
|
### Added
|
|
10
35
|
|
|
@@ -50,6 +50,18 @@ require `--force`. `--explain` formats the generated plan and replan decisions;
|
|
|
50
50
|
does not invoke planning a second time. `--json` emits a versioned JSON wrapper to
|
|
51
51
|
stdout while the RenderPlan artifact remains TOML at `--output`.
|
|
52
52
|
|
|
53
|
+
## Logical roles and complete-profile coverage
|
|
54
|
+
|
|
55
|
+
Role coverage is validated before grouping or replanning. The selected profile must contain every explicit speech role and, when any speech omits a role reference, its `default_role`. Missing roles are reported together as `renderplan.role.missing`; extra profile roles are allowed. The check is renderer-independent and does not add role data to the RenderPlan schema.
|
|
56
|
+
|
|
57
|
+
Use source-only role inspection without loading a RenderProfile:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
utterplan inspect chapter.utterplan.toml --roles
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The human `render-plan` summary reports required roles and `coverage: complete`. With `--json`, the versioned CLI wrapper includes a `role_coverage` object (`default_role`, `required`, `available`, `missing`, and `uses_default_role`) alongside, but outside, the RenderPlan payload.
|
|
64
|
+
|
|
53
65
|
## Input resolution
|
|
54
66
|
|
|
55
67
|
The rules are deterministic:
|
|
@@ -124,6 +136,35 @@ Compile reports use format version 2. Each successful item records its resolved
|
|
|
124
136
|
|
|
125
137
|
Shared planning options include `--language`, `--input-format auto|plain|ssmd`, `--text-preparation`, `--spacy`, and `--renderability`. `--diagnostics warnings|all|none` controls terminal detail (default `warnings`): warnings mode suppresses informational diagnostics, all includes them, and none suppresses non-failure diagnostics. Failures are always reported, and the operational report always retains complete diagnostics. Progress, selected diagnostic details, actionable errors, and final counts are written to stderr. Exit status is 0 if every input succeeds, 1 if any input fails, and 2 for usage errors such as output collisions. `--fail-fast` skips later requests after the first failure but preserves all completed outputs and updates the report.
|
|
126
138
|
|
|
139
|
+
## Compile one SSMDDoc workspace
|
|
140
|
+
|
|
141
|
+
`compile-document` reads a single editable `ssmdconvert.document` v1 workspace and compiles its canonical SSMD 0.9 document into one plan. It accepts the workspace root or its canonical `document.ssmd.md` path:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
utterplan compile-document INPUT [--output-dir PATH] [--language LANGUAGE]
|
|
145
|
+
[--text-preparation {auto,ssmd,spokenform,identity}]
|
|
146
|
+
[--renderability {strict,repair}] [--spacy {auto,off,sm,md,lg,trf}]
|
|
147
|
+
[--force] [--report PATH] [--diagnostics {warnings,all,none}]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The default output directory is `<workspace>/utterplan/`, containing `document.utterplan.toml` and `compile-report.toml`. `--output-dir` and `--report` override those locations. Existing plan files require `--force`; output collisions with the source or manifest are rejected. A document header's language is authoritative; `--language`/`--lang` is a fallback when it is absent.
|
|
151
|
+
|
|
152
|
+
Editable content wins over the stored manifest digest: compilation reads the current `document.ssmd.md` but never modifies the manifest or source. The command has no `--input-format`, chapter selection, or `--fail-fast`; it handles one document. The existing `compile` and `validate` commands also accept the workspace root or canonical document path, while `compile` retains its normal stdout/`-o` behavior. This is not `compile-book`: an SSMDDoc creates one plan, while an SSMDBook orchestrates independent chapter plans. ZIP bundles are not supported and `ssmdconvert` is not a runtime dependency. See the [SSMDDoc guide](ssmdoc.md) for format validation and the `compile_ssmdoc()` Python API.
|
|
153
|
+
|
|
154
|
+
## Project an SSMDDoc RenderPlan
|
|
155
|
+
|
|
156
|
+
`render-document` projects the already-saved single-document UtterPlan through an explicit RenderProfile. It never compiles implicitly:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
utterplan render-document INPUT --profile PROFILE
|
|
160
|
+
[--utterplan-dir PATH] [--output-root PATH] [--variant LABEL]
|
|
161
|
+
[--force] [--report PATH]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
By default it reads `<workspace>/utterplan/document.utterplan.toml` and writes a profile-fingerprinted variant under `<workspace>/renderplan/<label>--<profile-id-prefix>/`, containing `renderprofile.toml`, `document.renderplan.toml`, and `render-report.toml`. `--variant` changes only the readable label; the profile fingerprint remains part of the directory identity. A profile mismatch or ambiguous existing snapshot is rejected even with `--force`. This is a one-document projection, not a book-set workflow. See the [SSMDDoc guide](ssmdoc.md).
|
|
165
|
+
|
|
166
|
+
The start summary also lists the document's required roles and coverage. Coverage is checked before a new variant directory, profile snapshot, or RenderPlan is written; a missing role leaves no partial variant.
|
|
167
|
+
|
|
127
168
|
## Compile chapters from an SSMDBook workspace
|
|
128
169
|
|
|
129
170
|
`compile-book` discovers selected SSMD chapters from an editable `.ssmdbook` manifest and compiles each chapter independently through the batch compiler. Pass either the book directory or its canonical `chapters/` directory:
|
|
@@ -170,8 +211,9 @@ utterplan render-book INPUT --profile PROFILE [--chapters SELECTOR]
|
|
|
170
211
|
`chapters/` directory. `--chapters` uses the same manifest `source_number`
|
|
171
212
|
selector as `compile-book`: `all` (default), one number, an inclusive range, or
|
|
172
213
|
comma-separated selections such as `1,3-5,9`. Chapters remain in manifest order.
|
|
173
|
-
`--profile` is required and is loaded once through the shared RenderPlan codec;
|
|
174
|
-
|
|
214
|
+
`--profile` is required and is loaded once through the shared RenderPlan codec; UtterPlan does not call VoiceRender or probe engines.
|
|
215
|
+
|
|
216
|
+
Before initializing a new variant, `render-book` checks role coverage across all readable selected chapter plans. A single incomplete chapter fails the projection with the missing role names and affected chapter IDs; no new profile snapshot or `renderplan-set.toml` is written. The start summary lists the aggregate required roles and complete coverage. Other missing/invalid source-plan behavior is unchanged.
|
|
175
217
|
|
|
176
218
|
Defaults and behavior:
|
|
177
219
|
|
|
@@ -9,6 +9,7 @@ speech plans. It stops before G2P and synthesis.
|
|
|
9
9
|
|
|
10
10
|
getting-started
|
|
11
11
|
cli
|
|
12
|
+
SSMDDoc workspace support <ssmdoc>
|
|
12
13
|
SSMDBook and RenderPlan workflow <ssmdbook>
|
|
13
14
|
consumer-guide
|
|
14
15
|
format
|
|
@@ -27,4 +28,5 @@ changelog
|
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
The [SSMDBook guide](ssmdbook.md) covers workspace compilation and the profile-specific `render-book` workflow, including how RenderPlan and VoiceRender fit after semantic planning.
|
|
31
|
+
The [SSMDDoc guide](ssmdoc.md) covers one-document workspace compilation, source immutability, and how it differs from an SSMDBook.
|
|
30
32
|
The package version and the UtterPlan schema version are independent. Schema v7 is the only version accepted by normal loading and execution. Schema-v5/v6 TOML and schemas v1–v4 remain immutable historical migration inputs; the sequential path reaches v6, while v6-to-v7 requires recompiling the original source.
|
|
@@ -79,6 +79,29 @@ prior partitions and replaces only exact failed speech occurrences. Backend metr
|
|
|
79
79
|
remain diagnostics supplied by preflight; UtterPlan does not estimate them. Use
|
|
80
80
|
`utterplan render-plan --explain` to format the already-built decisions.
|
|
81
81
|
|
|
82
|
+
### Inspect logical role coverage
|
|
83
|
+
|
|
84
|
+
The public role-coverage helpers expose source inventory independently of projection or renderer bindings. `logical_role_inventory()` counts explicit role references and speech using the profile default; `profile_role_coverage()` compares those requirements with one complete RenderProfile, preserving first-occurrence order for required roles and deterministic sorting for available roles. The returned `LogicalRoleInventory` and `ProfileRoleCoverage` types separate source inventory from profile coverage. Both functions are available from the package root:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from renderplan.codec import load_profile
|
|
88
|
+
from utterplan import (
|
|
89
|
+
FlowPlan,
|
|
90
|
+
logical_role_inventory,
|
|
91
|
+
profile_role_coverage,
|
|
92
|
+
assert_profile_role_coverage,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
source = FlowPlan.load("chapter.utterplan.toml")
|
|
96
|
+
inventory = logical_role_inventory(source)
|
|
97
|
+
profile = load_profile("cast.renderprofile.toml")
|
|
98
|
+
coverage = assert_profile_role_coverage(source, profile)
|
|
99
|
+
print(inventory.explicit_roles, inventory.explicit_occurrences)
|
|
100
|
+
print(coverage.required_roles, coverage.available_roles, coverage.missing_roles)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Empty and audio-only segments do not require a role. `assert_profile_role_coverage()` raises the normal `renderplan.role.missing` projection error with all missing role names; `build_render_plan()` performs this check before grouping or replanning.
|
|
104
|
+
|
|
82
105
|
## Persistable planning attempts
|
|
83
106
|
|
|
84
107
|
`compile_attempt` and `UtterancePlanner.compile_attempt` expose a finalized planning
|
|
@@ -102,6 +102,8 @@ utterplan render-book . --profile amy.renderprofile.toml --chapters 5-17
|
|
|
102
102
|
utterplan render-book . --profile joe.renderprofile.toml --chapters 5-17
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
One RenderProfile is the complete cast shared by every selected chapter, not a profile per character or role. Logical role names live in SSMD; the profile's role bindings can target different renderers. Before creating a new variant, `render-book` checks all readable selected UtterPlans together and reports every uncovered role with the affected chapter IDs. See the [README role example](https://github.com/buchwandler/utterplan/blob/main/README.md#logical-roles-and-complete-renderprofiles).
|
|
106
|
+
|
|
105
107
|
The result has one shared semantic collection and distinct renderer-specific
|
|
106
108
|
variants, for example:
|
|
107
109
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# SSMDDoc workspace support
|
|
2
|
+
|
|
3
|
+
UtterPlan can compile an editable `.ssmdoc` workspace as one SSMD 0.9 document. This is a workspace input convenience around the existing one-document compiler; it is not a book format and does not create chapter plans.
|
|
4
|
+
|
|
5
|
+
## Workspace contract
|
|
6
|
+
|
|
7
|
+
A workspace is identified by a `manifest.json` whose `format` is `ssmdconvert.document` and whose `schema_version` is `1`. UtterPlan supports the v1 contract and expects the canonical document entry to identify `document-0001` at the normalized relative path `document.ssmd.md`. The source is SSMD 0.9.
|
|
8
|
+
|
|
9
|
+
The current `document.ssmd.md` is authoritative. Its manifest digest and character count are metadata, not a lock: if you edit the document and its recorded digest becomes stale, UtterPlan compiles the current file. It never rewrites the manifest, refreshes hashes, or edits source content. Semantic plans and reports are written directly under the workspace's visible `utterplan/` directory; profile-specific RenderPlans are written directly under `renderplan/`. These are derived artifacts, not manifest members.
|
|
10
|
+
|
|
11
|
+
Discovery and path handling are deliberately strict. The manifest must be valid UTF-8 JSON within the 2 MiB limit, and the document is limited to 64 MiB. UtterPlan checks the canonical path and workspace containment, rejects unsupported manifest versions and unsafe paths, and does not follow a document path outside the workspace. It reads no source-media files. `ssmdconvert` is not a runtime dependency: UtterPlan consumes the published file-format contract directly.
|
|
12
|
+
|
|
13
|
+
ZIP bundles are not supported by this workflow; use an editable directory workspace.
|
|
14
|
+
|
|
15
|
+
## Compile a workspace
|
|
16
|
+
|
|
17
|
+
Run `compile-document` with the workspace directory (the suffix need not be `.ssmdoc` if the manifest identifies it):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
utterplan compile-document story.ssmdoc
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
It writes one plan and one operational report by default:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
story.ssmdoc/utterplan/
|
|
27
|
+
├── document.utterplan.toml
|
|
28
|
+
└── compile-report.toml
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The report describes the single compilation and is not a FlowPlan. You can override the destination and report path:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
utterplan compile-document story.ssmdoc \
|
|
35
|
+
--output-dir build/story-plan \
|
|
36
|
+
--report build/story-report.toml \
|
|
37
|
+
--language en-US \
|
|
38
|
+
--spacy off
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Options are `--output-dir`, `--report`, `--language`/`--lang`, `--text-preparation`, `--renderability`, `--spacy`, `--diagnostics`, and `--force`. SSMD header language remains authoritative; pass `--language` as a fallback when the document has no language. Existing plan outputs are protected unless `--force` is supplied. The report may not collide with the plan, manifest, or source document. `compile-document` is a single-workspace command, so it has no chapter selector or `--fail-fast` option.
|
|
42
|
+
|
|
43
|
+
The existing `compile` and `validate` commands also accept the workspace root or its canonical `document.ssmd.md` file as input. `compile` keeps its normal stdout/`-o` behavior; use `compile-document` when you want the workspace-oriented default output directory and report. `validate` compiles the source for validation without writing a plan.
|
|
44
|
+
|
|
45
|
+
## Python API
|
|
46
|
+
|
|
47
|
+
Use `compile_ssmdoc()` for file-backed workspace compilation. The existing `compile_document()` remains the in-memory text API:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from utterplan import compile_ssmdoc
|
|
51
|
+
|
|
52
|
+
result = compile_ssmdoc("story.ssmdoc", language="en-US")
|
|
53
|
+
if result.failed:
|
|
54
|
+
raise RuntimeError(f"workspace compilation failed; see {result.report_path}")
|
|
55
|
+
print(result.plan_path)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The result provides the workspace and source paths, output and report paths, and the one-item batch outcome. Options include `output_dir`, `report`, `language`, `planner_config`, `force`, `diagnostics`, and progress/start callbacks. The default artifacts match the CLI: `utterplan/document.utterplan.toml` and `utterplan/compile-report.toml`.
|
|
59
|
+
|
|
60
|
+
## SSMDDoc is not SSMDBook
|
|
61
|
+
|
|
62
|
+
An SSMDDoc contains one editable document and produces one canonical FlowPlan. An SSMDBook manifest discovers multiple independent chapter documents; `compile-book` writes one plan per selected chapter and never builds a book-level combined plan. Use [SSMDBook workflows](ssmdbook.md) for book compilation and RenderPlan projection.
|
|
63
|
+
|
|
64
|
+
Neither workspace workflow changes its source manifest or source documents. UtterPlan stops at semantic FlowPlans; engine selection, G2P, synthesis, and audio remain downstream.
|
|
65
|
+
|
|
66
|
+
## Projecting a document RenderPlan
|
|
67
|
+
|
|
68
|
+
After `utterplan compile-document .`, project the existing canonical FlowPlan without recompiling it:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
utterplan render-document . --profile narration.renderprofile.toml
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This writes `renderplan/<label>--<profile-fingerprint>/renderprofile.toml`, `document.renderplan.toml`, and `render-report.toml` directly under the workspace. The printed exact variant can be passed to `voicerender render-document`. A document is never wrapped in a one-chapter book or a RenderPlanSet. Re-run `compile-document` and this projection after source edits; VoiceRender intentionally renders only the selected explicit RenderPlan.
|
|
75
|
+
|
|
76
|
+
### Logical roles and profile coverage
|
|
77
|
+
|
|
78
|
+
A source-level `voice` name such as `narrator`, `host`, or `guest` is a **logical role**; it does not name an engine voice. The selected RenderProfile's **role binding** supplies the concrete renderer configuration. Treat one RenderProfile as the complete cast for a rendering variant, including its default role and shared planning/pause policy. UtterPlan accepts exactly one profile for this projection; it does not accept one profile per role or discover engines.
|
|
79
|
+
|
|
80
|
+
Use `utterplan inspect <plan> --roles` to see explicit speech-role counts and whether unqualified speech needs the selected profile's default. `render-document` reports required roles and complete coverage, and rejects any missing roles before creating a new variant directory. The same multi-role RenderProfile format and example are documented in the [README](https://github.com/buchwandler/utterplan/blob/main/README.md#logical-roles-and-complete-renderprofiles).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "ssmdconvert.document",
|
|
3
|
+
"schema_version": 1,
|
|
4
|
+
"ssmd_version": "0.9",
|
|
5
|
+
"metadata": {
|
|
6
|
+
"title": "UtterPlan document fixture",
|
|
7
|
+
"language": "en-US"
|
|
8
|
+
},
|
|
9
|
+
"source": {
|
|
10
|
+
"format": "markdown",
|
|
11
|
+
"media_type": "text/markdown",
|
|
12
|
+
"name": "story.md",
|
|
13
|
+
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
14
|
+
},
|
|
15
|
+
"document": {
|
|
16
|
+
"id": "document-0001",
|
|
17
|
+
"path": "document.ssmd.md",
|
|
18
|
+
"char_count": 87,
|
|
19
|
+
"sha256": "ed67851d91bb3d82c08020d1cdfef99102632a62dbeea46ee1793cf8fa9a49c3"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -27,7 +27,7 @@ from utterplan import (
|
|
|
27
27
|
replan_book,
|
|
28
28
|
)
|
|
29
29
|
from utterplan.config import LinguisticsConfig, PlannerConfig
|
|
30
|
-
from utterplan.model import FlowPlan
|
|
30
|
+
from utterplan.model import FlowPlan, FlowSegment, FlowUnit, SegmentDirectives, VoiceDirective
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _ssmd(text: str) -> str:
|
|
@@ -481,3 +481,28 @@ def test_public_book_services_refuse_outputs_inside_source_chapters(tmp_path: Pa
|
|
|
481
481
|
with pytest.raises(BookServiceError, match="inside source chapters"):
|
|
482
482
|
render_book(root, profile=profile_path, output_root=root / "chapters" / "renderplans")
|
|
483
483
|
assert not (root / "chapters/renderplans").exists()
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def test_render_book_aggregates_missing_roles_before_variant_initialization(tmp_path: Path) -> None:
|
|
487
|
+
root = _book(tmp_path / "role-coverage.ssmdbook", (5, 6, 7))
|
|
488
|
+
utterplan_dir = root / "utterplan"
|
|
489
|
+
utterplan_dir.mkdir()
|
|
490
|
+
for number, role in ((5, None), (6, "host"), (7, "guest")):
|
|
491
|
+
text = f"Chapter {number}."
|
|
492
|
+
directives = (
|
|
493
|
+
SegmentDirectives(voice=VoiceDirective(reference=role)) if role else SegmentDirectives()
|
|
494
|
+
)
|
|
495
|
+
FlowPlan(
|
|
496
|
+
language="en-US",
|
|
497
|
+
flow=(FlowUnit((FlowSegment(text, "en-US", directives=directives),)),),
|
|
498
|
+
).save(utterplan_dir / f"chapter-{number:04d}.utterplan.toml")
|
|
499
|
+
profile_path = root / "narration.renderprofile.toml"
|
|
500
|
+
_profile(profile_path)
|
|
501
|
+
|
|
502
|
+
with pytest.raises(BookServiceError) as raised:
|
|
503
|
+
render_book(root, profile=profile_path)
|
|
504
|
+
|
|
505
|
+
message = str(raised.value)
|
|
506
|
+
assert "host: chapter-0006" in message
|
|
507
|
+
assert "guest: chapter-0007" in message
|
|
508
|
+
assert not (root / "renderplan").exists()
|