utterplan 0.4.1__tar.gz → 0.5.0__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 (212) hide show
  1. {utterplan-0.4.1 → utterplan-0.5.0}/AGENTS.md +4 -3
  2. {utterplan-0.4.1 → utterplan-0.5.0}/PKG-INFO +37 -29
  3. {utterplan-0.4.1 → utterplan-0.5.0}/README.md +36 -28
  4. utterplan-0.5.0/docs/architecture.md +63 -0
  5. {utterplan-0.4.1 → utterplan-0.5.0}/docs/changelog.md +12 -0
  6. {utterplan-0.4.1 → utterplan-0.5.0}/docs/cli.md +36 -12
  7. utterplan-0.5.0/docs/consumer-guide.md +92 -0
  8. utterplan-0.5.0/docs/coordinate-spaces.md +22 -0
  9. utterplan-0.5.0/docs/debugging.md +28 -0
  10. utterplan-0.5.0/docs/format.md +62 -0
  11. {utterplan-0.4.1 → utterplan-0.5.0}/docs/getting-started.md +33 -15
  12. {utterplan-0.4.1 → utterplan-0.5.0}/docs/index.md +1 -0
  13. utterplan-0.5.0/docs/pykokoro-integration.md +46 -0
  14. {utterplan-0.4.1 → utterplan-0.5.0}/docs/python-api.md +67 -56
  15. utterplan-0.5.0/docs/ssmdbook.md +72 -0
  16. {utterplan-0.4.1 → utterplan-0.5.0}/examples/compile_file.py +1 -1
  17. {utterplan-0.4.1 → utterplan-0.5.0}/examples/inspect_plan.py +6 -5
  18. {utterplan-0.4.1 → utterplan-0.5.0}/examples/multilingual.py +1 -1
  19. utterplan-0.5.0/tests/compiler_helpers.py +36 -0
  20. utterplan-0.5.0/tests/fixtures/canonical_consumer_contract.expected.toml +35 -0
  21. utterplan-0.5.0/tests/migration/test_legacy_json_import.py +38 -0
  22. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/test_semantic_migration_regressions.py +35 -8
  23. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_batch.py +10 -6
  24. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_boundaries.py +2 -1
  25. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_cli.py +66 -42
  26. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_cli_batch.py +9 -4
  27. utterplan-0.5.0/tests/test_cli_ssmdbook.py +431 -0
  28. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_compiler.py +39 -17
  29. utterplan-0.5.0/tests/test_consumer_contract.py +182 -0
  30. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_consumer_readiness.py +19 -38
  31. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_coordinates.py +2 -1
  32. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_directives.py +3 -6
  33. utterplan-0.5.0/tests/test_explain.py +121 -0
  34. utterplan-0.5.0/tests/test_fake_renderer.py +133 -0
  35. utterplan-0.5.0/tests/test_flow_compilation.py +97 -0
  36. utterplan-0.5.0/tests/test_format.py +110 -0
  37. utterplan-0.5.0/tests/test_golden.py +65 -0
  38. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_identity_units.py +2 -1
  39. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_linguistics.py +59 -11
  40. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_migration_framework.py +3 -3
  41. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_migration_v3_to_v4.py +6 -6
  42. utterplan-0.5.0/tests/test_migration_v4_to_v5.py +179 -0
  43. utterplan-0.5.0/tests/test_pauses.py +213 -0
  44. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_planner.py +7 -5
  45. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_preparation.py +10 -5
  46. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_progress.py +3 -3
  47. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_public_identity.py +3 -3
  48. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_renderability.py +1 -1
  49. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_renderability_repair.py +3 -5
  50. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_schema_history.py +10 -7
  51. utterplan-0.5.0/tests/test_schema_registry.py +54 -0
  52. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_schema_strict.py +4 -2
  53. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_segment_topology.py +4 -3
  54. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_semantic_boundaries.py +2 -2
  55. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_ssmd_09_parser.py +15 -20
  56. utterplan-0.5.0/tests/test_ssmdbook.py +279 -0
  57. utterplan-0.5.0/tests/test_toml_format.py +226 -0
  58. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/__init__.py +18 -4
  59. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/_version.py +3 -3
  60. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/attempt_serialization.py +17 -12
  61. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/batch.py +4 -7
  62. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/cli.py +414 -126
  63. utterplan-0.5.0/utterplan/codecs/__init__.py +1 -0
  64. utterplan-0.4.1/utterplan/toml_codec.py → utterplan-0.5.0/utterplan/codecs/v4_toml.py +50 -31
  65. utterplan-0.5.0/utterplan/codecs/v5_toml.py +504 -0
  66. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/compiler.py +41 -5
  67. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/config.py +0 -54
  68. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/explain.py +156 -54
  69. utterplan-0.5.0/utterplan/flow_projection.py +276 -0
  70. utterplan-0.5.0/utterplan/format.py +48 -0
  71. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/hashing.py +92 -2
  72. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/migration.py +1 -1
  73. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/migrations/__init__.py +2 -0
  74. utterplan-0.5.0/utterplan/migrations/v4_to_v5.py +580 -0
  75. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/model.py +737 -58
  76. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/parsers.py +15 -117
  77. utterplan-0.5.0/utterplan/pauses.py +108 -0
  78. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/planner.py +48 -45
  79. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/preparation.py +7 -7
  80. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/renderability.py +8 -1
  81. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/schema_registry.py +7 -5
  82. utterplan-0.5.0/utterplan/serialization.py +40 -0
  83. utterplan-0.5.0/utterplan/ssmdbook.py +259 -0
  84. utterplan-0.5.0/utterplan/toml_codec.py +100 -0
  85. utterplan-0.5.0/utterplan/trace_codec.py +137 -0
  86. utterplan-0.5.0/utterplan/versioning.py +11 -0
  87. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/PKG-INFO +37 -29
  88. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/SOURCES.txt +13 -0
  89. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/scm_file_list.json +24 -0
  90. utterplan-0.5.0/utterplan.egg-info/scm_version.json +8 -0
  91. utterplan-0.4.1/docs/architecture.md +0 -110
  92. utterplan-0.4.1/docs/consumer-guide.md +0 -149
  93. utterplan-0.4.1/docs/coordinate-spaces.md +0 -16
  94. utterplan-0.4.1/docs/debugging.md +0 -31
  95. utterplan-0.4.1/docs/format.md +0 -39
  96. utterplan-0.4.1/docs/pykokoro-integration.md +0 -63
  97. utterplan-0.4.1/tests/fixtures/canonical_consumer_contract.expected.toml +0 -6
  98. utterplan-0.4.1/tests/migration/test_legacy_json_import.py +0 -29
  99. utterplan-0.4.1/tests/test_consumer_contract.py +0 -313
  100. utterplan-0.4.1/tests/test_explain.py +0 -180
  101. utterplan-0.4.1/tests/test_fake_renderer.py +0 -72
  102. utterplan-0.4.1/tests/test_format.py +0 -114
  103. utterplan-0.4.1/tests/test_golden.py +0 -64
  104. utterplan-0.4.1/tests/test_pauses.py +0 -212
  105. utterplan-0.4.1/tests/test_schema_registry.py +0 -54
  106. utterplan-0.4.1/tests/test_toml_format.py +0 -179
  107. utterplan-0.4.1/utterplan/format.py +0 -46
  108. utterplan-0.4.1/utterplan/pauses.py +0 -76
  109. utterplan-0.4.1/utterplan/serialization.py +0 -32
  110. utterplan-0.4.1/utterplan/versioning.py +0 -8
  111. utterplan-0.4.1/utterplan.egg-info/scm_version.json +0 -8
  112. {utterplan-0.4.1 → utterplan-0.5.0}/.codecrate.toml +0 -0
  113. {utterplan-0.4.1 → utterplan-0.5.0}/.github/workflows/codecov.yml +0 -0
  114. {utterplan-0.4.1 → utterplan-0.5.0}/.github/workflows/pre-commit.yml +0 -0
  115. {utterplan-0.4.1 → utterplan-0.5.0}/.github/workflows/python-publish.yml +0 -0
  116. {utterplan-0.4.1 → utterplan-0.5.0}/.github/workflows/tests.yml +0 -0
  117. {utterplan-0.4.1 → utterplan-0.5.0}/.gitignore +0 -0
  118. {utterplan-0.4.1 → utterplan-0.5.0}/.pre-commit-config.yaml +0 -0
  119. {utterplan-0.4.1 → utterplan-0.5.0}/LICENSE +0 -0
  120. {utterplan-0.4.1 → utterplan-0.5.0}/MANIFEST.in +0 -0
  121. {utterplan-0.4.1 → utterplan-0.5.0}/NOTICE +0 -0
  122. {utterplan-0.4.1 → utterplan-0.5.0}/docs/Makefile +0 -0
  123. {utterplan-0.4.1 → utterplan-0.5.0}/docs/conf.py +0 -0
  124. {utterplan-0.4.1 → utterplan-0.5.0}/docs/make.bat +0 -0
  125. {utterplan-0.4.1 → utterplan-0.5.0}/docs/phase-a-completion.md +0 -0
  126. {utterplan-0.4.1 → utterplan-0.5.0}/docs/requirements.txt +0 -0
  127. {utterplan-0.4.1 → utterplan-0.5.0}/examples/basic.py +0 -0
  128. {utterplan-0.4.1 → utterplan-0.5.0}/examples/chapter.ssmd +0 -0
  129. {utterplan-0.4.1 → utterplan-0.5.0}/examples/ssmd_example.py +0 -0
  130. {utterplan-0.4.1 → utterplan-0.5.0}/pyproject.toml +0 -0
  131. {utterplan-0.4.1 → utterplan-0.5.0}/setup.cfg +0 -0
  132. {utterplan-0.4.1 → utterplan-0.5.0}/spec/schemas/v1.schema.json +0 -0
  133. {utterplan-0.4.1 → utterplan-0.5.0}/spec/schemas/v2.schema.json +0 -0
  134. {utterplan-0.4.1 → utterplan-0.5.0}/spec/schemas/v3.schema.json +0 -0
  135. {utterplan-0.4.1 → utterplan-0.5.0}/spec/schemas/v4.schema.json +0 -0
  136. {utterplan-0.4.1 → utterplan-0.5.0}/spec/utterplan.schema.json +0 -0
  137. {utterplan-0.4.1 → utterplan-0.5.0}/tests/__init__.py +0 -0
  138. {utterplan-0.4.1 → utterplan-0.5.0}/tests/fixtures/canonical_consumer_contract.ssmd +0 -0
  139. {utterplan-0.4.1 → utterplan-0.5.0}/tests/fixtures/ssmd_09_comprehensive.ssmd +0 -0
  140. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/basic_en.utterplan.toml +0 -0
  141. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/directives.utterplan.toml +0 -0
  142. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/markers.utterplan.toml +0 -0
  143. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/multilingual.utterplan.toml +0 -0
  144. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/parenthetical.utterplan.toml +0 -0
  145. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/spokenform_offsets.utterplan.toml +0 -0
  146. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/ssmd_09_comprehensive.utterplan.toml +0 -0
  147. {utterplan-0.4.1 → utterplan-0.5.0}/tests/golden/ssmd_breaks.utterplan.toml +0 -0
  148. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/__init__.py +0 -0
  149. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/cases.py +0 -0
  150. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/basic_en.utterplan.json +0 -0
  151. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/directives.utterplan.json +0 -0
  152. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/markers.utterplan.json +0 -0
  153. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/multilingual.utterplan.json +0 -0
  154. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/parenthetical.utterplan.json +0 -0
  155. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/spokenform_offsets.utterplan.json +0 -0
  156. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/ssmd_09_comprehensive.utterplan.json +0 -0
  157. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/fixtures/v4/ssmd_breaks.utterplan.json +0 -0
  158. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/goldens/multilingual_preparation.json +0 -0
  159. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/goldens/spokenform_numbers.json +0 -0
  160. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/goldens/ssmd_break.json +0 -0
  161. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/goldens/ssmd_language_detection.json +0 -0
  162. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/goldens/ssmd_marker.json +0 -0
  163. {utterplan-0.4.1 → utterplan-0.5.0}/tests/migration/goldens/ssmd_pronunciation.json +0 -0
  164. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/README.md +0 -0
  165. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/basic.json +0 -0
  166. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/directives.json +0 -0
  167. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/markers.json +0 -0
  168. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/multilingual.json +0 -0
  169. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/parenthetical.json +0 -0
  170. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/spokenform_offsets.json +0 -0
  171. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v1/ssmd_breaks.json +0 -0
  172. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v2/directives.json +0 -0
  173. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v3/multilingual.json +0 -0
  174. {utterplan-0.4.1 → utterplan-0.5.0}/tests/schema_history/v3/ssmd_09_comprehensive.json +0 -0
  175. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_atomic_io.py +0 -0
  176. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_import_boundaries.py +0 -0
  177. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_language.py +0 -0
  178. {utterplan-0.4.1 → utterplan-0.5.0}/tests/test_version.py +0 -0
  179. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/__main__.py +0 -0
  180. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/atomic_io.py +0 -0
  181. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/attempts.py +0 -0
  182. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/diagnostics.py +0 -0
  183. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/directives.py +0 -0
  184. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/exceptions.py +0 -0
  185. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/language.py +0 -0
  186. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/linguistics.py +0 -0
  187. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/migrations/registry.py +0 -0
  188. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/migrations/v1_to_v2.py +0 -0
  189. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/migrations/v2_to_v3.py +0 -0
  190. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/migrations/v3_to_v4.py +0 -0
  191. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/progress.py +0 -0
  192. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/py.typed +0 -0
  193. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/schemas/v1.schema.json +0 -0
  194. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/schemas/v2.schema.json +0 -0
  195. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/schemas/v3.schema.json +0 -0
  196. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/schemas/v4.schema.json +0 -0
  197. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/spacy_models.py +0 -0
  198. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/spans.py +0 -0
  199. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/__init__.py +0 -0
  200. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/document/__init__.py +0 -0
  201. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/document/plain.py +0 -0
  202. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/document/ssmd.py +0 -0
  203. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/preparation/__init__.py +0 -0
  204. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/preparation/identity.py +0 -0
  205. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/preparation/spokenform.py +0 -0
  206. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/stages/protocols.py +0 -0
  207. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/units.py +0 -0
  208. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan/utterplan.schema.json +0 -0
  209. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/dependency_links.txt +0 -0
  210. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/entry_points.txt +0 -0
  211. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/requires.txt +0 -0
  212. {utterplan-0.4.1 → utterplan-0.5.0}/utterplan.egg-info/top_level.txt +0 -0
