Skip to main content

renderplan MVP

renderplan is a deliberately small Python contract package shared by UtterPlan, VoiceRender, and AudioCompose. It contains no SSMD compiler, NLP, TTS engine, G2P, waveform, DSP, or orchestration implementation.

The intended dependency graph is:

utterplan ──────┐
voicerender ────┼──> renderplan
audiocompose ──┘

The applications do not depend on each other; the contract package is their only shared dependency.

Contracts

The package defines four TOML documents:

  1. renderprofile.toml — seeded by VoiceRender and user-owned. It contains opaque, self-contained renderer bindings, portable requirements, optional capacity descriptions, split/fallback policy, and explicit pause durations. Shared pause modes are manual and none; orchestration pass limits do not belong in this contract.
  2. renderplan.toml — produced by UtterPlan. Its ordered flow is the exact serial execution contract: numbered speech requests, exact NNNNNN.wav names, generic pauses, audio items, controls, tokens, source provenance, and role bindings copied from the profile.
  3. renderplan-preflight.toml — produced by VoiceRender for one exact RenderPlan. It has status ok, replan, or reject and refers to speech occurrences by (segment_number, segment_id).
  4. render-manifest.toml — produced by VoiceRender. It binds WAV metadata to exact (segment_number, segment_id) plan occurrences. A complete manifest contains exactly every plan speech occurrence; an incomplete one may contain only occurrences from that plan.

Consumers can use the shared joins instead of implementing their own parsers:

plan.validate_against_profile(profile)
report.validate_against(plan)
manifest.validate_against(plan)

These are portable contract checks only; they do not resolve engines, inspect WAV files, or orchestrate a pipeline.

UtterPlan v7 source and token mapping

The first producer uses zero-based v7 provenance locators such as f000000.s000, f000000.s001, and f000001.s000: six digits for the flow index and three for the segment index. A locator is an opaque provenance address, meaningful only together with RenderPlan.source_plan_id; it is not a globally stable segment ID. renderplan does not parse or resolve locators and has no UtterPlan dependency.

SourceSpan.start and .end are Python string/code-point offsets into the prepared FlowSegment.text. For every speech request, UtterPlan must prove:

SpeechItem.text == concatenation, in order, of each referenced FlowSegment.text[start:end]

Do not trim request-edge whitespace. These offsets also map source spans and request-local controls/tokens deterministically. Source-to-text equality is proved by UtterPlan against its source document, not by renderplan. The destination start offset of source span N inside the request is the sum of the lengths of all preceding source slices. This preserves a direct mapping without trimming or a second offset table.

TokenBundle.span is a dense, ordered list of request-local [start, end] character ranges; pos and tag, when present, are dense parallel arrays. lemma and morph are sparse arrays of [token_index, value]. VoiceRender derives a token surface from speech.text[start:end]. Profile-required token fields must be complete under those semantics; available optional fields should be preserved, but lemma and morph should not be declared required unless an adapter genuinely requires them.

SpeechControl is request-local and renderer-neutral: it carries start, end, name, and TOML-safe params. Initial semantic names include pronunciation, prosody, emphasis, say_as, and extension:<name>. Controls participate in segment_id; renderers decide support, and unsupported controls must fail preflight rather than be ignored. Control ranges may overlap only when the source semantics permit it. Engine-specific voice selection is resolved into the opaque logical role/binding; audio directives become AudioItems.

Bindings copied into plans must be self-contained enough to execute without reopening the RenderProfile. This contract does not define renderer-specific path keys or local-asset resolution. This schema has no generic asset-reference type yet. A VoiceRender profile producer must refuse bindings that depend on profile-local or otherwise uncopied asset state; do not introduce renderer-specific asset-path keys into this shared contract.

Identity and replan contract

segment_id identifies the exact synthesis request: text, language, role, binding, tokens, and controls. It excludes display number and plan provenance such as source spans, split reason, planning level, and semantic end. Duplicate requests may therefore share a segment_id; (segment_number, segment_id) identifies each occurrence within a plan, report, or manifest.

