utterplan 0.4.0__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 (213) hide show
  1. {utterplan-0.4.0 → utterplan-0.5.0}/.github/workflows/tests.yml +2 -0
  2. {utterplan-0.4.0 → utterplan-0.5.0}/AGENTS.md +4 -3
  3. {utterplan-0.4.0 → utterplan-0.5.0}/PKG-INFO +42 -29
  4. {utterplan-0.4.0 → utterplan-0.5.0}/README.md +41 -28
  5. utterplan-0.5.0/docs/architecture.md +63 -0
  6. {utterplan-0.4.0 → utterplan-0.5.0}/docs/changelog.md +32 -0
  7. {utterplan-0.4.0 → utterplan-0.5.0}/docs/cli.md +54 -11
  8. utterplan-0.5.0/docs/consumer-guide.md +92 -0
  9. utterplan-0.5.0/docs/coordinate-spaces.md +22 -0
  10. utterplan-0.5.0/docs/debugging.md +28 -0
  11. utterplan-0.5.0/docs/format.md +62 -0
  12. {utterplan-0.4.0 → utterplan-0.5.0}/docs/getting-started.md +33 -15
  13. {utterplan-0.4.0 → utterplan-0.5.0}/docs/index.md +1 -0
  14. utterplan-0.5.0/docs/pykokoro-integration.md +46 -0
  15. {utterplan-0.4.0 → utterplan-0.5.0}/docs/python-api.md +105 -53
  16. utterplan-0.5.0/docs/ssmdbook.md +72 -0
  17. {utterplan-0.4.0 → utterplan-0.5.0}/examples/compile_file.py +1 -1
  18. {utterplan-0.4.0 → utterplan-0.5.0}/examples/inspect_plan.py +6 -5
  19. {utterplan-0.4.0 → utterplan-0.5.0}/examples/multilingual.py +1 -1
  20. utterplan-0.5.0/tests/compiler_helpers.py +36 -0
  21. utterplan-0.5.0/tests/fixtures/canonical_consumer_contract.expected.toml +35 -0
  22. utterplan-0.5.0/tests/migration/test_legacy_json_import.py +38 -0
  23. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/test_semantic_migration_regressions.py +35 -8
  24. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_batch.py +10 -6
  25. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_boundaries.py +2 -1
  26. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_cli.py +124 -42
  27. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_cli_batch.py +9 -4
  28. utterplan-0.5.0/tests/test_cli_ssmdbook.py +431 -0
  29. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_compiler.py +39 -17
  30. utterplan-0.5.0/tests/test_consumer_contract.py +182 -0
  31. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_consumer_readiness.py +19 -38
  32. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_coordinates.py +2 -1
  33. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_directives.py +3 -6
  34. utterplan-0.5.0/tests/test_explain.py +121 -0
  35. utterplan-0.5.0/tests/test_fake_renderer.py +133 -0
  36. utterplan-0.5.0/tests/test_flow_compilation.py +97 -0
  37. utterplan-0.5.0/tests/test_format.py +110 -0
  38. utterplan-0.5.0/tests/test_golden.py +65 -0
  39. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_identity_units.py +2 -1
  40. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_linguistics.py +59 -11
  41. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_migration_framework.py +3 -3
  42. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_migration_v3_to_v4.py +6 -6
  43. utterplan-0.5.0/tests/test_migration_v4_to_v5.py +179 -0
  44. utterplan-0.5.0/tests/test_pauses.py +213 -0
  45. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_planner.py +7 -5
  46. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_preparation.py +10 -5
  47. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_progress.py +3 -3
  48. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_public_identity.py +3 -3
  49. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_renderability.py +1 -1
  50. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_renderability_repair.py +110 -5
  51. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_schema_history.py +10 -7
  52. utterplan-0.5.0/tests/test_schema_registry.py +54 -0
  53. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_schema_strict.py +4 -2
  54. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_segment_topology.py +4 -3
  55. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_semantic_boundaries.py +2 -2
  56. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_ssmd_09_parser.py +96 -20
  57. utterplan-0.5.0/tests/test_ssmdbook.py +279 -0
  58. utterplan-0.5.0/tests/test_toml_format.py +226 -0
  59. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/__init__.py +24 -4
  60. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/_version.py +3 -3
  61. utterplan-0.5.0/utterplan/attempt_serialization.py +250 -0
  62. utterplan-0.5.0/utterplan/attempts.py +103 -0
  63. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/batch.py +4 -7
  64. utterplan-0.5.0/utterplan/cli.py +1048 -0
  65. utterplan-0.5.0/utterplan/codecs/__init__.py +1 -0
  66. utterplan-0.4.0/utterplan/toml_codec.py → utterplan-0.5.0/utterplan/codecs/v4_toml.py +71 -33
  67. utterplan-0.5.0/utterplan/codecs/v5_toml.py +504 -0
  68. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/compiler.py +73 -5
  69. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/config.py +0 -54
  70. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/explain.py +156 -54
  71. utterplan-0.5.0/utterplan/flow_projection.py +276 -0
  72. utterplan-0.5.0/utterplan/format.py +48 -0
  73. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/hashing.py +92 -2
  74. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/migration.py +1 -1
  75. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/migrations/__init__.py +2 -0
  76. utterplan-0.5.0/utterplan/migrations/v4_to_v5.py +580 -0
  77. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/model.py +748 -64
  78. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/parsers.py +194 -177
  79. utterplan-0.5.0/utterplan/pauses.py +108 -0
  80. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/planner.py +149 -89
  81. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/preparation.py +7 -7
  82. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/renderability.py +8 -1
  83. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/schema_registry.py +7 -5
  84. utterplan-0.5.0/utterplan/serialization.py +40 -0
  85. utterplan-0.5.0/utterplan/ssmdbook.py +259 -0
  86. utterplan-0.5.0/utterplan/toml_codec.py +100 -0
  87. utterplan-0.5.0/utterplan/trace_codec.py +137 -0
  88. utterplan-0.5.0/utterplan/versioning.py +11 -0
  89. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/PKG-INFO +42 -29
  90. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/SOURCES.txt +15 -0
  91. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/scm_file_list.json +38 -0
  92. utterplan-0.5.0/utterplan.egg-info/scm_version.json +8 -0
  93. utterplan-0.4.0/docs/architecture.md +0 -110
  94. utterplan-0.4.0/docs/consumer-guide.md +0 -149
  95. utterplan-0.4.0/docs/coordinate-spaces.md +0 -16
  96. utterplan-0.4.0/docs/debugging.md +0 -31
  97. utterplan-0.4.0/docs/format.md +0 -39
  98. utterplan-0.4.0/docs/pykokoro-integration.md +0 -63
  99. utterplan-0.4.0/tests/fixtures/canonical_consumer_contract.expected.toml +0 -6
  100. utterplan-0.4.0/tests/migration/test_legacy_json_import.py +0 -29
  101. utterplan-0.4.0/tests/test_consumer_contract.py +0 -313
  102. utterplan-0.4.0/tests/test_explain.py +0 -180
  103. utterplan-0.4.0/tests/test_fake_renderer.py +0 -72
  104. utterplan-0.4.0/tests/test_format.py +0 -114
  105. utterplan-0.4.0/tests/test_golden.py +0 -64
  106. utterplan-0.4.0/tests/test_pauses.py +0 -212
  107. utterplan-0.4.0/tests/test_schema_registry.py +0 -54
  108. utterplan-0.4.0/tests/test_toml_format.py +0 -179
  109. utterplan-0.4.0/utterplan/cli.py +0 -656
  110. utterplan-0.4.0/utterplan/format.py +0 -46
  111. utterplan-0.4.0/utterplan/pauses.py +0 -76
  112. utterplan-0.4.0/utterplan/serialization.py +0 -32
  113. utterplan-0.4.0/utterplan/versioning.py +0 -8
  114. utterplan-0.4.0/utterplan.egg-info/scm_version.json +0 -8
  115. {utterplan-0.4.0 → utterplan-0.5.0}/.codecrate.toml +0 -0
  116. {utterplan-0.4.0 → utterplan-0.5.0}/.github/workflows/codecov.yml +0 -0
  117. {utterplan-0.4.0 → utterplan-0.5.0}/.github/workflows/pre-commit.yml +0 -0
  118. {utterplan-0.4.0 → utterplan-0.5.0}/.github/workflows/python-publish.yml +0 -0
  119. {utterplan-0.4.0 → utterplan-0.5.0}/.gitignore +0 -0
  120. {utterplan-0.4.0 → utterplan-0.5.0}/.pre-commit-config.yaml +0 -0
  121. {utterplan-0.4.0 → utterplan-0.5.0}/LICENSE +0 -0
  122. {utterplan-0.4.0 → utterplan-0.5.0}/MANIFEST.in +0 -0
  123. {utterplan-0.4.0 → utterplan-0.5.0}/NOTICE +0 -0
  124. {utterplan-0.4.0 → utterplan-0.5.0}/docs/Makefile +0 -0
  125. {utterplan-0.4.0 → utterplan-0.5.0}/docs/conf.py +0 -0
  126. {utterplan-0.4.0 → utterplan-0.5.0}/docs/make.bat +0 -0
  127. {utterplan-0.4.0 → utterplan-0.5.0}/docs/phase-a-completion.md +0 -0
  128. {utterplan-0.4.0 → utterplan-0.5.0}/docs/requirements.txt +0 -0
  129. {utterplan-0.4.0 → utterplan-0.5.0}/examples/basic.py +0 -0
  130. {utterplan-0.4.0 → utterplan-0.5.0}/examples/chapter.ssmd +0 -0
  131. {utterplan-0.4.0 → utterplan-0.5.0}/examples/ssmd_example.py +0 -0
  132. {utterplan-0.4.0 → utterplan-0.5.0}/pyproject.toml +0 -0
  133. {utterplan-0.4.0 → utterplan-0.5.0}/setup.cfg +0 -0
  134. {utterplan-0.4.0 → utterplan-0.5.0}/spec/schemas/v1.schema.json +0 -0
  135. {utterplan-0.4.0 → utterplan-0.5.0}/spec/schemas/v2.schema.json +0 -0
  136. {utterplan-0.4.0 → utterplan-0.5.0}/spec/schemas/v3.schema.json +0 -0
  137. {utterplan-0.4.0 → utterplan-0.5.0}/spec/schemas/v4.schema.json +0 -0
  138. {utterplan-0.4.0 → utterplan-0.5.0}/spec/utterplan.schema.json +0 -0
  139. {utterplan-0.4.0 → utterplan-0.5.0}/tests/__init__.py +0 -0
  140. {utterplan-0.4.0 → utterplan-0.5.0}/tests/fixtures/canonical_consumer_contract.ssmd +0 -0
  141. {utterplan-0.4.0 → utterplan-0.5.0}/tests/fixtures/ssmd_09_comprehensive.ssmd +0 -0
  142. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/basic_en.utterplan.toml +0 -0
  143. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/directives.utterplan.toml +0 -0
  144. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/markers.utterplan.toml +0 -0
  145. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/multilingual.utterplan.toml +0 -0
  146. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/parenthetical.utterplan.toml +0 -0
  147. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/spokenform_offsets.utterplan.toml +0 -0
  148. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/ssmd_09_comprehensive.utterplan.toml +0 -0
  149. {utterplan-0.4.0 → utterplan-0.5.0}/tests/golden/ssmd_breaks.utterplan.toml +0 -0
  150. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/__init__.py +0 -0
  151. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/cases.py +0 -0
  152. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/basic_en.utterplan.json +0 -0
  153. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/directives.utterplan.json +0 -0
  154. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/markers.utterplan.json +0 -0
  155. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/multilingual.utterplan.json +0 -0
  156. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/parenthetical.utterplan.json +0 -0
  157. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/spokenform_offsets.utterplan.json +0 -0
  158. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/ssmd_09_comprehensive.utterplan.json +0 -0
  159. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/fixtures/v4/ssmd_breaks.utterplan.json +0 -0
  160. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/goldens/multilingual_preparation.json +0 -0
  161. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/goldens/spokenform_numbers.json +0 -0
  162. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/goldens/ssmd_break.json +0 -0
  163. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/goldens/ssmd_language_detection.json +0 -0
  164. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/goldens/ssmd_marker.json +0 -0
  165. {utterplan-0.4.0 → utterplan-0.5.0}/tests/migration/goldens/ssmd_pronunciation.json +0 -0
  166. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/README.md +0 -0
  167. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/basic.json +0 -0
  168. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/directives.json +0 -0
  169. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/markers.json +0 -0
  170. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/multilingual.json +0 -0
  171. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/parenthetical.json +0 -0
  172. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/spokenform_offsets.json +0 -0
  173. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v1/ssmd_breaks.json +0 -0
  174. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v2/directives.json +0 -0
  175. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v3/multilingual.json +0 -0
  176. {utterplan-0.4.0 → utterplan-0.5.0}/tests/schema_history/v3/ssmd_09_comprehensive.json +0 -0
  177. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_atomic_io.py +0 -0
  178. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_import_boundaries.py +0 -0
  179. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_language.py +0 -0
  180. {utterplan-0.4.0 → utterplan-0.5.0}/tests/test_version.py +0 -0
  181. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/__main__.py +0 -0
  182. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/atomic_io.py +0 -0
  183. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/diagnostics.py +0 -0
  184. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/directives.py +0 -0
  185. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/exceptions.py +0 -0
  186. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/language.py +0 -0
  187. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/linguistics.py +0 -0
  188. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/migrations/registry.py +0 -0
  189. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/migrations/v1_to_v2.py +0 -0
  190. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/migrations/v2_to_v3.py +0 -0
  191. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/migrations/v3_to_v4.py +0 -0
  192. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/progress.py +0 -0
  193. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/py.typed +0 -0
  194. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/schemas/v1.schema.json +0 -0
  195. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/schemas/v2.schema.json +0 -0
  196. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/schemas/v3.schema.json +0 -0
  197. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/schemas/v4.schema.json +0 -0
  198. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/spacy_models.py +0 -0
  199. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/spans.py +0 -0
  200. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/__init__.py +0 -0
  201. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/document/__init__.py +0 -0
  202. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/document/plain.py +0 -0
  203. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/document/ssmd.py +0 -0
  204. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/preparation/__init__.py +0 -0
  205. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/preparation/identity.py +0 -0
  206. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/preparation/spokenform.py +0 -0
  207. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/stages/protocols.py +0 -0
  208. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/units.py +0 -0
  209. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan/utterplan.schema.json +0 -0
  210. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/dependency_links.txt +0 -0
  211. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/entry_points.txt +0 -0
  212. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/requires.txt +0 -0
  213. {utterplan-0.4.0 → utterplan-0.5.0}/utterplan.egg-info/top_level.txt +0 -0