@@ -1,19 +1,20 @@
1
1
  # UtterPlan development rules
2
2
 
3
3
  1. UtterPlan is engine-independent.
4
- 2. `.utterplan.json` schema v1 is the canonical inter-package contract.
4
+ 2. `.utterplan.toml` schema v5 is the current inter-package contract; historical JSON schemas v1–v4 remain migration inputs only.
5
5
  3. Python objects may not contain semantic state that cannot survive file roundtrip.
6
6
  4. UtterPlan ends before G2P.
7
7
  5. Core code must not import PyKokoro, PiperSynth, kokorog2p, piperg2p, ONNX Runtime, or audio packages.
8
- 6. Public UtterancePlan objects contain no phonemes, model token IDs, models, sessions, or audio.
8
+ 6. Public FlowPlan objects contain no phonemes, model token IDs, models, sessions, or audio.
9
9
  7. Completed plans must not retain spaCy or provider documents.
10
10
  8. Every offset has a documented coordinate space.
11
11
  9. Default planning is deterministic.
12
12
  10. Schema changes require explicit compatibility review.
13
13
  11. Repository tests must be self-contained and must not require sibling consumer checkouts.
14
14
  12. Consumer-specific compatibility testing belongs in the consumer repository.
15
- 13. Released schema files are immutable and retained under versioned paths.
15
+ 13. Released schema files are immutable and retained under versioned paths; v5 has no historical JSON Schema resource.
16
16
  14. Every supported older schema must retain a sequential migration path to current.