plan_id identifies the complete ordered execution flow, including speech numbers/order, request IDs, provenance and planning semantics, preflight requirements, every pause, and every audio item. Producer package versions do not change semantic profile or plan identity. Exact source-file bytes are not included in RenderPlan identity.

A PreflightReport describes failures only for its concrete RenderPlan; it cannot preserve successful capacity splits from earlier attempts. The replan join is therefore:

original UtterPlan + RenderProfile + previous RenderPlan
                           + PreflightReport for that previous RenderPlan
                              -> new RenderPlan

UtterPlan uses the previous plan as the partition baseline and rebuilds only failed source ranges. Each replan request must correspond to a too_long check and exactly match that speech occurrence's source coverage and current planning level. VoiceRender preflight never edits the plan. replan is only for recoverable capacity failures; missing engines, unknown voices, unsupported controls, invalid token fields, and frontend/API failures are reject conditions.

A PauseItem is a generic serial event positioned by flow, with duration, reason, and optional provenance; it can lead a flow or follow speech, audio, or another operation. No preceding speech number is required. The ordered flow is authoritative for AudioCompose.

Example preflight occurrence

[[checks]]
segment_number = 37
segment_id = "sha256:..."
status = "too_long"
metric = "model_tokens"
measured = 532
maximum = 510
source = "pykokoro.prepare"

[[replan]]
segment_number = 37
segment_id = "sha256:..."
current_level = "sentence"
action = "split"
reason = "capacity"
metric = "model_tokens"
measured = 532
maximum = 510

[[replan.source]]
locator = "f000123.s004"
start = 0
end = 42

UtterPlan does not need to understand model_tokens; the source-plan ID, copied profile ID, exact plan ID, source ranges, and generic split level/action allow stale feedback to be rejected without importing VoiceRender.

Install for development

This repository intentionally has no src/ directory.

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy renderplan

Versioning is dynamic through setuptools-scm; create Git tags such as v0.1.0. A source tree without Git metadata uses the configured development fallback version.

Example API

from renderplan import load_plan, load_preflight

plan = load_plan("chapter.renderplan.toml")
report = load_preflight("chapter.preflight.toml")

report.validate_against(plan)
if report.status == "replan":
    for request in report.replan:
        print(request.segment_number, request.action, request.source)

MVP invariants

  • Persisted identities are SHA-256 over canonical semantic payloads; producer versions are provenance, not identity.
  • Speech numbers are contiguous starting at 1; speech N maps to NNNNNN.wav.
  • Speech-request identity is stable across renumbering; full plan identity changes when flow order or execution semantics change.
  • RenderPlan.validate_against_profile, PreflightReport.validate_against, and RenderManifest.validate_against enforce portable joins and exact occurrence matching.
  • VoiceRender preflight never changes the plan, and rendering never introduces unplanned speech segments.
  • AudioCompose consumes RenderPlan flow and RenderManifest artifacts; it does not reconstruct pauses from UtterPlan.
  • Engine-specific binding tables are opaque to UtterPlan and AudioCompose.

Metadata

Release files for renderplan 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for renderplan 0.1.0
File Size Uploaded
renderplan-0.1.0.tar.gz 47.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for renderplan 0.1.0
File Interpreter ABI Platform
renderplan-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 74.4 kB

Release files / renderplan-0.1.0.tar.gz

Download URL renderplan-0.1.0.tar.gz
Size 47.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a4cc89cf89d493fea85d4521a3576a1100f0f670a4fb6713af39d3eb89f6c7ea
BLAKE2b-256 checksum
How to use checksums
a2c7836af3fb2c448b7057dfa637470c5fc9a3c8c72b728e801a0bb63261656e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.14

Release files / renderplan-0.1.0-py3-none-any.whl

Download URL renderplan-0.1.0-py3-none-any.whl
Size 26.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f8522716f505771fc34288ac433736af937c610abb922a4d137a0ce5c2a1309
BLAKE2b-256 checksum
How to use checksums
507bb6dba564f6e1f8683f4b09c098f4f96c78c7b359a2baa4997e6b460cb15e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.14

Release history Release notifications | RSS feed

0.1.2

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page