@@ -53,6 +53,8 @@ jobs:
53
53
  "typing_extensions==4.0.0" \
54
54
  "tomlkit==0.13.0"
55
55
  python -m pip install --no-deps -e .
56
+ - name: Verify SSMD 0.9.3 front-matter scene-break handling
57
+ run: python -m pytest -q tests/test_ssmd_09_parser.py -k front_matter_scene_break
56
58
  - name: Run lower-bound tests
57
59
  run: python -m pytest -q
58
60
 
@@ -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.0
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,17 +284,43 @@ 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
316
+ utterplan inspect-attempt chapter.attempt.toml --issues
296
317
  ```
297
318
 
298
- `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.
320
+
321
+ `inspect-attempt` reads the separate `utterplan.planning-attempt.v1` TOML artifact,
322
+ not a canonical plan. Use it to review renderability issues and safe repair
323
+ assessments on blocked planning outcomes; such candidates remain inspect-only drafts.
299
324
  Canonical plan output is TOML (`.utterplan.toml`) and is written to stdout when no output file is supplied. Status messages use stderr, and existing output files require `--force`. Safe punctuation repair is the default; use `--renderability strict` to reject every repair opportunity.
300
325
 
301
326
  ## SSMD source contract
@@ -313,11 +338,11 @@ ssmd migrate old.ssmd --to 0.9
313
338
  ```
314
339
 
315
340
  `utterplan migrate` explicitly imports supported historical `.utterplan.json` plans and writes current TOML. It does not migrate SSMD source.
316
- 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.
317
342
 
318
343
  ## Planning defaults
319
344
 
320
- 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.
321
346
 
322
347
  Python `PlannerConfig` defaults to `document_format="plain"`; set it to `"ssmd"` when a Python string contains SSMD source.
323
348
 
@@ -328,7 +353,7 @@ Python `PlannerConfig.renderability_mode` also defaults to safe punctuation-only
328
353
  ## Python API
329
354
 
330
355
  ```python