17
17
  15. Migrations operate on serialized plain data and may not call parser, planner, G2P, renderer, or audio stages.
18
18
  16. Schema changes require frozen historical fixture coverage, deterministic migration tests, and package artifact checks.
19
19
  17. Package version and schema version remain independent. Migration preserves a compiled plan; replanning is a separate operation.
20
+ 18. Optional compiler traces are sidecars; they must never alter executable plan content or identity.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: utterplan
3
- Version: 0.4.1
3
+ Version: 0.5.0
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
@@ -250,10 +250,9 @@ Dynamic: license-file
250
250
 
251
251
  UtterPlan is the canonical, engine-independent semantic compiler from one SSMD
252
252
  document (or explicitly selected plain-text document) to an executable speech
253
- plan. It produces deterministic language runs, prepared text, segments, resolved
254
- pauses, portable metadata, directives, markers, and render units shared by
255
- independent consumers such as ttsready and Readio. It does not manage books or
256
- consumer workspaces, and stops before G2P, synthesis, and audio.
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.
257
256
 
258
257
  ## CLI
259
258
 
@@ -285,18 +284,39 @@ utterplan compile-many examples/*.ssmd --output-dir build/plans
285
284
 
286
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.
287
286
 
287
+ Compile a selected chapter range directly from an editable SSMDBook workspace:
288
+
289
+ ```bash
290
+ cd "Platform Decay - Martha Wells.ssmdbook"
291
+
292
+ utterplan compile-book chapters --chapters 5-17
293
+ ```
294
+
295
+ The command reads the workspace manifest to discover chapters and writes independent v5 plans and a report under `utterplan/`:
296
+
297
+ ```text
298
+ utterplan/
299
+ ├── compile-report.toml
300
+ ├── chapter-0005.utterplan.toml
301
+ ├── chapter-0006.utterplan.toml
302
+ ├── ...
303
+ └── chapter-0017.utterplan.toml
304
+ ```
305
+
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).
288
307
  The CLI also provides:
289
308
 
290
309
  ```bash
291
310
  utterplan --version
292
311
  utterplan validate chapter.utterplan.toml
293
312
  utterplan inspect chapter.utterplan.toml --segment 0
294
- utterplan inspect chapter.utterplan.toml --semantic-boundaries
295
- utterplan explain chapter.utterplan.toml
313
+ utterplan inspect chapter.utterplan.toml --boundaries --tokens
314
+ utterplan explain chapter.utterplan.toml --trace chapter.trace.toml
315
+ utterplan inspect-trace chapter.trace.toml --preparation --boundaries
296
316
  utterplan inspect-attempt chapter.attempt.toml --issues
297
317
  ```
298
318
 
299
- `explain` presents the compiled plan as a human-readable speech plan, while `inspect` exposes lower-level diagnostic fields.
319
+ `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.
300
320
 
301
321
  `inspect-attempt` reads the separate `utterplan.planning-attempt.v1` TOML artifact,
302
322
  not a canonical plan. Use it to review renderability issues and safe repair
@@ -318,11 +338,11 @@ ssmd migrate old.ssmd --to 0.9
318
338
  ```
319
339
 
320
340
  `utterplan migrate` explicitly imports supported historical `.utterplan.json` plans and writes current TOML. It does not migrate SSMD source.
321
- Normal plan loading is TOML-only: `UtterancePlan.load()` and plan-inspection commands reject JSON rather than auto-detecting it.
341
+ Normal plan loading is TOML-only: `FlowPlan.load()` and plan-inspection commands reject JSON rather than auto-detecting it.
322
342
 
323
343
  ## Planning defaults
324
344
 
325
- The minimal CLI defaults are explicit: `spokenform` is the default text-preparation backend, `tts` is the default pause 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.
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.
326
346
 
327
347
  Python `PlannerConfig` defaults to `document_format="plain"`; set it to `"ssmd"` when a Python string contains SSMD source.
328
348
 
@@ -333,7 +353,7 @@ Python `PlannerConfig.renderability_mode` also defaults to safe punctuation-only
333
353
  ## Python API
334
354
 
335
355
  ```python
336
- from utterplan import PlannerConfig, UtterancePlan, compile_document
356
+ from utterplan import PlannerConfig, FlowPlan, compile_document
337
357
 
338
358
  ssmd_source = """---
339
359
  ssmd_version: "0.9"
@@ -350,7 +370,7 @@ result = compile_document(
350
370
  plan = result.plan
351
371
  assert result.trace is not None
352
372
  plan.save("example.utterplan.toml")
353
- assert UtterancePlan.load("example.utterplan.toml") == plan
373
+ assert FlowPlan.load("example.utterplan.toml") == plan
354
374
  ```
355
375
 
356
376
  `compile_document` is the stable public one-document API shared by consumers. The
@@ -378,21 +398,9 @@ Callbacks run synchronously and exceptions propagate. See the [Python API guide]
378
398
 
379
399
  ## Renderer-consumer boundary
380
400
 
381
- Renderers consume `PlanSegment.text`, which is prepared/spoken text, and use
382
- `spoken_start`/`spoken_end` for spoken-text coordinates. Resolved segment
383
- pauses, language, directives, annotations, boundaries, semantic boundaries,
384
- markers, units, and
385
- document metadata are public plan fields. Semantic boundaries are stable
386
- engine-neutral opportunities for spoken-text subdivision; they are not pause
387
- events and carry no duration or renderer policy. Plans contain no phonemes, model
388
- tokens, model sessions, renderer configuration, provider documents, or audio.
389
- For SSMD input, `plan.annotations` preserve declared source semantics and source
390
- provenance, `document_metadata` preserves portable header data, and
391
- `segment.directives` carries effective typed semantics after scope and voice-default
392
- resolution. Typed directives include voice, pronunciation, prosody, emphasis, say-as,
393
- substitution, audio references, and extension references. Audio and extensions are
394
- data only. UtterPlan does not fetch media or execute extension handlers.
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.
395
402
 
403
+ `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.
396
404
  The intended dependency direction is:
397
405
 
398
406
  ```text
@@ -407,6 +415,7 @@ renderer repository rather than UtterPlan's test suite.
407
415
 
408
416
  - [Getting started](docs/getting-started.md)
409
417
  - [CLI](docs/cli.md)
418
+ - [SSMDBook workflows](docs/ssmdbook.md)
410
419
  - [Format and schema](docs/format.md)
411
420
  - [Consumer guide](docs/consumer-guide.md)
412
421
  - [Architecture](docs/architecture.md)
@@ -418,10 +427,9 @@ renderer repository rather than UtterPlan's test suite.
418
427
 
419
428
  ## Versions
420
429
 
421
- 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 v4; released schema v1, v2, and v3 remain immutable and supported through sequential migrations.
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.
422
431
 
423
- Schema v4 adds stable `SemanticBoundary` records in spoken-text coordinates. Migration converts serialized plan data only: the registered v3-to-v4 step preserves existing evidence and derives topology where possible, but does not rerun parsing, NLP, planning, G2P, rendering, or audio processing. Unit hashes use `utterplan-unit-v3` and include relative semantic-boundary positions; older hash algorithms remain available for their historical migration paths.
424
- Schema v4 retains typed renderer-neutral SSMD semantics, final pass-B token facts, and per-language-run provider provenance. Plans never serialize provider documents, models, sessions, phonemes, token IDs, or audio.
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.
425
433
 
426
434
  ## Development
427
435
 
@@ -7,10 +7,9 @@
7
7
 
8
8
  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
- plan. It produces deterministic language runs, prepared text, segments, resolved
11
- pauses, portable metadata, directives, markers, and render units shared by
12
- independent consumers such as ttsready and Readio. It does not manage books or
13
- consumer workspaces, and stops before G2P, synthesis, and audio.
10
+ plan. It produces deterministic prepared text, ordered flow units, segment-local
11
+ semantics, pause intents, portable document metadata, and typed directives for
12
+ 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.
14
13
 
15
14
  ## CLI
16
15
 
@@ -42,18 +41,39 @@ utterplan compile-many examples/*.ssmd --output-dir build/plans
42
41
 
43
42
  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.
44
43
 
44
+ Compile a selected chapter range directly from an editable SSMDBook workspace:
45
+
46
+ ```bash
47
+ cd "Platform Decay - Martha Wells.ssmdbook"
48
+
49
+ utterplan compile-book chapters --chapters 5-17
50
+ ```
51
+
52
+ The command reads the workspace manifest to discover chapters and writes independent v5 plans and a report under `utterplan/`:
53
+
54
+ ```text
55
+ utterplan/
56
+ ├── compile-report.toml
57
+ ├── chapter-0005.utterplan.toml
58
+ ├── chapter-0006.utterplan.toml
59
+ ├── ...
60
+ └── chapter-0017.utterplan.toml
61
+ ```
62
+
63
+ 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).
45
64
  The CLI also provides:
46
65
 
47
66
  ```bash
48
67
  utterplan --version
49
68
  utterplan validate chapter.utterplan.toml
50
69
  utterplan inspect chapter.utterplan.toml --segment 0
51
- utterplan inspect chapter.utterplan.toml --semantic-boundaries
52
- utterplan explain chapter.utterplan.toml
70
+ utterplan inspect chapter.utterplan.toml --boundaries --tokens
71
+ utterplan explain chapter.utterplan.toml --trace chapter.trace.toml
72
+ utterplan inspect-trace chapter.trace.toml --preparation --boundaries
53
73
  utterplan inspect-attempt chapter.attempt.toml --issues
54
74
  ```
55
75
 
56
- `explain` presents the compiled plan as a human-readable speech plan, while `inspect` exposes lower-level diagnostic fields.
76
+ `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.
57
77
 
58
78
  `inspect-attempt` reads the separate `utterplan.planning-attempt.v1` TOML artifact,
59
79
  not a canonical plan. Use it to review renderability issues and safe repair
@@ -75,11 +95,11 @@ ssmd migrate old.ssmd --to 0.9
75
95
  ```
76
96
 
77
97
  `utterplan migrate` explicitly imports supported historical `.utterplan.json` plans and writes current TOML. It does not migrate SSMD source.
78
- Normal plan loading is TOML-only: `UtterancePlan.load()` and plan-inspection commands reject JSON rather than auto-detecting it.
98
+ Normal plan loading is TOML-only: `FlowPlan.load()` and plan-inspection commands reject JSON rather than auto-detecting it.
79
99
 
80
100
  ## Planning defaults
81
101
 
82
- The minimal CLI defaults are explicit: `spokenform` is the default text-preparation backend, `tts` is the default pause 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.
102
+ 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.
83
103
 
84
104
  Python `PlannerConfig` defaults to `document_format="plain"`; set it to `"ssmd"` when a Python string contains SSMD source.
85
105
 
@@ -90,7 +110,7 @@ Python `PlannerConfig.renderability_mode` also defaults to safe punctuation-only
90
110
  ## Python API
91
111
 
92
112
  ```python
93
- from utterplan import PlannerConfig, UtterancePlan, compile_document
113
+ from utterplan import PlannerConfig, FlowPlan, compile_document
94
114
 
95
115
  ssmd_source = """---
96
116
  ssmd_version: "0.9"
@@ -107,7 +127,7 @@ result = compile_document(
107
127
  plan = result.plan
108
128
  assert result.trace is not None
109
129
  plan.save("example.utterplan.toml")
110
- assert UtterancePlan.load("example.utterplan.toml") == plan
130
+ assert FlowPlan.load("example.utterplan.toml") == plan
111
131
  ```
112
132
 
113
133
  `compile_document` is the stable public one-document API shared by consumers. The
@@ -135,21 +155,9 @@ Callbacks run synchronously and exceptions propagate. See the [Python API guide]
135
155
 
136
156
  ## Renderer-consumer boundary
137
157
 
138
- Renderers consume `PlanSegment.text`, which is prepared/spoken text, and use
139
- `spoken_start`/`spoken_end` for spoken-text coordinates. Resolved segment
140
- pauses, language, directives, annotations, boundaries, semantic boundaries,
141
- markers, units, and
142
- document metadata are public plan fields. Semantic boundaries are stable
143
- engine-neutral opportunities for spoken-text subdivision; they are not pause
144
- events and carry no duration or renderer policy. Plans contain no phonemes, model
145
- tokens, model sessions, renderer configuration, provider documents, or audio.
146
- For SSMD input, `plan.annotations` preserve declared source semantics and source
147
- provenance, `document_metadata` preserves portable header data, and
148
- `segment.directives` carries effective typed semantics after scope and voice-default
149
- resolution. Typed directives include voice, pronunciation, prosody, emphasis, say-as,
150
- substitution, audio references, and extension references. Audio and extensions are
151
- data only. UtterPlan does not fetch media or execute extension handlers.
158
+ 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.
152
159
 
160
+ `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.
153
161
  The intended dependency direction is:
154
162
 
155
163
  ```text
@@ -164,6 +172,7 @@ renderer repository rather than UtterPlan's test suite.
164
172
 
165
173
  - [Getting started](docs/getting-started.md)
166
174
  - [CLI](docs/cli.md)
175
+ - [SSMDBook workflows](docs/ssmdbook.md)
167
176
  - [Format and schema](docs/format.md)
168
177
  - [Consumer guide](docs/consumer-guide.md)
169
178
  - [Architecture](docs/architecture.md)
@@ -175,10 +184,9 @@ renderer repository rather than UtterPlan's test suite.
175
184
 
176
185
  ## Versions
177
186
 
178
- 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 v4; released schema v1, v2, and v3 remain immutable and supported through sequential migrations.
187
+ 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.
179
188
 
180
- Schema v4 adds stable `SemanticBoundary` records in spoken-text coordinates. Migration converts serialized plan data only: the registered v3-to-v4 step preserves existing evidence and derives topology where possible, but does not rerun parsing, NLP, planning, G2P, rendering, or audio processing. Unit hashes use `utterplan-unit-v3` and include relative semantic-boundary positions; older hash algorithms remain available for their historical migration paths.
181
- Schema v4 retains typed renderer-neutral SSMD semantics, final pass-B token facts, and per-language-run provider provenance. Plans never serialize provider documents, models, sessions, phonemes, token IDs, or audio.
189
+ 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.
182
190
 
183
191
  ## Development
184
192
 
@@ -0,0 +1,63 @@
1
+ # Architecture
2
+
3
+ UtterPlan is an engine-independent compiler from one SSMD document (or explicitly selected plain-text document) to an executable speech plan. Consumers compile documents independently; UtterPlan does not load books or manage workspaces.
4
+
5
+ ```text
6
+ one SSMD document / explicit plain text
7
+ |
8
+ v
9
+ parse -> language semantics -> spokenform preparation
10
+ -> segmentation -> directive resolution
11
+ -> semantic pause intent -> internal compiler plan
12
+ | |
13
+ | +--> optional trace sidecar
14
+ v
15
+ FlowPlan (ordered units, local segments)
16
+ / \
17
+ consumer A consumer B
18
+ |
19
+ v
20
+ G2P / renderer / audio
21
+ ```
22
+
23
+ The dependency direction is from SSMD, spokenform, and phrasplit into UtterPlan, then from UtterPlan to consumer packages. UtterPlan must not depend on ttsready, Readio, engine registries, G2P packages, model runtimes, or audio packages. Book iteration belongs to consumers and conversion tools.
24
+
25
+ ## Compiler and public plan boundary
26
+
27
+ `compile_document` returns a `CompileResult` containing the current immutable `FlowPlan`, renderer-independent diagnostics, and an optional `PreparationTrace`. `UtterancePlanner.plan` also returns `FlowPlan`. Compiler-only normalized graph state remains private. When requested, the trace retains source text/hash, coordinate maps, preparation provenance, diagnostics, and renderability evidence in a separate versioned TOML sidecar. Trace state is not renderer input and does not affect plan identity or TOML.
28
+
29
+ `FlowPlan` is the current v5 executable contract: ordered `FlowUnit` objects each own ordered `FlowSegment` records. Segments include prepared text, effective language, local tokens, semantic pause intents, directives, markers, and optional heading metadata. `DocumentInfo` retains compact portable document information; `LinguisticProvenance` identifies providers without retaining their documents. UtterPlan ends before G2P. Engine/model selection, synthesis, and audio composition happen downstream.
30
+
31
+ ## SSMD and preparation
32
+
33
+ The document parser calls SSMD with `dialect="0.9"` for every SSMD source path, including unversioned fragments selected with `document_format="ssmd"`. UtterPlan does not parse SSMD 0.8 or migrate source. Older documents must first be converted with `ssmd migrate FILE --to 0.9`. The `utterplan migrate` command imports serialized legacy plans and applies schema migrations only.
34
+
35
+ SSMD header language is authoritative over a fallback. The CLI can omit `--language` when the header declares a language; plain input always needs a fallback. A fallback never forces or rewrites document semantics.
36
+
37
+ Preparation creates structural and spoken representations internally. The executable FlowPlan retains only prepared segment text; it does not retain the exact source string, structural text, dense source-to-spoken maps, parser annotations, or global compiler token tables. These diagnostics/provenance survive only when an optional trace is requested. See the [coordinate-space contract](coordinate-spaces).
38
+
39
+ ## Pause and directive semantics
40
+
41
+ Authored SSMD breaks and semantic pause strengths project to local `PauseIntent` values on segment edges. The plan does not invent numeric durations or serialize an activation policy. Application pause mode controls which intents the compiler activates; consumer-specific timing policy remains downstream. Exact authored timed breaks remain exact. Ambiguous historical pause evidence fails migration rather than being guessed.
42
+
43
+ Typed directives are renderer-neutral values resolved from SSMD scopes and voice defaults. Logical voice bindings remain references, not concrete engine voices. Audio references and extension names are data only; UtterPlan does not fetch media or execute handlers.
44
+
45
+ ## Identity and determinism
46
+
47
+ Plan identity is deterministic and renderer-independent. The v5 `plan_id` hashes executable flow and compact portable metadata rather than source text or TOML formatting. Flow-unit hashes use `utterplan-flow-v1` over local ordered segment semantics. Trace data, provider documents, model sessions, diagnostics, producer/package version, G2P output, and audio do not define executable identity. Package version is independent of explicit plan `schema_version`.
48
+
49
+ ## Persistence compatibility boundary
50
+
51
+ Current plans persist as deterministic `.utterplan.toml` files with schema v5; `FlowPlan.load()` accepts TOML only. The v5 TOML codec validates and constructs `FlowPlan`. Schema v5 deliberately has no JSON Schema resource or current JSON plan format. Frozen JSON Schema definitions for historical schemas v1–v4 remain under versioned resources.
52
+
53
+ ```text
54
+ current plan:
55
+ .utterplan.toml -- TOML decode / schema-v5 validation --> FlowPlan --> consumer
56
+
57
+ legacy saved plan:
58
+ .utterplan.json -- explicit `utterplan migrate` --> current .utterplan.toml
59
+ ```
60
+
61
+ Migration is not planning. Supported historical plans migrate through the registered sequential chain v1 -> v2 -> v3 -> v4 -> v5. Every step operates on serialized plain data and does not rerun source parsing, preparation, NLP, planning, G2P, rendering, or audio processing. The v4-to-v5 projection verifies token spans and pause evidence and fails rather than guessing. Downgrades are not supported.
62
+
63
+ `compile-many` orchestrates independent source documents in order. Each successful FlowPlan is validated and atomically saved before the next source is processed; ordinary failures are reported and later inputs continue unless fail-fast is requested. Its TOML report is operational data, not a FlowPlan.
@@ -4,6 +4,18 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.5.0] - 2026-10-09
8
+
9
+ ### Added
10
+
11
+ - Added compile-book for selecting and compiling SSMDBook chapters into independent v5 plans with operational reports
12
+
13
+ ### Changed
14
+
15
+ - **BREAKING:** Changed plan persistence to schema v5 with deterministic TOML, sequential legacy migration, and optional trace sidecars
16
+
17
+ <!-- generated by releaseledger -->
18
+
7
19
  ## [0.4.1] - 2026-10-07
8
20
 
9
21
  ### Added
@@ -9,7 +9,8 @@ usage: utterplan compile [-h] [--file FILE] [--language LANGUAGE]
9
9
  [--text-preparation {spokenform,identity}]
10
10
  [--pause-mode {tts,manual,auto}]
11
11
  [--spacy {auto,off,sm,md,lg,trf}] [-o OUTPUT]
12
- [--force] [--stdout] [--renderability {strict,repair}]
12
+ [--trace TRACE] [--force] [--stdout]
13
+ [--renderability {strict,repair}]
13
14
  [text ...]
14
15
  ```
15
16
 
@@ -65,6 +66,7 @@ Without `--output`, compile writes the pretty TOML plan to stdout. With
65
66
  `--force` is supplied. Add `--stdout` with an output path to write the file and
66
67
  also emit the same TOML plan to stdout.
67
68
 
69
+ `--trace PATH` writes optional compiler provenance to a separate TOML sidecar. The trace is not embedded in, or hashed as part of, the executable plan. Keep and distribute the sidecar only when source text, preparation maps, diagnostics, or renderability evidence must be retained.
68
70
  Human status messages are written to stderr, never mixed into TOML stdout:
69
71
 
70
72
  ```bash
@@ -85,10 +87,35 @@ utterplan compile-many chapters/*.ssmd --output-dir build/plans \
85
87
  --language en-us --report build/compile-report.toml
86
88
  ```
87
89
 
88
- Source names determine output names: `chapter.ssmd`, `chapter.ssmd.md`, and `chapter.md` each map to `chapter.utterplan.toml`. Duplicate output names and a report path that collides with a plan output are rejected before any writes. Existing plans are protected unless `--force` is supplied. By default the command writes an atomically refreshed `compile-report.toml` in the output directory; the report is operational TOML, not a plan accepted by `UtterancePlan.load()`.
90
+ Source names determine output names: `chapter.ssmd`, `chapter.ssmd.md`, and `chapter.md` each map to `chapter.utterplan.toml`. Duplicate output names and a report path that collides with a plan output are rejected before any writes. Existing plans are protected unless `--force` is supplied. By default the command writes an atomically refreshed `compile-report.toml` in the output directory; the report is operational TOML, not a plan accepted by `FlowPlan.load()`.
89
91
 
90
92
  Shared planning options include `--language`, `--input-format auto|plain|ssmd`, `--unit`, `--text-preparation`, `--pause-mode`, `--spacy`, and `--renderability`. Progress, repair notices, actionable errors, and the 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.
91
93
 
94
+ ## Compile chapters from an SSMDBook workspace
95
+
96
+ `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:
97
+
98
+ ```bash
99
+ utterplan compile-book novel.ssmdbook --chapters 5-17
100
+ utterplan compile-book novel.ssmdbook/chapters --chapters 1,3-5
101
+ ```
102
+
103
+ The workflow used from inside the workspace is:
104
+
105
+ ```bash
106
+ cd "Platform Decay - Martha Wells.ssmdbook"
107
+
108
+ utterplan compile-book chapters --chapters 5-17
109
+ ```
110
+
111
+ `--chapters` selects manifest `source_number` values, not filenames or manifest indexes. It accepts `all` (the default), one number, inclusive ranges, or comma-separated combinations such as `1,3-5,9`. Duplicate selections do not duplicate work, and selected chapters always follow manifest array order. A selected missing source number or malformed selector is rejected before compilation.
112
+
113
+ By default, plans and the operational report are written to `<book-root>/utterplan/`. Use `--output-dir PATH` to override the destination. One canonical v5 `.utterplan.toml` plan is written per selected chapter, plus `compile-report.toml`. Existing plans are protected unless `--force` is given; `--fail-fast` skips later chapters after the first failure. `--report PATH` overrides the report location. Duplicate output names, report/plan collisions, and writes into the source `chapters/` directory or over `manifest.json` are rejected before writing.
114
+
115
+ Shared planning options are `--language`/`--lang`, `--unit`, `--text-preparation`, `--pause-mode`, `--renderability`, and `--spacy`. Chapter documents are SSMD 0.9 by contract, so `compile-book` does not accept `--input-format`. The manifest is read-only: edited chapter content is compiled as it currently exists even if its recorded digest is stale, and UtterPlan never refreshes the manifest or chapter hashes. Only selected chapter files are opened, so an unrelated broken chapter outside the selection does not block the request.
116
+
117
+ For the full editable-workspace behavior and examples, see the [SSMDBook guide](ssmdbook.md).
118
+
92
119
  ## Explain a plan
93
120
 
94
121
  Explain an existing compiled plan as a human-readable speech narrative:
@@ -98,7 +125,7 @@ utterplan explain chapter.utterplan.toml
98
125
  utterplan explain chapter.utterplan.toml --details
99
126
  ```
100
127
 
101
- The default output shows prepared wording, render units, ordered segments, languages, resolved pauses, headings, SSMD version/title/document language, effective typed directives, metadata, and warning/error codes with source locations. Add `--details` for IDs, offsets, provenance, hashes, plan identity, and token analysis beneath each segment. Use `inspect --tokens` for a compact token/provenance view.
128
+ The default output explains executable flow: prepared segment text, unit order, effective languages, semantic pause intents, headings, markers, and typed directives. Compiler source diagnostics and preparation provenance are intentionally absent from the plan unless a trace sidecar was saved. Add `--details` for local token offsets, flow hashes, plan identity, and trace preparation mappings. Pass `--trace PATH` to attach a matching sidecar; the TOML trace can also be read independently with `inspect-trace`.
102
129
 
103
130
  ## Inspect a persisted planning attempt
104
131
 
@@ -116,7 +143,7 @@ The default view summarizes status, renderability, and candidate size. `--issues
116
143
  shows source context and conservative repair assessments; segment and unit selectors
117
144
  accept an ID or zero-based index. `--json` emits the complete artifact as JSON for
118
145
  inspection, but the persisted attempt itself remains TOML. A blocked candidate is an
119
- inspect-only draft, not a canonical plan, and is rejected by `UtterancePlan.load()`.
146
+ inspect-only draft, not a canonical plan, and is rejected by `FlowPlan.load()`.
120
147
 
121
148
  ## Planning controls
122
149
 
@@ -142,12 +169,13 @@ utterplan validate chapter.ssmd.md
142
169
  utterplan validate plain.txt --input-format plain --language en-us
143
170
  utterplan inspect chapter.utterplan.toml --segment 0
144
171
  utterplan inspect chapter.utterplan.toml --unit 0 --boundaries --tokens
145
- utterplan inspect chapter.utterplan.toml --preparation
146
- utterplan inspect chapter.utterplan.toml --semantic-boundaries
172
+ utterplan compile chapter.ssmd.md -o chapter.utterplan.toml --trace chapter.trace.toml
173
+ utterplan explain chapter.utterplan.toml --trace chapter.trace.toml
174
+ utterplan inspect-trace chapter.trace.toml --preparation --boundaries
147
175
  utterplan inspect-attempt chapter.attempt.toml --issues
148
176
  ```
149
177
 
150
- `inspect --preparation` reports the preparation backend and version, structural and spoken text lengths, replacement count, and each replacement's structural and spoken ranges and text. This is the supported human-facing preparation diagnostic; raw coordinate lookup tables are intentionally absent from the persisted TOML plan.
178
+ `inspect-trace --preparation` reports source/prepared text lengths, maps, preparation changes, and repair/diagnostic evidence from the optional trace. `inspect-trace --boundaries` shows compiler-only boundary events and semantic candidates. These fields are intentionally absent from the executable plan TOML.
151
179
 
152
180
  ## Migrate a saved plan
153
181
 
@@ -167,11 +195,7 @@ route and reports source schema, target schema, and whether migration is require
167
195
  without writing a file. A future schema version is rejected rather than guessed
168
196
  or downgraded.
169
197
 
170
- Schema migration is a separate operation from SSMD source migration. UtterPlan
171
- preserves released schemas v1, v2, and v3 and migrates supported plans through the
172
- registered chain to current schema v4. The v3-to-v4 step does not rerun parsing,
173
- NLP, or planning. Use `ssmd migrate FILE --to 0.9` for older SSMD source
174
- documents.
198
+ Schema migration is separate from SSMD source migration. Frozen JSON schemas v1–v4 migrate through the registered sequential chain to current schema v5. The v4-to-v5 projection does not rerun parsing, text preparation, NLP, or planning, and refuses ambiguous token coordinates or pause meanings rather than guessing. Use `ssmd migrate FILE --to 0.9` for older SSMD source documents.
175
199
 
176
200
  For a saved TOML plan, `validate` verifies the current semantic schema and plan
177
201
  invariants; JSON plan paths are rejected outside `migrate`. For an SSMD or
@@ -0,0 +1,92 @@
1
+ # Renderer consumer guide
2
+
3
+ UtterPlan ends at a semantic planning boundary. A renderer consumes the public `FlowPlan` and begins G2P after planning. It does not need a TOML round trip when planner and renderer run in the same process.
4
+
5
+ For persistence across processes, save a current plan as `.utterplan.toml` and load it with `FlowPlan.load()`. `to_toml()` / `from_toml()` provide text round-tripping, and `plan_id` identifies executable semantics rather than TOML formatting. Batch reports and optional compiler traces are operational/provenance artifacts, not plans.
6
+
7
+ UtterPlan accepts SSMD source syntax at version 0.9 only. Convert older source with `ssmd migrate FILE --to 0.9`; `utterplan migrate` is for importing serialized legacy plans.
8
+
9
+ ## Importing legacy plans
10
+
11
+ Historical JSON schemas v1–v4 remain immutable and supported through sequential migrations to schema v5. Import explicitly:
12
+
13
+ ```bash
14
+ utterplan migrate old.utterplan.json -o current.utterplan.toml
15
+ ```
16
+
17
+ Migration operates on serialized plain data and does not reparse, reprepare, rerun NLP, or replan. The v4-to-v5 projection fails safely if token ownership/spans or authored pause semantics cannot be verified without guessing. Recompiling source is a separate operation. Normal `FlowPlan.load()` and plan-inspection commands reject JSON.
18
+
19
+ ## Planning defaults
20
+
21
+ The default text-preparation backend is `spokenform`, pause activation mode is `tts`, and the default CLI linguistic-resource policy is `spacy off`. Deterministic fallback tokenization and analysis do not require an installed spaCy model. `spacy auto` is opt-in; it may expose richer tokenization, POS, lemmas, and tags, but provider documents remain internal.
22
+
23
+ In Python, `PlannerConfig.document_format` defaults to `"plain"`; select `"ssmd"` for SSMD source. `PauseConfig.mode` controls whether eligible semantic pause intents are activated by the compiler. The executable plan carries semantic intent (or an exact authored timed pause), not numeric durations invented from an activation policy. A renderer may interpret supported intents according to its own capabilities.
24
+
25
+ ## Consumer contract
26
+
27
+ `FlowPlan.flow` is the render order. Each `FlowUnit` owns its ordered `FlowSegment` records; no ID join is required. A segment provides:
28
+
29
+ - `text`: prepared speech text for this segment.
30
+ - `language`: effective language, defaulting from `FlowPlan.language` when omitted on the wire.
31
+ - `tokens`: local token views with optional lemma, POS, tag, and morphology.
32
+ - `pause_before` and `pause_after`: semantic pause intents such as `none`, `sentence`, `parenthetical`, or an exact authored time.
33
+ - `directives`: typed voice, pronunciation, prosody, emphasis, say-as, substitution, audio, and extension data.
34
+ - `markers` and optional `heading` metadata already localized to the owning segment.
35
+
36
+ Token offsets are half-open Python-character ranges into the owning `segment.text`. Do not use them to slice document text or add offsets from another segment. Consumers render flow units and segments in their stored order.
37
+
38
+ ```python
39
+ from utterplan import FlowPlan
40
+
41
+ plan = FlowPlan.load("chapter.utterplan.toml")
42
+ plan.validate()
43
+
44
+ for unit in plan.flow:
45
+ for segment in unit.segments:
46
+ token_views = [
47
+ (segment.text[token.start : token.end], token.lemma, token.pos, token.tag, token.morph)
48
+ for token in segment.tokens
49
+ ]
50
+ render_speech(
51
+ text=segment.text,
52
+ language=segment.language,
53
+ tokens=token_views,
54
+ pause_before=segment.pause_before,
55
+ pause_after=segment.pause_after,
56
+ directives=segment.directives,
57
+ )
58
+ ```
59
+
60
+ `FlowPlan.document` retains compact document information such as format, title, SSMD version, and portable semantics. `FlowPlan.linguistics` identifies analysis provider/model provenance without retaining provider state. Source text, source locations, compiler diagnostics, preparation mappings, and renderability details are intentionally not executable-plan fields.
61
+
62
+ ## Optional compiler trace
63
+
64
+ When source-level evidence must survive a process boundary, request a separate trace sidecar:
65
+
66
+ ```bash
67
+ utterplan compile chapter.ssmd.md -o chapter.utterplan.toml --trace chapter.trace.toml
68
+ utterplan explain chapter.utterplan.toml --trace chapter.trace.toml
69
+ utterplan inspect-trace chapter.trace.toml --preparation --boundaries
70
+ ```
71
+
72
+ The trace contains source text/hash, structural/prepared text, coordinate maps, preparation changes, diagnostics, and renderability evidence. It is not renderer input, does not affect `FlowPlan.plan_id`, and does not change the resulting plan TOML. See the [coordinate-space contract](coordinate-spaces) for every trace offset's coordinate space.
73
+
74
+ ## Directives and media
75
+
76
+ Voice bindings and directive voice references are logical names, not backend voice IDs; consumers translate them to engine-specific resources. UtterPlan resolves SSMD scopes and defaults but does not choose engine settings or recompute pause policy.
77
+
78
+ An audio directive is already attached to its owning segment. Its `src` is opaque data for an external resolver; UtterPlan does not select or invoke one. For an audio-bearing segment, `segment.text` is an optional spoken fallback. Identical source URIs on distinct segments are separate timeline occurrences and must not be deduplicated as playback events. Extension references are also data only; UtterPlan does not execute handlers.
79
+
80
+ ## Stable renderer input
81
+
82
+ A completed plan is immutable consumer input. Consumers may derive data for G2P/rendering, but must not rewrite planning decisions or mutate the plan:
83
+
84
+ ```python
85
+ before = plan.to_toml()
86
+ plan_id = plan.plan_id
87
+ consume_plan(plan)
88
+ assert plan.to_toml() == before
89
+ assert plan.plan_id == plan_id
90
+ ```
91
+
92
+ Plans contain no phonemes, model token IDs, model sessions, audio, renderer configuration, or model-derived timings. Acoustic retries and renderer-level randomness remain outside UtterPlan.
@@ -0,0 +1,22 @@
1
+ # Coordinate spaces
2
+
3
+ Schema v5 keeps the executable plan compact: token coordinates are local to each `FlowSegment.text`; document-global source and preparation coordinates live only in an optional `PreparationTrace` sidecar.
4
+
5
+ ## Executable plan coordinates
6
+
7
+ `FlowSegment.text` is the prepared speech text for that segment. Each `TokenView.start` and `TokenView.end` is a half-open Python-character offset into that segment's text. Slice a token with `segment.text[token.start:token.end]`. Do not add a unit, segment, document, or compiler offset to these values. Token membership is stored locally in `segment.tokens`; there are no plan-global token indices or lookup joins.
8
+
9
+ Pauses, directives, markers, and optional heading levels are attached directly to their owning flow-segment edge or segment. They have no independent text coordinate. Flow-unit and segment order is the render order.
10
+
11
+ ## Optional trace coordinates
12
+
13
+ Trace coordinates use Python string character boundaries (Unicode code points), not UTF-8 bytes or grapheme clusters:
14
+
15
+ - `source_text` is the exact caller input, including SSMD front matter and markup.
16
+ - `source_spans` maps original-source `[source_start, source_end)` ranges to parsed structural `[structural_start, structural_end)` ranges.
17
+ - `structural_text` is SSMD-clean structural text before written-to-spoken preparation.
18
+ - `spoken_text` is the prepared text used to construct executable segments.
19
+ - `structural_to_spoken` maps structural character boundaries to spoken boundaries; `spoken_to_structural` maps spoken boundaries back to structural boundaries.
20
+ - `PreparationTraceUnit.source_start` / `source_end` address structural text. `PreparationChange.source_start` / `source_end` use structural coordinates; `output_start` / `output_end` use prepared spoken coordinates.
21
+
22
+ Diagnostic source offsets use the exact original-source coordinate space. Diagnostic `line` and `column` values are 1-based; columns count Python characters from the start of a line. The trace retains all these maps and source evidence. The executable FlowPlan intentionally does not.