utterplan 0.5.1__tar.gz → 0.6.2__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 (242) hide show
  1. {utterplan-0.5.1 → utterplan-0.6.2}/.github/workflows/python-publish.yml +2 -1
  2. {utterplan-0.5.1 → utterplan-0.6.2}/.github/workflows/tests.yml +90 -4
  3. utterplan-0.6.2/AGENTS.md +29 -0
  4. {utterplan-0.5.1 → utterplan-0.6.2}/PKG-INFO +94 -14
  5. utterplan-0.6.2/README.md +279 -0
  6. utterplan-0.6.2/docs/architecture.md +587 -0
  7. {utterplan-0.5.1 → utterplan-0.6.2}/docs/changelog.md +38 -0
  8. utterplan-0.6.2/docs/cli.md +302 -0
  9. utterplan-0.6.2/docs/consumer-guide.md +121 -0
  10. {utterplan-0.5.1 → utterplan-0.6.2}/docs/coordinate-spaces.md +6 -4
  11. utterplan-0.6.2/docs/debugging.md +42 -0
  12. utterplan-0.6.2/docs/format.md +81 -0
  13. {utterplan-0.5.1 → utterplan-0.6.2}/docs/getting-started.md +35 -10
  14. utterplan-0.6.2/docs/index.md +30 -0
  15. {utterplan-0.5.1 → utterplan-0.6.2}/docs/pykokoro-integration.md +6 -5
  16. {utterplan-0.5.1 → utterplan-0.6.2}/docs/python-api.md +91 -17
  17. utterplan-0.6.2/docs/ssmdbook.md +169 -0
  18. {utterplan-0.5.1 → utterplan-0.6.2}/pyproject.toml +2 -1
  19. {utterplan-0.5.1 → utterplan-0.6.2}/tests/compiler_helpers.py +0 -2
  20. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/cases.py +25 -9
  21. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/test_legacy_json_import.py +4 -7
  22. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/test_semantic_migration_regressions.py +37 -2
  23. utterplan-0.6.2/tests/schema_history/README.md +7 -0
  24. utterplan-0.6.2/tests/schema_history/v5/canonical_consumer_contract.toml +35 -0
  25. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_batch.py +1 -1
  26. utterplan-0.6.2/tests/test_book_api.py +439 -0
  27. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_boundaries.py +45 -1
  28. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_cli.py +181 -22
  29. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_cli_batch.py +2 -0
  30. utterplan-0.6.2/tests/test_cli_render_book.py +489 -0
  31. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_cli_ssmdbook.py +115 -4
  32. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_compiler.py +8 -11
  33. utterplan-0.6.2/tests/test_consumer_contract.py +350 -0
  34. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_consumer_readiness.py +24 -23
  35. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_coordinates.py +6 -4
  36. utterplan-0.6.2/tests/test_dependency_architecture.py +41 -0
  37. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_explain.py +73 -19
  38. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_fake_renderer.py +3 -4
  39. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_flow_compilation.py +16 -35
  40. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_format.py +11 -11
  41. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_golden.py +12 -11
  42. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_identity_units.py +7 -9
  43. utterplan-0.6.2/tests/test_import_boundaries.py +29 -0
  44. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_linguistics.py +120 -98
  45. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_migration_framework.py +3 -3
  46. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_migration_v4_to_v5.py +36 -2
  47. utterplan-0.6.2/tests/test_pauses.py +146 -0
  48. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_planner.py +120 -31
  49. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_preparation.py +16 -12
  50. utterplan-0.6.2/tests/test_preview.py +161 -0
  51. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_progress.py +1 -0
  52. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_public_identity.py +4 -1
  53. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_renderability.py +1 -1
  54. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_renderability_repair.py +8 -10
  55. utterplan-0.6.2/tests/test_renderplan_batch.py +334 -0
  56. utterplan-0.6.2/tests/test_renderplan_dependency_contract.py +32 -0
  57. utterplan-0.6.2/tests/test_renderplan_export.py +264 -0
  58. utterplan-0.6.2/tests/test_renderplan_replan.py +402 -0
  59. utterplan-0.6.2/tests/test_renderplan_v7_contract.py +523 -0
  60. utterplan-0.6.2/tests/test_replacement_provenance.py +228 -0
  61. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_schema_history.py +9 -2
  62. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_schema_registry.py +7 -3
  63. utterplan-0.6.2/tests/test_schema_v6_source.py +122 -0
  64. utterplan-0.6.2/tests/test_schema_v7.py +148 -0
  65. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_segment_topology.py +2 -1
  66. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_segmentation_recovery.py +48 -0
  67. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_semantic_boundaries.py +0 -1
  68. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_ssmd_09_parser.py +3 -3
  69. utterplan-0.6.2/tests/test_ssmd_substitution_preparation.py +257 -0
  70. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_toml_format.py +37 -19
  71. utterplan-0.6.2/tests/test_ttsready_preparation_adapter.py +305 -0
  72. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/__init__.py +48 -2
  73. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/_version.py +3 -3
  74. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/batch.py +58 -3
  75. utterplan-0.6.2/utterplan/book.py +598 -0
  76. utterplan-0.6.2/utterplan/boundaries.py +51 -0
  77. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/cli.py +538 -113
  78. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/codecs/v5_toml.py +126 -19
  79. utterplan-0.6.2/utterplan/codecs/v6_toml.py +123 -0
  80. utterplan-0.6.2/utterplan/codecs/v7_toml.py +625 -0
  81. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/compiler.py +1 -0
  82. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/config.py +24 -21
  83. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/directives.py +2 -1
  84. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/exceptions.py +3 -4
  85. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/explain.py +40 -5
  86. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/flow_projection.py +103 -7
  87. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/format.py +3 -3
  88. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/hashing.py +31 -7
  89. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/linguistics.py +1 -1
  90. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migration.py +2 -0
  91. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migrations/__init__.py +4 -0
  92. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migrations/v4_to_v5.py +77 -2
  93. utterplan-0.6.2/utterplan/migrations/v5_to_v6.py +48 -0
  94. utterplan-0.6.2/utterplan/migrations/v6_to_v7.py +34 -0
  95. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/model.py +440 -66
  96. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/parsers.py +105 -1
  97. utterplan-0.6.2/utterplan/pauses.py +80 -0
  98. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/planner.py +662 -100
  99. utterplan-0.6.2/utterplan/preparation.py +665 -0
  100. utterplan-0.6.2/utterplan/preview.py +257 -0
  101. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/renderability.py +9 -25
  102. utterplan-0.6.2/utterplan/renderplan_batch.py +471 -0
  103. utterplan-0.6.2/utterplan/renderplan_export.py +160 -0
  104. utterplan-0.6.2/utterplan/renderplan_grouping.py +729 -0
  105. utterplan-0.6.2/utterplan/renderplan_projection.py +369 -0
  106. utterplan-0.6.2/utterplan/renderplan_replan.py +273 -0
  107. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/schema_registry.py +1 -1
  108. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/segmentation.py +116 -4
  109. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/serialization.py +6 -9
  110. utterplan-0.6.2/utterplan/stages/preparation/ssmd.py +3 -0
  111. utterplan-0.6.2/utterplan/stages/preparation/ttsready.py +3 -0
  112. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/toml_codec.py +19 -23
  113. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/units.py +4 -5
  114. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/versioning.py +5 -3
  115. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/PKG-INFO +94 -14
  116. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/SOURCES.txt +29 -1
  117. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/requires.txt +2 -1
  118. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/scm_file_list.json +118 -1
  119. utterplan-0.6.2/utterplan.egg-info/scm_version.json +8 -0
  120. utterplan-0.5.1/AGENTS.md +0 -20
  121. utterplan-0.5.1/README.md +0 -200
  122. utterplan-0.5.1/docs/architecture.md +0 -69
  123. utterplan-0.5.1/docs/cli.md +0 -204
  124. utterplan-0.5.1/docs/consumer-guide.md +0 -92
  125. utterplan-0.5.1/docs/debugging.md +0 -30
  126. utterplan-0.5.1/docs/format.md +0 -68
  127. utterplan-0.5.1/docs/index.md +0 -31
  128. utterplan-0.5.1/docs/ssmdbook.md +0 -72
  129. utterplan-0.5.1/tests/schema_history/README.md +0 -9
  130. utterplan-0.5.1/tests/test_consumer_contract.py +0 -185
  131. utterplan-0.5.1/tests/test_import_boundaries.py +0 -16
  132. utterplan-0.5.1/tests/test_pauses.py +0 -213
  133. utterplan-0.5.1/utterplan/pauses.py +0 -108
  134. utterplan-0.5.1/utterplan/preparation.py +0 -263
  135. utterplan-0.5.1/utterplan/stages/preparation/spokenform.py +0 -3
  136. utterplan-0.5.1/utterplan.egg-info/scm_version.json +0 -8
  137. {utterplan-0.5.1 → utterplan-0.6.2}/.codecrate.toml +0 -0
  138. {utterplan-0.5.1 → utterplan-0.6.2}/.github/workflows/codecov.yml +0 -0
  139. {utterplan-0.5.1 → utterplan-0.6.2}/.github/workflows/pre-commit.yml +0 -0
  140. {utterplan-0.5.1 → utterplan-0.6.2}/.gitignore +0 -0
  141. {utterplan-0.5.1 → utterplan-0.6.2}/.pre-commit-config.yaml +0 -0
  142. {utterplan-0.5.1 → utterplan-0.6.2}/LICENSE +0 -0
  143. {utterplan-0.5.1 → utterplan-0.6.2}/MANIFEST.in +0 -0
  144. {utterplan-0.5.1 → utterplan-0.6.2}/NOTICE +0 -0
  145. {utterplan-0.5.1 → utterplan-0.6.2}/docs/Makefile +0 -0
  146. {utterplan-0.5.1 → utterplan-0.6.2}/docs/conf.py +0 -0
  147. {utterplan-0.5.1 → utterplan-0.6.2}/docs/make.bat +0 -0
  148. {utterplan-0.5.1 → utterplan-0.6.2}/docs/phase-a-completion.md +0 -0
  149. {utterplan-0.5.1 → utterplan-0.6.2}/docs/requirements.txt +0 -0
  150. {utterplan-0.5.1 → utterplan-0.6.2}/examples/basic.py +0 -0
  151. {utterplan-0.5.1 → utterplan-0.6.2}/examples/chapter.ssmd +0 -0
  152. {utterplan-0.5.1 → utterplan-0.6.2}/examples/compile_file.py +0 -0
  153. {utterplan-0.5.1 → utterplan-0.6.2}/examples/inspect_plan.py +0 -0
  154. {utterplan-0.5.1 → utterplan-0.6.2}/examples/multilingual.py +0 -0
  155. {utterplan-0.5.1 → utterplan-0.6.2}/examples/ssmd_example.py +0 -0
  156. {utterplan-0.5.1 → utterplan-0.6.2}/setup.cfg +0 -0
  157. {utterplan-0.5.1 → utterplan-0.6.2}/spec/schemas/v1.schema.json +0 -0
  158. {utterplan-0.5.1 → utterplan-0.6.2}/spec/schemas/v2.schema.json +0 -0
  159. {utterplan-0.5.1 → utterplan-0.6.2}/spec/schemas/v3.schema.json +0 -0
  160. {utterplan-0.5.1 → utterplan-0.6.2}/spec/schemas/v4.schema.json +0 -0
  161. {utterplan-0.5.1 → utterplan-0.6.2}/spec/utterplan.schema.json +0 -0
  162. {utterplan-0.5.1 → utterplan-0.6.2}/tests/__init__.py +0 -0
  163. {utterplan-0.5.1 → utterplan-0.6.2}/tests/fixtures/canonical_consumer_contract.expected.toml +0 -0
  164. {utterplan-0.5.1 → utterplan-0.6.2}/tests/fixtures/canonical_consumer_contract.ssmd +0 -0
  165. {utterplan-0.5.1 → utterplan-0.6.2}/tests/fixtures/ssmd_09_comprehensive.ssmd +0 -0
  166. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/basic_en.utterplan.toml +0 -0
  167. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/directives.utterplan.toml +0 -0
  168. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/markers.utterplan.toml +0 -0
  169. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/multilingual.utterplan.toml +0 -0
  170. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/parenthetical.utterplan.toml +0 -0
  171. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/spokenform_offsets.utterplan.toml +0 -0
  172. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/ssmd_09_comprehensive.utterplan.toml +0 -0
  173. {utterplan-0.5.1 → utterplan-0.6.2}/tests/golden/ssmd_breaks.utterplan.toml +0 -0
  174. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/__init__.py +0 -0
  175. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/basic_en.utterplan.json +0 -0
  176. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/directives.utterplan.json +0 -0
  177. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/markers.utterplan.json +0 -0
  178. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/multilingual.utterplan.json +0 -0
  179. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/parenthetical.utterplan.json +0 -0
  180. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/spokenform_offsets.utterplan.json +0 -0
  181. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/ssmd_09_comprehensive.utterplan.json +0 -0
  182. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/fixtures/v4/ssmd_breaks.utterplan.json +0 -0
  183. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/goldens/multilingual_preparation.json +0 -0
  184. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/goldens/spokenform_numbers.json +0 -0
  185. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/goldens/ssmd_break.json +0 -0
  186. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/goldens/ssmd_language_detection.json +0 -0
  187. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/goldens/ssmd_marker.json +0 -0
  188. {utterplan-0.5.1 → utterplan-0.6.2}/tests/migration/goldens/ssmd_pronunciation.json +0 -0
  189. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/basic.json +0 -0
  190. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/directives.json +0 -0
  191. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/markers.json +0 -0
  192. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/multilingual.json +0 -0
  193. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/parenthetical.json +0 -0
  194. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/spokenform_offsets.json +0 -0
  195. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v1/ssmd_breaks.json +0 -0
  196. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v2/directives.json +0 -0
  197. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v3/multilingual.json +0 -0
  198. {utterplan-0.5.1 → utterplan-0.6.2}/tests/schema_history/v3/ssmd_09_comprehensive.json +0 -0
  199. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_atomic_io.py +0 -0
  200. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_directives.py +0 -0
  201. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_language.py +0 -0
  202. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_migration_v3_to_v4.py +0 -0
  203. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_schema_strict.py +0 -0
  204. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_segmentation_adapter.py +0 -0
  205. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_sentence_topology.py +0 -0
  206. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_ssmdbook.py +0 -0
  207. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_token_topology.py +0 -0
  208. {utterplan-0.5.1 → utterplan-0.6.2}/tests/test_version.py +0 -0
  209. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/__main__.py +0 -0
  210. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/atomic_io.py +0 -0
  211. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/attempt_serialization.py +0 -0
  212. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/attempts.py +0 -0
  213. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/codecs/__init__.py +0 -0
  214. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/codecs/v4_toml.py +0 -0
  215. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/diagnostics.py +0 -0
  216. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/language.py +0 -0
  217. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migrations/registry.py +0 -0
  218. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migrations/v1_to_v2.py +0 -0
  219. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migrations/v2_to_v3.py +0 -0
  220. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/migrations/v3_to_v4.py +0 -0
  221. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/progress.py +0 -0
  222. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/py.typed +0 -0
  223. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/schemas/v1.schema.json +0 -0
  224. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/schemas/v2.schema.json +0 -0
  225. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/schemas/v3.schema.json +0 -0
  226. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/schemas/v4.schema.json +0 -0
  227. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/spacy_models.py +0 -0
  228. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/spans.py +0 -0
  229. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/ssmdbook.py +0 -0
  230. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/__init__.py +0 -0
  231. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/document/__init__.py +0 -0
  232. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/document/plain.py +0 -0
  233. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/document/ssmd.py +0 -0
  234. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/preparation/__init__.py +0 -0
  235. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/preparation/identity.py +0 -0
  236. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/stages/protocols.py +0 -0
  237. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/token_topology.py +0 -0
  238. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/trace_codec.py +0 -0
  239. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan/utterplan.schema.json +0 -0
  240. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/dependency_links.txt +0 -0
  241. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/entry_points.txt +0 -0
  242. {utterplan-0.5.1 → utterplan-0.6.2}/utterplan.egg-info/top_level.txt +0 -0