331
- from utterplan import PlannerConfig, UtterancePlan, compile_document
356
+ from utterplan import PlannerConfig, FlowPlan, compile_document
332
357
 
333
358
  ssmd_source = """---
334
359
  ssmd_version: "0.9"
@@ -345,7 +370,7 @@ result = compile_document(
345
370
  plan = result.plan
346
371
  assert result.trace is not None
347
372
  plan.save("example.utterplan.toml")
348
- assert UtterancePlan.load("example.utterplan.toml") == plan
373
+ assert FlowPlan.load("example.utterplan.toml") == plan
349
374
  ```
350
375
 
351
376
  `compile_document` is the stable public one-document API shared by consumers. The
@@ -373,21 +398,9 @@ Callbacks run synchronously and exceptions propagate. See the [Python API guide]
373
398
 
374
399
  ## Renderer-consumer boundary
375
400
 
376
- Renderers consume `PlanSegment.text`, which is prepared/spoken text, and use
377
- `spoken_start`/`spoken_end` for spoken-text coordinates. Resolved segment
378
- pauses, language, directives, annotations, boundaries, semantic boundaries,
379
- markers, units, and
380
- document metadata are public plan fields. Semantic boundaries are stable
381
- engine-neutral opportunities for spoken-text subdivision; they are not pause
382
- events and carry no duration or renderer policy. Plans contain no phonemes, model
383
- tokens, model sessions, renderer configuration, provider documents, or audio.
384
- For SSMD input, `plan.annotations` preserve declared source semantics and source
385
- provenance, `document_metadata` preserves portable header data, and
386
- `segment.directives` carries effective typed semantics after scope and voice-default
387
- resolution. Typed directives include voice, pronunciation, prosody, emphasis, say-as,
388
- substitution, audio references, and extension references. Audio and extensions are
389
- 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.
390
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.
391
404
  The intended dependency direction is:
392
405
 
393
406
  ```text
@@ -402,6 +415,7 @@ renderer repository rather than UtterPlan's test suite.
402
415
 
403
416
  - [Getting started](docs/getting-started.md)
404
417
  - [CLI](docs/cli.md)
418
+ - [SSMDBook workflows](docs/ssmdbook.md)
405
419
  - [Format and schema](docs/format.md)
406
420
  - [Consumer guide](docs/consumer-guide.md)
407
421
  - [Architecture](docs/architecture.md)
@@ -413,10 +427,9 @@ renderer repository rather than UtterPlan's test suite.
413
427
 
414
428
  ## Versions
415
429
 
416
- 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.
417
431
 
418
- 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.
419
- 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.
420
433
 
421
434
  ## Development
422
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,17 +41,43 @@ 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
73
+ utterplan inspect-attempt chapter.attempt.toml --issues
53
74
  ```
54
75
 
55
- `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.
77
+
78
+ `inspect-attempt` reads the separate `utterplan.planning-attempt.v1` TOML artifact,
79
+ not a canonical plan. Use it to review renderability issues and safe repair
80
+ assessments on blocked planning outcomes; such candidates remain inspect-only drafts.
56
81
  Canonical plan output is TOML (`.utterplan.toml`) and is written to stdout when no output file is supplied. Status messages use stderr, and existing output files require `--force`. Safe punctuation repair is the default; use `--renderability strict` to reject every repair opportunity.
57
82
 
58
83
  ## SSMD source contract
@@ -70,11 +95,11 @@ ssmd migrate old.ssmd --to 0.9
70
95
  ```
71
96
 
72
97
  `utterplan migrate` explicitly imports supported historical `.utterplan.json` plans and writes current TOML. It does not migrate SSMD source.
73
- 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.
74
99
 
75
100
  ## Planning defaults
76
101
 
77
- 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.
78
103
 
79
104
  Python `PlannerConfig` defaults to `document_format="plain"`; set it to `"ssmd"` when a Python string contains SSMD source.
80
105
 
@@ -85,7 +110,7 @@ Python `PlannerConfig.renderability_mode` also defaults to safe punctuation-only
85
110
  ## Python API
86
111
 
87
112
  ```python
88
- from utterplan import PlannerConfig, UtterancePlan, compile_document
113
+ from utterplan import PlannerConfig, FlowPlan, compile_document
89
114
 
90
115
  ssmd_source = """---
