utterplan 0.6.2__tar.gz → 0.6.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. utterplan-0.6.4/MANIFEST.in +2 -0
  2. {utterplan-0.6.2 → utterplan-0.6.4}/PKG-INFO +46 -1
  3. {utterplan-0.6.2 → utterplan-0.6.4}/README.md +45 -0
  4. {utterplan-0.6.2 → utterplan-0.6.4}/docs/architecture.md +32 -1
  5. {utterplan-0.6.2 → utterplan-0.6.4}/docs/changelog.md +16 -0
  6. {utterplan-0.6.2 → utterplan-0.6.4}/docs/cli.md +85 -0
  7. {utterplan-0.6.2 → utterplan-0.6.4}/docs/index.md +2 -0
  8. utterplan-0.6.4/docs/ssmdoc.md +64 -0
  9. utterplan-0.6.4/tests/fixtures/ssmdoc-v1/story.ssmdoc/document.ssmd.md +6 -0
  10. utterplan-0.6.4/tests/fixtures/ssmdoc-v1/story.ssmdoc/manifest.json +21 -0
  11. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_book_api.py +44 -0
  12. utterplan-0.6.4/tests/test_book_replan.py +471 -0
  13. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_cli.py +52 -0
  14. utterplan-0.6.4/tests/test_cli_replan_book.py +261 -0
  15. utterplan-0.6.4/tests/test_cli_ssmdoc.py +279 -0
  16. utterplan-0.6.4/tests/test_document_workspace.py +248 -0
  17. utterplan-0.6.4/tests/test_source_input.py +104 -0
  18. utterplan-0.6.4/tests/test_ssmdoc.py +250 -0
  19. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/__init__.py +34 -0
  20. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/_version.py +3 -3
  21. utterplan-0.6.4/utterplan/book_replan.py +761 -0
  22. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/cli.py +337 -41
  23. utterplan-0.6.4/utterplan/document_workspace.py +194 -0
  24. utterplan-0.6.4/utterplan/source_input.py +121 -0
  25. utterplan-0.6.4/utterplan/ssmdoc.py +191 -0
  26. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/PKG-INFO +46 -1
  27. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/SOURCES.txt +13 -0
  28. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/scm_file_list.json +24 -0
  29. utterplan-0.6.4/utterplan.egg-info/scm_version.json +8 -0
  30. utterplan-0.6.2/MANIFEST.in +0 -1
  31. utterplan-0.6.2/utterplan.egg-info/scm_version.json +0 -8
  32. {utterplan-0.6.2 → utterplan-0.6.4}/.codecrate.toml +0 -0
  33. {utterplan-0.6.2 → utterplan-0.6.4}/.github/workflows/codecov.yml +0 -0
  34. {utterplan-0.6.2 → utterplan-0.6.4}/.github/workflows/pre-commit.yml +0 -0
  35. {utterplan-0.6.2 → utterplan-0.6.4}/.github/workflows/python-publish.yml +0 -0
  36. {utterplan-0.6.2 → utterplan-0.6.4}/.github/workflows/tests.yml +0 -0
  37. {utterplan-0.6.2 → utterplan-0.6.4}/.gitignore +0 -0
  38. {utterplan-0.6.2 → utterplan-0.6.4}/.pre-commit-config.yaml +0 -0
  39. {utterplan-0.6.2 → utterplan-0.6.4}/AGENTS.md +0 -0
  40. {utterplan-0.6.2 → utterplan-0.6.4}/LICENSE +0 -0
  41. {utterplan-0.6.2 → utterplan-0.6.4}/NOTICE +0 -0
  42. {utterplan-0.6.2 → utterplan-0.6.4}/docs/Makefile +0 -0
  43. {utterplan-0.6.2 → utterplan-0.6.4}/docs/conf.py +0 -0
  44. {utterplan-0.6.2 → utterplan-0.6.4}/docs/consumer-guide.md +0 -0
  45. {utterplan-0.6.2 → utterplan-0.6.4}/docs/coordinate-spaces.md +0 -0
  46. {utterplan-0.6.2 → utterplan-0.6.4}/docs/debugging.md +0 -0
  47. {utterplan-0.6.2 → utterplan-0.6.4}/docs/format.md +0 -0
  48. {utterplan-0.6.2 → utterplan-0.6.4}/docs/getting-started.md +0 -0
  49. {utterplan-0.6.2 → utterplan-0.6.4}/docs/make.bat +0 -0
  50. {utterplan-0.6.2 → utterplan-0.6.4}/docs/phase-a-completion.md +0 -0
  51. {utterplan-0.6.2 → utterplan-0.6.4}/docs/pykokoro-integration.md +0 -0
  52. {utterplan-0.6.2 → utterplan-0.6.4}/docs/python-api.md +0 -0
  53. {utterplan-0.6.2 → utterplan-0.6.4}/docs/requirements.txt +0 -0
  54. {utterplan-0.6.2 → utterplan-0.6.4}/docs/ssmdbook.md +0 -0
  55. {utterplan-0.6.2 → utterplan-0.6.4}/examples/basic.py +0 -0
  56. {utterplan-0.6.2 → utterplan-0.6.4}/examples/chapter.ssmd +0 -0
  57. {utterplan-0.6.2 → utterplan-0.6.4}/examples/compile_file.py +0 -0
  58. {utterplan-0.6.2 → utterplan-0.6.4}/examples/inspect_plan.py +0 -0
  59. {utterplan-0.6.2 → utterplan-0.6.4}/examples/multilingual.py +0 -0
  60. {utterplan-0.6.2 → utterplan-0.6.4}/examples/ssmd_example.py +0 -0
  61. {utterplan-0.6.2 → utterplan-0.6.4}/pyproject.toml +0 -0
  62. {utterplan-0.6.2 → utterplan-0.6.4}/setup.cfg +0 -0
  63. {utterplan-0.6.2 → utterplan-0.6.4}/spec/schemas/v1.schema.json +0 -0
  64. {utterplan-0.6.2 → utterplan-0.6.4}/spec/schemas/v2.schema.json +0 -0
  65. {utterplan-0.6.2 → utterplan-0.6.4}/spec/schemas/v3.schema.json +0 -0
  66. {utterplan-0.6.2 → utterplan-0.6.4}/spec/schemas/v4.schema.json +0 -0
  67. {utterplan-0.6.2 → utterplan-0.6.4}/spec/utterplan.schema.json +0 -0
  68. {utterplan-0.6.2 → utterplan-0.6.4}/tests/__init__.py +0 -0
  69. {utterplan-0.6.2 → utterplan-0.6.4}/tests/compiler_helpers.py +0 -0
  70. {utterplan-0.6.2 → utterplan-0.6.4}/tests/fixtures/canonical_consumer_contract.expected.toml +0 -0
  71. {utterplan-0.6.2 → utterplan-0.6.4}/tests/fixtures/canonical_consumer_contract.ssmd +0 -0
  72. {utterplan-0.6.2 → utterplan-0.6.4}/tests/fixtures/ssmd_09_comprehensive.ssmd +0 -0
  73. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/basic_en.utterplan.toml +0 -0
  74. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/directives.utterplan.toml +0 -0
  75. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/markers.utterplan.toml +0 -0
  76. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/multilingual.utterplan.toml +0 -0
  77. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/parenthetical.utterplan.toml +0 -0
  78. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/spokenform_offsets.utterplan.toml +0 -0
  79. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/ssmd_09_comprehensive.utterplan.toml +0 -0
  80. {utterplan-0.6.2 → utterplan-0.6.4}/tests/golden/ssmd_breaks.utterplan.toml +0 -0
  81. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/__init__.py +0 -0
  82. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/cases.py +0 -0
  83. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/basic_en.utterplan.json +0 -0
  84. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/directives.utterplan.json +0 -0
  85. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/markers.utterplan.json +0 -0
  86. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/multilingual.utterplan.json +0 -0
  87. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/parenthetical.utterplan.json +0 -0
  88. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/spokenform_offsets.utterplan.json +0 -0
  89. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/ssmd_09_comprehensive.utterplan.json +0 -0
  90. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/fixtures/v4/ssmd_breaks.utterplan.json +0 -0
  91. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/goldens/multilingual_preparation.json +0 -0
  92. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/goldens/spokenform_numbers.json +0 -0
  93. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/goldens/ssmd_break.json +0 -0
  94. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/goldens/ssmd_language_detection.json +0 -0
  95. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/goldens/ssmd_marker.json +0 -0
  96. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/goldens/ssmd_pronunciation.json +0 -0
  97. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/test_legacy_json_import.py +0 -0
  98. {utterplan-0.6.2 → utterplan-0.6.4}/tests/migration/test_semantic_migration_regressions.py +0 -0
  99. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/README.md +0 -0
  100. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/basic.json +0 -0
  101. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/directives.json +0 -0
  102. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/markers.json +0 -0
  103. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/multilingual.json +0 -0
  104. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/parenthetical.json +0 -0
  105. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/spokenform_offsets.json +0 -0
  106. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v1/ssmd_breaks.json +0 -0
  107. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v2/directives.json +0 -0
  108. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v3/multilingual.json +0 -0
  109. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v3/ssmd_09_comprehensive.json +0 -0
  110. {utterplan-0.6.2 → utterplan-0.6.4}/tests/schema_history/v5/canonical_consumer_contract.toml +0 -0
  111. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_atomic_io.py +0 -0
  112. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_batch.py +0 -0
  113. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_boundaries.py +0 -0
  114. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_cli_batch.py +0 -0
  115. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_cli_render_book.py +0 -0
  116. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_cli_ssmdbook.py +0 -0
  117. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_compiler.py +0 -0
  118. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_consumer_contract.py +0 -0
  119. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_consumer_readiness.py +0 -0
  120. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_coordinates.py +0 -0
  121. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_dependency_architecture.py +0 -0
  122. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_directives.py +0 -0
  123. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_explain.py +0 -0
  124. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_fake_renderer.py +0 -0
  125. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_flow_compilation.py +0 -0
  126. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_format.py +0 -0
  127. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_golden.py +0 -0
  128. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_identity_units.py +0 -0
  129. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_import_boundaries.py +0 -0
  130. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_language.py +0 -0
  131. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_linguistics.py +0 -0
  132. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_migration_framework.py +0 -0
  133. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_migration_v3_to_v4.py +0 -0
  134. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_migration_v4_to_v5.py +0 -0
  135. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_pauses.py +0 -0
  136. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_planner.py +0 -0
  137. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_preparation.py +0 -0
  138. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_preview.py +0 -0
  139. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_progress.py +0 -0
  140. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_public_identity.py +0 -0
  141. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderability.py +0 -0
  142. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderability_repair.py +0 -0
  143. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderplan_batch.py +0 -0
  144. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderplan_dependency_contract.py +0 -0
  145. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderplan_export.py +0 -0
  146. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderplan_replan.py +0 -0
  147. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_renderplan_v7_contract.py +0 -0
  148. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_replacement_provenance.py +0 -0
  149. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_schema_history.py +0 -0
  150. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_schema_registry.py +0 -0
  151. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_schema_strict.py +0 -0
  152. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_schema_v6_source.py +0 -0
  153. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_schema_v7.py +0 -0
  154. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_segment_topology.py +0 -0
  155. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_segmentation_adapter.py +0 -0
  156. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_segmentation_recovery.py +0 -0
  157. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_semantic_boundaries.py +0 -0
  158. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_sentence_topology.py +0 -0
  159. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_ssmd_09_parser.py +0 -0
  160. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_ssmd_substitution_preparation.py +0 -0
  161. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_ssmdbook.py +0 -0
  162. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_token_topology.py +0 -0
  163. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_toml_format.py +0 -0
  164. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_ttsready_preparation_adapter.py +0 -0
  165. {utterplan-0.6.2 → utterplan-0.6.4}/tests/test_version.py +0 -0
  166. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/__main__.py +0 -0
  167. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/atomic_io.py +0 -0
  168. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/attempt_serialization.py +0 -0
  169. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/attempts.py +0 -0
  170. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/batch.py +0 -0
  171. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/book.py +0 -0
  172. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/boundaries.py +0 -0
  173. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/codecs/__init__.py +0 -0
  174. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/codecs/v4_toml.py +0 -0
  175. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/codecs/v5_toml.py +0 -0
  176. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/codecs/v6_toml.py +0 -0
  177. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/codecs/v7_toml.py +0 -0
  178. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/compiler.py +0 -0
  179. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/config.py +0 -0
  180. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/diagnostics.py +0 -0
  181. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/directives.py +0 -0
  182. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/exceptions.py +0 -0
  183. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/explain.py +0 -0
  184. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/flow_projection.py +0 -0
  185. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/format.py +0 -0
  186. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/hashing.py +0 -0
  187. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/language.py +0 -0
  188. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/linguistics.py +0 -0
  189. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migration.py +0 -0
  190. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/__init__.py +0 -0
  191. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/registry.py +0 -0
  192. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/v1_to_v2.py +0 -0
  193. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/v2_to_v3.py +0 -0
  194. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/v3_to_v4.py +0 -0
  195. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/v4_to_v5.py +0 -0
  196. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/v5_to_v6.py +0 -0
  197. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/migrations/v6_to_v7.py +0 -0
  198. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/model.py +0 -0
  199. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/parsers.py +0 -0
  200. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/pauses.py +0 -0
  201. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/planner.py +0 -0
  202. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/preparation.py +0 -0
  203. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/preview.py +0 -0
  204. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/progress.py +0 -0
  205. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/py.typed +0 -0
  206. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/renderability.py +0 -0
  207. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/renderplan_batch.py +0 -0
  208. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/renderplan_export.py +0 -0
  209. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/renderplan_grouping.py +0 -0
  210. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/renderplan_projection.py +0 -0
  211. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/renderplan_replan.py +0 -0
  212. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/schema_registry.py +0 -0
  213. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/schemas/v1.schema.json +0 -0
  214. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/schemas/v2.schema.json +0 -0
  215. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/schemas/v3.schema.json +0 -0
  216. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/schemas/v4.schema.json +0 -0
  217. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/segmentation.py +0 -0
  218. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/serialization.py +0 -0
  219. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/spacy_models.py +0 -0
  220. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/spans.py +0 -0
  221. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/ssmdbook.py +0 -0
  222. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/__init__.py +0 -0
  223. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/document/__init__.py +0 -0
  224. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/document/plain.py +0 -0
  225. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/document/ssmd.py +0 -0
  226. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/preparation/__init__.py +0 -0
  227. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/preparation/identity.py +0 -0
  228. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/preparation/ssmd.py +0 -0
  229. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/preparation/ttsready.py +0 -0
  230. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/stages/protocols.py +0 -0
  231. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/token_topology.py +0 -0
  232. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/toml_codec.py +0 -0
  233. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/trace_codec.py +0 -0
  234. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/units.py +0 -0
  235. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/utterplan.schema.json +0 -0
  236. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan/versioning.py +0 -0
  237. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/dependency_links.txt +0 -0
  238. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/entry_points.txt +0 -0
  239. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/requires.txt +0 -0
  240. {utterplan-0.6.2 → utterplan-0.6.4}/utterplan.egg-info/top_level.txt +0 -0
