Emitter boundary
Typra is a contract projector, not a general-purpose source translator. It emits runtime surfaces whose shape and behavior can be derived deterministically from TypeSpec, Typra decorators, and emitter configuration. Consumers own algorithms and runtime policy that the contract does not define.
This boundary keeps generated output reviewable, makes parity across targets measurable, and prevents seven generated implementations from becoming seven hidden sources of product behavior.
The decision rule
Section titled “The decision rule”Apply the rule to the generated surface under evaluation, not necessarily to the whole feature request. A mixed request can contain a schema-derived seam and a consumer-owned implementation.
Ask one question first:
Can the requested behavior be derived completely and deterministically from the contract?
| Classification | Typra’s responsibility | Consumer’s responsibility |
|---|---|---|
| Schema projection | Generate it and prove equivalent behavior across targets. | Supply runtime dependencies or implementations only where the contract declares a seam. |
| Mixed | Generate types, protocols, dispatch, adapters, and conformance evidence. | Implement the algorithm or policy behind the generated seam. |
| Algorithm or runtime policy | Do not generate the implementation. Define an interoperable seam only when the contract needs one. | Author, vendor, or transpile the implementation. |
A capability belongs in the emitter when all of these are true:
- Its inputs and semantics are present in TypeSpec, a Typra decorator, explicit emitter configuration, or a documented deterministic emitter convention.
- A domain-neutral fixture and, when observable, an
@vectorcan pin behavior that every target must satisfy. - The behavior can be expressed as a domain-neutral fixture and, when observable, an executable vector.
- Every supported target can implement it without importing product policy.
If any answer is no, keep the implementation consumer-owned. Typra may still project the contract around it.
Emitted today
Section titled “Emitted today”- Models, fields, optionality, nullability, wire names, and serialization helpers.
- Closed and open polymorphic shapes and scalar coercion.
- Interfaces and operation signatures.
@dispatchprovider and resolver contracts.- Samples, vectors, compile gates, and conformance evidence derived from those declarations.
These are projections: changing the TypeSpec changes the generated surface predictably.
Prefer existing language
Section titled “Prefer existing language”Passing the projection boundary is necessary, but not sufficient. Before adding a Typra capability, prefer:
- Native TypeSpec constructs and libraries.
- Existing Typra contracts such as interfaces, operations,
@dispatch,@sample, and@vector. - Small consumer-authored implementations pinned by generated conformance.
Add a Typra concept only when those cannot express a general, deterministic contract. Saving a small amount of registration or adapter code does not justify a permanent decorator, mapping language, or seven-target runtime surface.
What consumers own
Section titled “What consumers own”- Parsers, evaluators, renderers, planners, tokenizers, and other general algorithms.
- Authentication token acquisition and refresh policy.
- Retry, timeout, caching, persistence, logging, tracing, and deployment policy.
- Product-specific provider selection or plugin discovery behind a generated wildcard seam.
- Runtime integrations whose behavior cannot be inferred from the contract.
These choices can vary without changing the wire contract. Generating them would hide product policy in the emitter and make Typra responsible for maintaining the same algorithm in every target.
Worked negative example: a Jinja-subset engine
Section titled “Worked negative example: a Jinja-subset engine”A Jinja-subset tokenizer, parser, AST, and evaluator is an algorithm. One consumer measured the engine alone (excluding tests) as:
| Runtime | Lines |
|---|---|
| Go | 1,320 |
| Rust | 1,211 |
| C# | 1,040 |
That is roughly 1,000–1,350 lines per runtime, but duplication alone does not make it schema projection. TypeSpec can describe a renderer seam, its inputs, its output, dispatch variants, and conformance vectors; it does not determine tokenization rules, expression evaluation, escaping policy, or error recovery.
Typra should therefore emit the renderer contract and tests, while the consumer should author, vendor, or transpile the engine. Moving the algorithm into Typra would merely relocate seven implementations into the generator and couple every consumer to one product-policy choice.
Companion assets
Section titled “Companion assets”Keep authored or transpiled algorithms outside every configured target output-dir:
generated/typescript/ # emitter-owned target outputgenerated/python/ # emitter-owned target outputsrc/algorithms/ # authored, vendored, or transpiled companion assetssrc/adapters/ # consumer implementations of generated seamsGenerated provider interfaces and conformance vectors are the integration boundary. The companion asset can
change implementation strategy without changing generated code. When authored files must be colocated with target
output, use protected-paths or hydration-zones rather than relying on a directory
name to prevent cleanup. See Generated output for the output lifecycle.
Triage examples
Section titled “Triage examples”| Request | Classification | Decision |
|---|---|---|
Preserve @encodedName during load/save |
Schema projection | Emit it. |
| Route unknown open-union values to a wildcard provider | Schema projection | Emit routing; require a consumer implementation. |
| Generate a template parser/evaluator | Algorithm | Keep consumer-owned. |
| Represent a historical property rename | Native TypeSpec versioning | Consume TypeSpec.Versioning.@renamedFrom; do not create a Typra equivalent. |
| Accept an old payload in a current runtime | Mixed | Project native version history where useful; keep migration policy consumer-owned unless the contract determines it completely. |
| Retry failed operations three times | Runtime policy | Keep consumer-owned. |
| Generate a seam that accepts a retry policy | Mixed | Emit the seam; consumer owns policy behavior. |
When classification is unclear, open a design discussion before an implementation issue. The burden for a new emitter capability is to show the schema-derived rule and a target-independent conformance case. See Typra contracts for the source model that projection begins from.