91
116
  ssmd_version: "0.9"
@@ -102,7 +127,7 @@ result = compile_document(
102
127
  plan = result.plan
103
128
  assert result.trace is not None
104
129
  plan.save("example.utterplan.toml")
105
- assert UtterancePlan.load("example.utterplan.toml") == plan
130
+ assert FlowPlan.load("example.utterplan.toml") == plan
106
131
  ```
107
132
 
108
133
  `compile_document` is the stable public one-document API shared by consumers. The
@@ -130,21 +155,9 @@ Callbacks run synchronously and exceptions propagate. See the [Python API guide]
130
155
 
131
156
  ## Renderer-consumer boundary
132
157
 
133
- Renderers consume `PlanSegment.text`, which is prepared/spoken text, and use
134
- `spoken_start`/`spoken_end` for spoken-text coordinates. Resolved segment
135
- pauses, language, directives, annotations, boundaries, semantic boundaries,
136
- markers, units, and
137
- document metadata are public plan fields. Semantic boundaries are stable
138
- engine-neutral opportunities for spoken-text subdivision; they are not pause
139
- events and carry no duration or renderer policy. Plans contain no phonemes, model
140
- tokens, model sessions, renderer configuration, provider documents, or audio.
141
- For SSMD input, `plan.annotations` preserve declared source semantics and source
142
- provenance, `document_metadata` preserves portable header data, and
143
- `segment.directives` carries effective typed semantics after scope and voice-default
144
- resolution. Typed directives include voice, pronunciation, prosody, emphasis, say-as,
145
- substitution, audio references, and extension references. Audio and extensions are
146
- 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.
147
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.
148
161
  The intended dependency direction is:
149
162
 
150
163
  ```text
@@ -159,6 +172,7 @@ renderer repository rather than UtterPlan's test suite.
159
172
 
160
173
  - [Getting started](docs/getting-started.md)
161
174
  - [CLI](docs/cli.md)
175
+ - [SSMDBook workflows](docs/ssmdbook.md)
162
176
  - [Format and schema](docs/format.md)
163
177
  - [Consumer guide](docs/consumer-guide.md)
164
178
  - [Architecture](docs/architecture.md)
@@ -170,10 +184,9 @@ renderer repository rather than UtterPlan's test suite.
170
184
 
171
185
  ## Versions
172
186
 
173
- 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.
174
188
 
175
- 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.
176
- 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.
177
190
 
178
191
  ## Development
179
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,38 @@
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
+
19
+ ## [0.4.1] - 2026-10-07
20
+
21
+ ### Added
22
+
23
+ - Added persistable planning attempts with inspectable renderability outcomes and safe repair assessments
24
+
25
+ ### Changed
26
+
27
+ - Changed planning APIs to expose blocked candidates without weakening canonical plan validation
28
+
29
+ ### Fixed
30
+
31
+ - Fixed legacy SSMD scene breaks to preserve front-matter boundaries and clean-to-source offsets
32
+
33
+ ### Documentation
34
+
35
+ - Documented planning-attempt artifacts, inspection workflows, and renderability guarantees
36
+
37
+ <!-- generated by releaseledger -->
38
+
7
39
  ## [0.4.0] - 2026-10-06
8
40
 
9
41
  ### 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,25 @@ 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`.
129
+
130
+ ## Inspect a persisted planning attempt
131
+
132
+ `inspect` reads canonical plans. Persistable planning outcomes use the separate
133
+ `utterplan.planning-attempt.v1` artifact and are opened with `inspect-attempt`:
134
+
135
+ ```bash
136
+ utterplan inspect-attempt chapter.attempt.toml
137
+ utterplan inspect-attempt chapter.attempt.toml --issues
138
+ utterplan inspect-attempt chapter.attempt.toml --segment seg-000001 --unit unit-000001
139
+ utterplan inspect-attempt chapter.attempt.toml --json
140
+ ```
141
+
142
+ The default view summarizes status, renderability, and candidate size. `--issues`
143
+ shows source context and conservative repair assessments; segment and unit selectors
144
+ accept an ID or zero-based index. `--json` emits the complete artifact as JSON for
145
+ inspection, but the persisted attempt itself remains TOML. A blocked candidate is an
146
+ inspect-only draft, not a canonical plan, and is rejected by `FlowPlan.load()`.
102
147
 
103
148
  ## Planning controls
104
149
 
@@ -124,11 +169,13 @@ utterplan validate chapter.ssmd.md
124
169
  utterplan validate plain.txt --input-format plain --language en-us
125
170
  utterplan inspect chapter.utterplan.toml --segment 0
126
171
  utterplan inspect chapter.utterplan.toml --unit 0 --boundaries --tokens
127
- utterplan inspect chapter.utterplan.toml --preparation
128
- 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
175
+ utterplan inspect-attempt chapter.attempt.toml --issues
129
176
  ```
130
177
 
131
- `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.
132
179
 
133
180
  ## Migrate a saved plan
134
181
 
@@ -148,11 +195,7 @@ route and reports source schema, target schema, and whether migration is require
148
195
  without writing a file. A future schema version is rejected rather than guessed
149
196
  or downgraded.
150
197
 
151
- Schema migration is a separate operation from SSMD source migration. UtterPlan
152
- preserves released schemas v1, v2, and v3 and migrates supported plans through the
153
- registered chain to current schema v4. The v3-to-v4 step does not rerun parsing,
154
- NLP, or planning. Use `ssmd migrate FILE --to 0.9` for older SSMD source
155
- 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.
156
199
 
157
200
  For a saved TOML plan, `validate` verifies the current semantic schema and plan
158
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.