@@ -81,7 +81,8 @@ jobs:
81
81
  ]
82
82
  assert has_range(requirements, "phrasplit", "0.3.9", "0.4")
83
83
  assert has_range(requirements, "ssmd", "0.9.3", "0.10")
84
- assert has_range(requirements, "spokenform", "0.4.3", "0.5")
84
+ assert has_range(requirements, "ttsready", "0.2.3", "0.3")
85
+ assert has_range(requirements, "renderplan", "0.1.1", "0.2")
85
86
  names = set(archive.namelist())
86
87
  expected = {
87
88
  "utterplan/py.typed",
@@ -49,7 +49,9 @@ jobs:
49
49
  python -m pip install \
50
50
  "phrasplit==0.3.9" \
51
51
  "ssmd==0.9.3" \
52
- "spokenform==0.4.3" \
52
+ "ttsready==0.2.3" \
53
+ "spokenform==0.4.5" \
54
+ "renderplan==0.1.1" \
53
55
  "typing_extensions==4.0.0" \
54
56
  "tomlkit==0.13.0"
55
57
  python -m pip install --no-deps -e .
@@ -58,6 +60,26 @@ jobs:
58
60
  - name: Run lower-bound tests
59
61
  run: python -m pytest -q
60
62
 
63
+ latest-renderplan:
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+ - name: Set up Python
68
+ uses: actions/setup-python@v5
69
+ with:
70
+ python-version: "3.13"
71
+ - name: Install latest supported dependencies
72
+ run: |
73
+ python -m pip install --upgrade pip
74
+ python -m pip install -e ".[dev]"
75
+ - name: Run RenderPlan integration tests
76
+ run: >-
77
+ python -m pytest -q
78
+ tests/test_renderplan_batch.py
79
+ tests/test_renderplan_export.py
80
+ tests/test_renderplan_replan.py
81
+ tests/test_cli_render_book.py
82
+ tests/test_renderplan_dependency_contract.py
61
83
  package-smoke:
62
84
  runs-on: ubuntu-latest
63
85
  steps:
@@ -97,7 +119,8 @@ jobs:
97
119
  expected_ranges = {
98
120
  "phrasplit": ("0.3.9", "0.4"),
99
121
  "ssmd": ("0.9.3", "0.10"),
100
- "spokenform": ("0.4.3", "0.5"),
122
+ "ttsready": ("0.2.3", "0.3"),
123
+ "renderplan": ("0.1.1", "0.2"),
101
124
  }
102
125
 
103
126
  def check_metadata(contents):
@@ -146,8 +169,11 @@ jobs:
146
169
  "$RUNNER_TEMP"/dist/utterplan-*.whl
147
170
  - name: Run installed smoke checks
148
171
  run: |
172
+ cd "$RUNNER_TEMP"
149
173
  "$RUNNER_TEMP/utterplan-wheel-venv/bin/python" -c \
150
174
  "import importlib.metadata as m; import utterplan; assert m.version('utterplan') == utterplan.__version__"
175
+ "$RUNNER_TEMP/utterplan-wheel-venv/bin/python" -c \
176
+ "import utterplan.renderplan_batch; from renderplan import RenderPlanSet"
151
177
  "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" --version
152
178
  cat > "$RUNNER_TEMP/test.ssmd.md" <<'EOF'
153
179
  ---
@@ -163,6 +189,61 @@ jobs:
163
189
  > "$RUNNER_TEMP/test.utterplan.toml"
164
190
  "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" validate \
165
191
  "$RUNNER_TEMP/test.utterplan.toml"
192
+ BOOK="$RUNNER_TEMP/render-book.smoke.ssmdbook"
193
+ mkdir -p "$BOOK/chapters" "$BOOK/utterplan"
194
+ cat > "$BOOK/chapters/chapter-0001.ssmd.md" <<'EOF'
195
+ ---
196
+ ssmd_version: "0.9"
197
+ language: en-US
198
+ ---
199
+ Installed wheel render-book smoke.
200
+ EOF
201
+ cat > "$BOOK/manifest.json" <<'EOF'
202
+ {
203
+ "format": "ssmdconvert.book",
204
+ "schema_version": 1,
205
+ "ssmd_version": "0.9",
206
+ "chapters": [
207
+ {
208
+ "id": "chapter-0001",
209
+ "source_number": 1,
210
+ "path": "chapters/chapter-0001.ssmd.md",
211
+ "title": "Chapter 1"
212
+ }
213
+ ]
214
+ }
215
+ EOF
216
+ "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" compile \
217
+ "$BOOK/chapters/chapter-0001.ssmd.md" --lang en-us --text-preparation identity \
218
+ -o "$BOOK/utterplan/chapter-0001.utterplan.toml"
219
+ "$RUNNER_TEMP/utterplan-wheel-venv/bin/python" - "$BOOK/narration.renderprofile.toml" <<'PY'
220
+ import sys
221
+ from pathlib import Path
222
+
223
+ from renderplan import PausePolicy, PlanningPolicy, RenderProfile, RoleProfile
224
+ from renderplan import codec
225
+
226
+ profile = RenderProfile(
227
+ roles={"narrator": RoleProfile(language="en-US", binding={"engine": "smoke"})},
228
+ default_role="narrator",
229
+ planning=PlanningPolicy(split="sentence"),
230
+ pauses=PausePolicy(mode="manual"),
231
+ )
232
+ codec.save_profile(profile, Path(sys.argv[1]))
233
+ PY
234
+ "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" render-book \
235
+ "$BOOK" --profile "$BOOK/narration.renderprofile.toml" --chapters 1
236
+ "$RUNNER_TEMP/utterplan-wheel-venv/bin/python" - "$BOOK" <<'PY'
237
+ import sys
238
+ from pathlib import Path
239
+
240
+ from renderplan import load_renderplan_set
241
+
242
+ book = Path(sys.argv[1])
243
+ set_path = next((book / "renderplan").glob("*/renderplan-set.toml"))
244
+ renderplan_set = load_renderplan_set(set_path)
245
+ assert [chapter.id for chapter in renderplan_set.chapters] == ["chapter-0001"]
246
+ PY
166
247
  cat > "$RUNNER_TEMP/test-0.8.ssmd.md" <<'EOF'
167
248
  ---
168
249
  ssmd_version: "0.8"
@@ -177,8 +258,13 @@ jobs:
177
258
  exit 1
178
259
  fi
179
260
  grep -q "header.version_unsupported" "$RUNNER_TEMP/test-0.8.out"
180
- "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" migrate \
181
- "$GITHUB_WORKSPACE/tests/schema_history/v1/basic.json" --check
261
+ if "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" migrate \
262
+ "$GITHUB_WORKSPACE/tests/schema_history/v1/basic.json" --check > "$RUNNER_TEMP/migration-check.out" 2>&1; then
263
+ cat "$RUNNER_TEMP/migration-check.out"
264
+ echo "Expected historical schema migration to require recompilation" >&2
265
+ exit 1
266
+ fi
267
+ grep -q "migration.recompile_required" "$RUNNER_TEMP/migration-check.out"
182
268
  "$RUNNER_TEMP/utterplan-wheel-venv/bin/utterplan" inspect \
183
269
  "$RUNNER_TEMP/test.utterplan.toml" --segment 0
184
270
 
@@ -0,0 +1,29 @@
1
+ # AGENTS.md
2
+
3
+ <!-- Generated by memoryledger. Do not edit directly. -->
4
+ <!-- Source: memoryledger records; regenerate with `memoryledger render` and `memoryledger export`. -->
5
+
6
+ ## Project memory policy
7
+
8
+ This file contains reviewed long-term project memory.
9
+
10
+ ## Rules
11
+
12
+ - UtterPlan is engine-independent. Core code must not import PyKokoro, PiperSynth, kokorog2p, piperg2p, ONNX Runtime, audio packages, or any consumer package.
13
+ - UtterPlan ends before G2P. Engine/model selection, synthesis, and audio composition happen downstream.
14
+ - `.utterplan.toml` schema v7 is the current inter-package contract; schema-v5/v6 TOML and historical JSON schemas v1–v4 remain sequential migration inputs only, and only the current schema version is natively supported.
15
+ - Python objects may not contain semantic state that cannot survive file roundtrip.
16
+ - Public FlowPlan objects contain no phonemes, model token IDs, models, sessions, or audio; completed plans must not retain spaCy or provider documents.
17
+ - Every offset has a documented coordinate space.
18
+ - Default planning is deterministic; the same source and configuration always produce the same executable plan and `plan_id`.
19
+ - Schema changes require explicit compatibility review, frozen historical fixture coverage, deterministic migration tests, and package artifact checks.
20
+ - Released schema files are immutable and retained under versioned paths; schemas v5, v6, and v7 have no JSON Schema resources.
21
+ - Every supported older schema must retain a sequential migration path to current (v1 through v6 feed v7).
22
+ - Migrations operate on serialized plain data and may not call parser, planner, G2P, renderer, or audio stages.
23
+ - Package version and schema version remain independent. Migration preserves a compiled plan; replanning is a separate operation.
24
+ - Optional compiler traces are sidecars; they must never alter executable plan content or identity.
25
+ - UtterPlan parses SSMD 0.9 only; it does not parse SSMD 0.8 or migrate source documents (`ssmd migrate` owns that).
26
+ - Book commands (`compile-book`, `render-book`) read the SSMDBook manifest only for chapter discovery, never modify the manifest or source chapters, write derived plans to separate directories, and never build book-level combined plans.
27
+ - RenderPlan projection is optional: VoiceRender creates and validates engine-backed RenderProfiles, while UtterPlan projects stored schema-v7 FlowPlans into profile-specific RenderPlans (with `renderplan-set.toml` and reports) and performs deterministic replan refinement only.
28
+ - UtterPlan depends directly on SSMD, PhraseSplit, TTSReady, and the renderplan contract package only; production code does not import Spokenform, and spaCy stays optional best-effort enrichment.
29
+ - Repository tests must be self-contained and must not require sibling consumer checkouts; consumer-specific compatibility testing belongs in the consumer repository.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: utterplan
3
- Version: 0.5.1
3
+ Version: 0.6.2
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
@@ -224,9 +224,10 @@ License-File: LICENSE
224
224
  License-File: NOTICE
225
225
  Requires-Dist: phrasplit<0.4,>=0.3.9
226
226
  Requires-Dist: ssmd<0.10,>=0.9.3
227
- Requires-Dist: spokenform<0.5,>=0.4.3
227
+ Requires-Dist: ttsready<0.3,>=0.2.3
228
228
  Requires-Dist: typing_extensions>=4.0
229
229
  Requires-Dist: tomlkit<1,>=0.13
230
+ Requires-Dist: renderplan<0.2,>=0.1.1
230
231
  Provides-Extra: dev
231
232
  Requires-Dist: build; extra == "dev"
232
233
  Requires-Dist: jsonschema; extra == "dev"
@@ -250,9 +251,9 @@ Dynamic: license-file
250
251
 
251
252
  UtterPlan is the canonical, engine-independent semantic compiler from one SSMD
252
253
  document (or explicitly selected plain-text document) to an executable speech
253
- plan. It produces deterministic prepared text, ordered flow units, segment-local
254
- semantics, pause intents, portable document metadata, and typed directives for
255
- independent consumers such as ttsready and Readio. It does not manage or modify book workspaces; `compile-book` reads an SSMDBook manifest only to discover selected source chapters. It stops before G2P, synthesis, and audio.
254
+ plan. It produces deterministic prepared text, paragraph-local flow units, safe boundary opportunities, authored pause intents, and segment-local
255
+ semantics, portable document metadata, and typed directives for
256
+ independent downstream consumers such as Readio, VoiceRender, and other FlowPlan users. 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.
256
257
 
257
258
  ## CLI
258
259
 
@@ -282,7 +283,7 @@ Compile independent documents incrementally; every successful plan is saved imme
282
283
  utterplan compile-many examples/*.ssmd --output-dir build/plans
283
284
  ```
284
285
 
285
- This writes one `.utterplan.toml` per source plus an atomically refreshed `compile-report.toml`. Use `--fail-fast` to skip later inputs after a failure, `--force` to replace existing plans, or `--report PATH` to choose another report location.
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.
286
287
 
287
288
  Compile a selected chapter range directly from an editable SSMDBook workspace:
288
289
 
@@ -292,7 +293,7 @@ cd "Platform Decay - Martha Wells.ssmdbook"
292
293
  utterplan compile-book chapters --chapters 5-17
293
294
  ```
294
295
 
295
- The command reads the workspace manifest to discover chapters and writes independent v5 plans and a report under `utterplan/`:
296
+ The command reads the workspace manifest to discover chapters and writes independent v7 plans and a report under `utterplan/`:
296
297
 
297
298
  ```text
298
299
  utterplan/
@@ -303,7 +304,59 @@ utterplan/
303
304
  └── chapter-0017.utterplan.toml
304
305
  ```
305
306
 
306
- 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`. The book root itself is also accepted as input; see the [SSMDBook guide](docs/ssmdbook.md).
307
+ 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
+
309
+ ## From an SSMDBook to RenderPlans
310
+
311
+ UtterPlan keeps one canonical semantic plan per chapter. A RenderProfile is a
312
+ separate renderer configuration; create and validate it with VoiceRender, then
313
+ project the selected saved plans into a profile-specific RenderPlan collection:
314
+
315
+ ```bash
316
+ voicerender profile create \
317
+ --engine piper \
318
+ --target en_US-amy-medium \
319
+ --language en-US \
320
+ --offline \
321
+ --output narration.renderprofile.toml
322
+ voicerender profile validate narration.renderprofile.toml
323
+
324
+ utterplan compile-book . --chapters 5-17
325
+ utterplan render-book . --chapters 5-17 --profile narration.renderprofile.toml
326
+ ```
327
+
328
+ The book's `utterplan/` directory remains the shared semantic source. The new
329
+ command writes independent renderer-specific plans into a deterministic variant:
330
+
331
+ ```text
332
+ renderplan/
333
+ └── narration--<profile-fingerprint>/
334
+ ├── renderprofile.toml
335
+ ├── renderplan-set.toml
336
+ ├── render-report.toml
337
+ ├── chapter-0005.renderplan.toml
338
+ └── ...
339
+ ```
340
+
341
+ The variant label comes from the profile filename by default; its suffix is the
342
+ first 12 hexadecimal characters of the canonical RenderProfile `profile_id`.
343
+ Changing identity-bearing profile semantics selects a different directory, so
344
+ multiple voices or planning policies can coexist without replacing one another.
345
+ Each variant snapshots the canonical profile; `renderplan-set.toml` records its
346
+ full identity, source profile reference, and chapter plan IDs. `--variant` changes
347
+ the human label without removing the fingerprint, and `--output-root` changes the
348
+ collection root while retaining the automatic variant directory.
349
+
350
+ `render-book` consumes only the existing schema-v7 UtterPlans and shared
351
+ RenderProfile/RenderPlan contract. VoiceRender is not required to run it: VoiceRender
352
+ creates or refreshes engine-backed profiles, then preflights and renders the
353
+ resulting RenderPlans. The single-file `utterplan render-plan` command remains the
354
+ low-level projection and deterministic replan primitive.
355
+
356
+ Related packages: [RenderPlan](https://pypi.org/project/renderplan/) defines the
357
+ shared profile and plan contracts; [VoiceRender](https://pypi.org/project/voicerender/)
358
+ creates engine-backed profiles and performs preflight and synthesis.
359
+
307
360
  The CLI also provides:
308
361
 
309
362
  ```bash
@@ -314,10 +367,14 @@ utterplan inspect chapter.utterplan.toml --boundaries --tokens
314
367
  utterplan explain chapter.utterplan.toml --trace chapter.trace.toml
315
368
  utterplan inspect-trace chapter.trace.toml --preparation --boundaries
316
369
  utterplan inspect-attempt chapter.attempt.toml --issues
370
+ utterplan preview chapter.utterplan.toml --segments 58-62 --chunk-by clause --pause-policy automatic
371
+ utterplan render-plan chapter.utterplan.toml --profile voice.renderprofile.toml -o chapter.renderplan.toml --explain
317
372
  ```
318
373
 
319
374
  `explain` presents executable flow as a human-readable speech plan. Use `compile --trace PATH` to retain optional compiler provenance; `explain --trace PATH` and `inspect-trace` read that sidecar separately from the plan.
320
375
 
376
+ `render-plan` projects only current schema-v7 FlowPlans into the shared RenderPlan contract. Replanning requires both the exact previous RenderPlan and its matching preflight report; UtterPlan refines only failed speech occurrences and does not calculate renderer-specific metrics.
377
+
321
378
  `inspect-attempt` reads the separate `utterplan.planning-attempt.v1` TOML artifact,
322
379
  not a canonical plan. Use it to review renderability issues and safe repair
323
380
  assessments on blocked planning outcomes; such candidates remain inspect-only drafts.
@@ -337,18 +394,18 @@ command:
337
394
  ssmd migrate old.ssmd --to 0.9
338
395
  ```
339
396
 
340
- `utterplan migrate` explicitly imports supported historical `.utterplan.json` plans and writes current TOML. It does not migrate SSMD source.
397
+ `utterplan migrate` handles only serialized plan data; v6-to-v7 migration refuses with `migration.recompile_required` when the saved plan cannot prove complete boundary coverage. Recompile the original source to produce a current plan. It does not migrate SSMD source.
341
398
  Normal plan loading is TOML-only: `FlowPlan.load()` and plan-inspection commands reject JSON rather than auto-detecting it.
342
399
 
343
400
  ## Planning defaults
344
401
 
345
- The minimal CLI defaults are explicit: `spokenform` is the default text-preparation backend, `tts` is the default pause activation mode, and `spacy off` is the default linguistic-resource policy. With `spacy off`, UtterPlan uses its deterministic fallback tokenizer and analysis and does not depend on an installed spaCy model.
402
+ The CLI and Python planner default to best-effort spaCy enrichment (`auto`). UtterPlan prefers an already-installed compatible model in `sm`, `md`, `lg`, `trf` order; if spaCy or every compatible local model is unavailable, planning continues with deterministic fallback tokens. UtterPlan never downloads models. Use `--spacy off` or `LinguisticsConfig(use_spacy=False)` to opt out, or request an explicit tier to require that local model.
346
403
 
347
404
  Python `PlannerConfig` defaults to `document_format="plain"`; set it to `"ssmd"` when a Python string contains SSMD source.
348
405
 
349
406
  Python `PlannerConfig.renderability_mode` also defaults to safe punctuation-only repair; choose `"strict"` to reject every repair opportunity. Neither mode guesses a symbol's pronunciation or crosses semantic blockers.
350
407
 
351
- `spacy auto` is opt-in. When enabled and a compatible local model is available, UtterPlan may expose richer tokenization, POS tags, lemmas, and tags; `auto` is not the default.
408
+ V7 `token.span`, `pos`, `tag`, `lemma`, and `morph` describe the prepared `segment.text` and are the downstream linguistic context, not engine/model token counts; consumers should not retokenize or rerun spaCy. Optional `replacement.span` / `replacement.source` records compact preparation provenance (for example, `A R T` from `ART`): spans index final prepared segment text, while full source coordinates and maps remain in the optional trace sidecar. Replacement provenance does not change executable hashes or synthesis inputs.
352
409
 
353
410
  ## Python API
354
411
 
@@ -380,6 +437,20 @@ identity. Plain text must be explicitly selected in Python and always requires a
380
437
  language fallback. Existing `UtterancePlanner.plan` remains supported and returns
381
438
  only the plan; TOML is the portable persistence and interchange format.
382
439
 
440
+ The optional RenderPlan producer consumes the stored prepared plan directly:
441
+
442
+ ```python
443
+ from renderplan.codec import load_profile, save_plan
444
+ from utterplan import FlowPlan, build_render_plan
445
+
446
+ source = FlowPlan.load("chapter.utterplan.toml")
447
+ profile = load_profile("voice.renderprofile.toml")
448
+ render_plan = build_render_plan(source, profile)
449
+ save_plan(render_plan, "chapter.renderplan.toml")
450
+ ```
451
+
452
+ Use `build_render_plan(..., previous_plan=previous, preflight=report)` for deterministic refinement; both values are required together. The RenderPlan path rejects historical UtterPlan schemas and does not depend on a renderer or audio runtime. See the [RenderPlan CLI](docs/cli.md#produce-or-replan-a-renderplan) and [Python API](docs/python-api.md#build-and-replan-a-renderplan) guides.
453
+
383
454
  For operational progress from a long-running Python plan, pass `on_progress` to
384
455
  `UtterancePlanner.plan`, `UtterancePlanner.compile`, or `compile_document`. The
385
456
  callback receives typed `PlannerProgressEvent` objects and does not change the plan:
@@ -398,7 +469,16 @@ Callbacks run synchronously and exceptions propagate. See the [Python API guide]
398
469
 
399
470
  ## Renderer-consumer boundary
400
471
 
401
- Renderers consume `FlowPlan.flow` in order. Each `FlowUnit` contains local `FlowSegment` objects with already-prepared speech text, effective language, segment-local token views, semantic pause intents, directives, markers, and optional heading level. Token `start`/`end` offsets are Python-character indexes into that segment's `text`; they are never document-global coordinates. Pause intents express `none`, semantic strengths, or exact authored times and do not prescribe engine-specific duration policy.
472
+ Renderers consume `FlowPlan.flow` in order. Each `FlowUnit` contains local `FlowSegment` objects with already-prepared speech text, effective language, segment-local linguistic token views, canonical boundary opportunities, authored pause intents, directives, markers, and optional heading level. Token `start`/`end` offsets are Python-character indexes into that segment's `text`; they are never document-global coordinates. FlowUnits are fixed paragraph-local blocks, not renderer chunks; a `FlowSegment` is not necessarily one TTS call. `boundary_before` / `boundary_after` hold safe cut opportunities independently from authored `none`, strength, or timed pause intents. Consumers may choose sentence, paragraph, or engine-token-budget chunking and native, automatic, or manual pause realization; linguistic token views are not model-token counts.
473
+
474
+ For renderer-neutral chunk tests and debugging, `preview_plan()` projects stored text and boundaries without changing the plan:
475
+
476
+ ```python
477
+ from utterplan import FlowPlan, preview_plan
478
+
479
+ plan = FlowPlan.load("chapter.utterplan.toml")
480
+ chunks = preview_plan(plan, chunk_by="clause", pause_policy="automatic")
481
+ ```
402
482
 
403
483
  `FlowPlan.document` carries compact document metadata and `FlowPlan.linguistics` identifies the analysis provider without retaining provider documents. Compiler source, preparation maps, diagnostics, and renderability details belong only in an optional trace sidecar. Plans contain no phonemes, model token IDs, models, sessions, renderer configuration, provider documents, or audio. UtterPlan does not fetch media or execute extension handlers.
404
484
  The intended dependency direction is:
@@ -427,9 +507,9 @@ renderer repository rather than UtterPlan's test suite.
427
507
 
428
508
  ## Versions
429
509
 
430
- The package version is dynamically derived from Git tags by setuptools-scm. Package version and UtterPlan schema version are independent. Current `.utterplan.toml` plans use semantic schema v5. Historical JSON Schemas v1–v4 remain immutable and supported through sequential migrations; v5 deliberately has no JSON Schema resource because its canonical executable contract is the validated TOML/FlowPlan model.
510
+ The package version is dynamically derived from Git tags by setuptools-scm. Package version and UtterPlan schema version are independent. Current `.utterplan.toml` plans use semantic schema v7. Historical JSON Schemas v1–v4 remain immutable; schemas v5, v6, and v7 use versioned TOML/FlowPlan contracts and have no JSON Schema resources.
431
511
 
432
- Schema v5 is a breaking redesign around ordered flow units and segment-local semantics. It preserves deterministic output and moves preparation/source provenance to an optional TOML trace sidecar, which does not affect plan identity. Migration converts serialized plan data only: v1–v4 migrate sequentially to v5 without reparsing, NLP, planning, G2P, rendering, or audio processing. The v4-to-v5 projection fails safely when historical token coordinates or pause semantics cannot be verified.
512
+ Schema v5 introduced ordered flow units and segment-local semantics; v6 added optional exact-source provenance. Schema v7 removes renderer-selected root `unit` and adds canonical safe-boundary opportunities separate from authored pause intents; boundaries participate in v7 executable identity. Older schemas retain sequential data-only migration steps through v6, but v6-to-v7 returns `migration.recompile_required` because the complete boundary inventory cannot be reconstructed. Migrations never reparse, run NLP, plan, call G2P, render, or process audio.
433
513
 
434
514
  ## Development
435
515