@@ -0,0 +1,2 @@
1
+ prune .ledger
2
+ include docs/ssmdoc.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: utterplan
3
- Version: 0.6.2
3
+ Version: 0.6.4
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
@@ -285,6 +285,16 @@ 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/.readio/utterplan/document-0001.utterplan.toml` and a `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
+
288
298
  Compile a selected chapter range directly from an editable SSMDBook workspace:
289
299
 
290
300
  ```bash
@@ -353,6 +363,41 @@ creates or refreshes engine-backed profiles, then preflights and renders the
353
363
  resulting RenderPlans. The single-file `utterplan render-plan` command remains the
354
364
  low-level projection and deterministic replan primitive.
355
365
 
366
+ When VoiceRender reports `preflight.replan`, use the new `replan-book` command to
367
+ refine the exact active chapter plan. The operation reads the RenderProfile snapshot
368
+ from the selected variant, writes a fingerprinted child RenderPlan, and updates only
369
+ that chapter's active set entry. It does not replace the parent plan or rerun initial
370
+ projection:
371
+
372
+ ```bash
373
+ # VoiceRender measures the active plans; suppose chapter 5 returns preflight.replan.
374
+ voicerender render-book . \
375
+ --variant narration4--28f616b6fe3b \
376
+ --chapters 5 \
377
+ --emphasis-policy defer-to-compose
378
+
379
+ utterplan replan-book . \
380
+ --variant narration4--28f616b6fe3b \
381
+ --chapters 5
382
+
383
+ # Measure/render the newly active child. Repeat these last two commands if it
384
+ # still reports preflight.replan; each cycle must use feedback for the active plan.
385
+ voicerender render-book . \
386
+ --variant narration4--28f616b6fe3b \
387
+ --chapters 5 \
388
+ --emphasis-policy defer-to-compose
389
+ ```
390
+
391
+ Use the exact variant directory name (including its profile fingerprint). `replan-book`
392
+ searches `preflight-recheck.toml` before `preflight.toml` and refuses stale feedback,
393
+ so a report for a parent can never be applied to its child. The single-file
394
+ `render-plan --previous ... --preflight ...` operation remains available for
395
+ low-level replanning.
396
+
397
+ This orchestration does not add a splitter, renderer-specific capacity estimate, or
398
+ engine dependency. VoiceRender supplies preflight measurements and remains responsible
399
+ for synthesis and audio composition.
400
+
356
401
  Related packages: [RenderPlan](https://pypi.org/project/renderplan/) defines the
357
402
  shared profile and plan contracts; [VoiceRender](https://pypi.org/project/voicerender/)
358
403
  creates engine-backed profiles and performs preflight and synthesis.
@@ -41,6 +41,16 @@ 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/.readio/utterplan/document-0001.utterplan.toml` and a `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
+
44
54
  Compile a selected chapter range directly from an editable SSMDBook workspace:
45
55
 
46
56
  ```bash
@@ -109,6 +119,41 @@ creates or refreshes engine-backed profiles, then preflights and renders the
109
119
  resulting RenderPlans. The single-file `utterplan render-plan` command remains the
110
120
  low-level projection and deterministic replan primitive.
111
121
 
122
+ When VoiceRender reports `preflight.replan`, use the new `replan-book` command to
123
+ refine the exact active chapter plan. The operation reads the RenderProfile snapshot
124
+ from the selected variant, writes a fingerprinted child RenderPlan, and updates only
125
+ that chapter's active set entry. It does not replace the parent plan or rerun initial
126
+ projection:
127
+
128
+ ```bash
129
+ # VoiceRender measures the active plans; suppose chapter 5 returns preflight.replan.
130
+ voicerender render-book . \
131
+ --variant narration4--28f616b6fe3b \
132
+ --chapters 5 \
133
+ --emphasis-policy defer-to-compose
134
+
135
+ utterplan replan-book . \
136
+ --variant narration4--28f616b6fe3b \
137
+ --chapters 5
138
+
139
+ # Measure/render the newly active child. Repeat these last two commands if it
140
+ # still reports preflight.replan; each cycle must use feedback for the active plan.
141
+ voicerender render-book . \
142
+ --variant narration4--28f616b6fe3b \
143
+ --chapters 5 \
144
+ --emphasis-policy defer-to-compose
145
+ ```
146
+
147
+ Use the exact variant directory name (including its profile fingerprint). `replan-book`
148
+ searches `preflight-recheck.toml` before `preflight.toml` and refuses stale feedback,
149
+ so a report for a parent can never be applied to its child. The single-file
150
+ `render-plan --previous ... --preflight ...` operation remains available for
151
+ low-level replanning.
152
+
153
+ This orchestration does not add a splitter, renderer-specific capacity estimate, or
154
+ engine dependency. VoiceRender supplies preflight measurements and remains responsible
155
+ for synthesis and audio composition.
156
+
112
157
  Related packages: [RenderPlan](https://pypi.org/project/renderplan/) defines the
113
158
  shared profile and plan contracts; [VoiceRender](https://pypi.org/project/voicerender/)
114
159
  creates engine-backed profiles and performs preflight and synthesis.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Architecture Documentation"
3
- version: 1
3
+ version: 2
4
4
  generator: "archledger 0.4.0"
5
5
  arc42_template_version: "9.0-EN"
6
6
  ---
@@ -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 `.readio/utterplan/`; it does not create a book or alter workspace source material.
66
+
63
67
  ## Requirements Overview
64
68
 
65
69
  <!-- archledger: no accepted records for this section yet -->
@@ -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,17 @@ 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 .readio/utterplan/document-0001.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
+
330
355
  <!-- archledger: no accepted records for this section yet -->
331
356
 
332
357
  # Deployment View
@@ -355,6 +380,8 @@ or audio dependencies:
355
380
  - **Quality gate.** `python -m pytest -q`, `ruff check .`, and `mypy utterplan` run
356
381
  against the self-contained repository test suite.
357
382
 
383
+ - **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 derived plans under the reserved `.readio/utterplan/` directory without changing source files.
384
+
358
385
  <!-- archledger: no accepted records for this section yet -->
359
386
 
360
387
  # Cross-cutting Concepts
@@ -484,6 +511,8 @@ drafts and never become canonical plans.
484
511
  compiled plan; replanning is a separate operation. _Rationale:_ schema evolution
485
512
  must not force package-version coupling or silent replans.
486
513
 
514
+ - **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`.
515
+
487
516
  <!-- archledger: no accepted records for this section yet -->
488
517
 
489
518
  # Quality Requirements
@@ -584,4 +613,6 @@ drafts and never become canonical plans.
584
613
  | Planning attempt | Inspect-only `utterplan.planning-attempt.v1` artifact for reviewing blocked renderability outcomes; never a canonical plan. |
585
614
  | plan_id | Deterministic renderer-independent plan identity; v7 `utterplan-flow-v3` includes boundaries and never hashes TOML formatting. |
586
615
 
616
+ | 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. |
617
+
587
618
  <!-- archledger: no accepted records for this section yet -->
@@ -4,6 +4,22 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [v0.6.4] - 2026-10-19
8
+
9
+ ### Added
10
+
11
+ - Added compile-document for editable SSMDDoc workspaces with safe source loading and plan reports
12
+
13
+ <!-- generated by releaseledger -->
14
+
15
+ ## [v0.6.3] - 2026-10-15
16
+
17
+ ### Added
18
+
19
+ - Added replan-book to refine active book RenderPlans from matching VoiceRender preflight feedback
20
+
21
+ <!-- generated by releaseledger -->
22
+
7
23
  ## [v0.6.2] - 2026-10-14
8
24
 
9
25
  ### Added
@@ -124,6 +124,21 @@ Compile reports use format version 2. Each successful item records its resolved
124
124
 
125
125
  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
126
 
127
+ ## Compile one SSMDDoc workspace
128
+
129
+ `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:
130
+
131
+ ```text
132
+ utterplan compile-document INPUT [--output-dir PATH] [--language LANGUAGE]
133
+ [--text-preparation {auto,ssmd,spokenform,identity}]
134
+ [--renderability {strict,repair}] [--spacy {auto,off,sm,md,lg,trf}]
135
+ [--force] [--report PATH] [--diagnostics {warnings,all,none}]
136
+ ```
137
+
138
+ The default output directory is `<workspace>/.readio/utterplan/`, containing `document-0001.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.
139
+
140
+ 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.
141
+
127
142
  ## Compile chapters from an SSMDBook workspace
128
143
 
129
144
  `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:
@@ -205,6 +220,76 @@ are rejected before chapter processing. Exit status is 0 when all selected
205
220
  chapters succeed, 1 when any chapter fails, and 2 for usage or shared-configuration
206
221
  errors. See the [SSMDBook workflow guide](ssmdbook.md) for end-to-end and multi-voice examples.
207
222
 
223
+ ## Replan active RenderPlans for selected chapters
224
+
225
+ `replan-book` is the book/variant orchestration for VoiceRender's capacity feedback.
226
+ It loads the profile snapshot owned by the existing RenderPlanSet; callers must select
227
+ the exact variant directory, not supply another profile:
228
+
229
+ VoiceRender supplies capacity feedback: UtterPlan does not add renderer-specific
230
+ metrics, a splitter, engine selection, synthesis, or audio composition.
231
+
232
+ ```text
233
+ utterplan replan-book INPUT --variant VARIANT [--chapters SELECTOR]
234
+ [--renderplan-root PATH] [--voicerender-root PATH] [--report PATH]
235
+ [--dry-run] [--fail-fast] [--explain] [--json]
236
+ ```
237
+
238
+ Example repeatable lifecycle:
239
+
240
+ ```bash
241
+ # Initial projection and exact renderer preflight/render
242
+ utterplan render-book . --profile narration4.renderprofile.toml --variant narration4 --chapters 5
243
+ voicerender render-book . --variant narration4--28f616b6fe3b --chapters 5 \
244
+ --emphasis-policy defer-to-compose
245
+
246
+ # If VoiceRender returns preflight.replan, refine only the active chapter plan
247
+ utterplan replan-book . --variant narration4--28f616b6fe3b --chapters 5
248
+
249
+ # Preflight/render the new active plan; repeat replan-book and this command if needed
250
+ voicerender render-book . --variant narration4--28f616b6fe3b --chapters 5 \
251
+ --emphasis-policy defer-to-compose
252
+ ```
253
+
254
+ `INPUT` is an SSMDBook root or its canonical `chapters/` directory. Chapter selectors
255
+ use manifest source numbers and retain manifest order. The default RenderPlan root is
256
+ `<book-root>/renderplan`; the default VoiceRender root is `<book-root>/voicerender`.
257
+ The command reads `<variant>/renderprofile.toml` and the selected active plan paths
258
+ from `renderplan-set.toml`. It discovers reports under
259
+ `<voicerender-root>/<variant>/<chapter-id>/`, preferring `preflight-recheck.toml`
260
+ over `preflight.toml` when both fully validate against the exact active RenderPlan.
261
+
262
+ Only a matching `status="replan"` report is accepted. Missing reports, stale parent
263
+ reports, mismatched profile/plan identities, and `ok`/`reject` statuses fail that
264
+ chapter; the command never falls back to an initial RenderPlan projection. A successful
265
+ replan writes a deterministic immutable child plan first, then atomically changes only
266
+ the selected chapter's active set entry. Parent plans, source UtterPlans, profile
267
+ identity, and unselected set entries remain unchanged. Run VoiceRender again after
268
+ each replan; repeat the two feedback steps until preflight is `ok`.
269
+
270
+ Defaults and behavior:
271
+
272
+ - `--variant` is required and must name the existing full variant directory, including
273
+ its profile fingerprint. The profile snapshot is loaded from that collection.
274
+ - `--chapters`: `all`, one source number, an inclusive range, or comma-separated
275
+ selections; default is `all`.
276
+ - `--renderplan-root` and `--voicerender-root` override the collection/data roots,
277
+ not the selected variant or chapter paths recorded by the contracts.
278
+ - `--report`: defaults to `<variant-dir>/replan-report.toml`; progress is persisted
279
+ after each chapter and the final report is marked complete.
280
+ - `--dry-run`: validates and plans children without writing child RenderPlans or
281
+ changing the set index. It writes the operational report and reports successful
282
+ items as `planned`.
283
+ - `--fail-fast`: later chapters are recorded as skipped after the first failure;
284
+ without it, later selected chapters continue.
285
+ - `--explain` uses the existing per-request RenderPlan explanation; `--json` emits
286
+ structured outcome paths, identities, replacement counts, errors, and optional
287
+ explanations.
288
+
289
+ Re-running with a stale report after activating a child fails with
290
+ `renderplan.replan.book.preflight_stale`. VoiceRender must first measure the active
291
+ child to produce its own matching feedback report.
292
+
208
293
  ## Explain a plan
209
294
 
210
295
  Explain an existing compiled plan as a human-readable speech narrative:
@@ -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.
@@ -0,0 +1,64 @@
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. The `.readio/utterplan/` directory is reserved for derived UtterPlan artifacts.
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/.readio/utterplan/
27
+ ├── document-0001.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: `.readio/utterplan/document-0001.utterplan.toml` and `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.
@@ -0,0 +1,6 @@
1
+ ---
2
+ ssmd_version: "0.9"
3
+ language: en-US
4
+ ---
5
+
6
+ I have [UtterPlan]{ph="utter plan"} here.
@@ -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
+ }
@@ -16,9 +16,15 @@ from utterplan import (
16
16
  BookCompileResult,
17
17
  BookRenderRequest,
18
18
  BookRenderResult,
19
+ BookReplanError,
20
+ BookReplanRequest,
21
+ BookReplanResult,
22
+ BookReplanStart,
19
23
  BookServiceError,
24
+ ReplanOutcome,
20
25
  compile_book,
21
26
  render_book,
27
+ replan_book,
22
28
  )
23
29
  from utterplan.config import LinguisticsConfig, PlannerConfig
24
30
  from utterplan.model import FlowPlan
@@ -95,9 +101,47 @@ def test_public_request_and_result_models_are_available_at_package_root() -> Non
95
101
  selected_chapter_ids=(),
96
102
  outcomes=(),
97
103
  )
104
+ replan_request = BookReplanRequest(Path("book"), variant="narration--abc")
105
+ replan_outcome = ReplanOutcome(
106
+ index=1,
107
+ id="chapter-0005",
108
+ source_number=5,
109
+ status="failed",
110
+ utterplan=None,
111
+ previous_renderplan=None,
112
+ previous_render_plan_id=None,
113
+ preflight=None,
114
+ )
115
+ replan_result = BookReplanResult(
116
+ workspace=Path("book"),
117
+ variant="narration--abc",
118
+ variant_dir=Path("book/renderplan/narration--abc"),
119
+ set_path=Path("book/renderplan/narration--abc/renderplan-set.toml"),
120
+ profile_path=Path("book/renderplan/narration--abc/renderprofile.toml"),
121
+ report_path=Path("book/renderplan/narration--abc/replan-report.toml"),
122
+ selected_chapter_ids=("chapter-0005",),
123
+ dry_run=False,
124
+ outcomes=(replan_outcome,),
125
+ )
126
+ replan_start = BookReplanStart(
127
+ workspace=Path("book"),
128
+ chapter_selector="5",
129
+ selected_chapter_ids=("chapter-0005",),
130
+ variant="narration--abc",
131
+ variant_dir=replan_result.variant_dir,
132
+ set_path=replan_result.set_path,
133
+ profile_path=replan_result.profile_path,
134
+ voicerender_dir=Path("book/voicerender/narration--abc"),
135
+ report_path=replan_result.report_path,
136
+ )
98
137
  assert compile_request.book == Path("book")
99
138
  assert render_request.profile == Path("profile.renderprofile.toml")
100
139
  assert compile_result.exit_code == render_result.exit_code == 0
140
+ assert replan_request.book == Path("book")
141
+ assert replan_result.exit_code == 1 and replan_result.failed == 1
142
+ assert replan_start.variant == replan_request.variant
143
+ assert callable(replan_book)
144
+ assert issubclass(BookReplanError, BookServiceError)
101
145
  assert compile_result.failed == render_result.failed == 0
102
146
 
103
147