microsoft / microsoft/prompty

Shrink the authored surface: TypeSpec as single source of truth, hand-write only what conformance requires

Open
#511 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Rust
Stars
1.3k
Forks
127
Avg merge
9h 23m
Merged PRs (30d)
38

Description

🚀 Feature Request

Prerequisites
  • I have checked the latest documentation and this feature doesn't exist
  • I have searched for similar feature requests and found none
  • I have linked to related issues or discussions in the description (if any exist)
Type of Improvement

Developer Experience

Guiding principle

The TypeSpec spec is the single source of truth. Everything that can be mechanically and predictably derived from the spec should be emitted by the Typra emitter, not hand-ported per runtime. The only code we author by hand is the irreducible minimum required to conform to the vectors and samples — the spec (via @vector/@sample conformance) is what enforces correctness. If a body of code is structurally identical across runtimes and derivable from the schema/seam definitions, it is a bug that we author it 7×.

Current state (measured 2026-08-27, all 7 runtimes)

Classified every non-build source file as generated (carries the Code generated by Typra emitter marker) vs authored; tests separated.

Runtime Generated Authored src Authored tests Authored src %
go 77,446 6,007 1,490 7.2%
csharp 65,738 10,823 11,262 14.1%
python 46,269 9,445 11,302 17.0%
typescript 32,550 9,422 10,247 22.4%
swift 21,514 7,752 8,404 26.5%
java 30,796 14,831 10,874 32.5%
rust 49,435 26,979 10,654 35.3%

Generated ≈ 324k lines vs authored-non-test 85k (~21% of production source). Go is the target shape (7%); Rust is the outlier (35%, 27k authored). The spread itself is the signal — the same runtime concept costs 7% in Go and 35% in Rust, which means most of the delta is mechanical code that should be emitted uniformly.

Where the 85k authored source lives (cross-cutting categories, each duplicated ~7×)
Category Authored lines Mechanization verdict
core runtime (loader / dispatch / discovery) 28,829 Partly — dispatch/discovery already emitted; residue is loader I/O + migration table
provider glue (openai / anthropic / foundry) 22,418 Largely — wire DTOs + field-mapping are schema; only transport glue is irreducible
engine / pipeline (agent loop, turn engine, ctx packing) 16,616 Keep — genuine orchestration logic
jinja-subset (template engine port) 6,993 Yes, but not via TypeSpec — algorithm; single-source + transpile/vendor
harness / reference impls 3,871 Partly
tracing 3,387 Yes — structurally identical plumbing
seam / vector adapter doubles 3,145+ Yes — already schema-derivable
Proposed Solution

Drive the authored surface down to an irreducible floor by moving each mechanical category into the emitter. Work items, ranked by leverage × predictability:

Tier 1 — pure schema, fits the existing emitter, do first

  1. Emit the seam/vector adapter doubles. Go seam_providers.go (1,390), C# VectorProviders.cs, Rust vector_adapters.rs, Java VectorProviders.java are mechanically derivable from the seam interface + @dispatch variant set — proven by hand-writing the Go + Rust versions during the 2.0.2 cycle. Emitting these also eliminates the recurring "fill the doubles by hand after every regen" thrash. Use the existing hand-written Go/Rust doubles as the golden reference for the template.
  2. Emit provider wire DTOs + response field-mapping. A generated wire layer already exists (140 files, e.g. AnthropicWireMessage), yet every provider re-hand-authors its own: Rust wire.rs 1,092 + processor.rs 1,338, Java Wire.java 573, TS wire.ts 549, C# WireFormat.cs 323. OpenAI/Anthropic request/response schemas are pure data — emit them and the deterministic field-mapping, leaving only the thin HTTP/SDK call authored.

Tier 2 — structural, needs a tiny spec/data source
3. Emit tracing plumbing (3.4k, 5 runtimes) — identical span/tracer scaffolding.
4. Data-drive the loader legacy-migration table — the v1→v2 rename map is data, currently hand-coded in each migration.*.

Tier 3 — mechanize outside TypeSpec
5. De-duplicate jinja-subset (7k, 7×) — biggest pure duplication, but it's an algorithm, not a schema. Single source-of-truth + transpile, or vendor a real engine.

Irreducible authored floor (the target end-state): executor transport glue, engine/pipeline orchestration, and loader frontmatter/${env}/${file} resolution. Everything else above should be emitted.

Specific flags
  • Rust is the priority runtime — at 27k it's 3–4× the leanest. Its provider stack (wire 1,092 + processor 1,338 + executor 893 ≈ 3.3k) and engine+pipeline (~5.4k) are heavier than every peer; it's likely carrying reference-impl weight that should be emitted or trimmed to match the others' generated coverage.
  • Emitter-side changes land in the Typra repo (sethjuarez/typra); the prompty side is regen + gap-fill until vectors/samples stay green. Each Tier-1/2 item should ship red-first with a fixture, consistent with the 2.0.x workflow, and ideally gated in validate:fixtures so regressions fail Typra CI (as the rust.dispatch-regression-compile gate already does).
Definition of done
  • Authored-src % converges toward the Go baseline (~single digits) across all runtimes.
  • No hand-written seam/vector adapter doubles, provider wire DTOs, or tracing plumbing remain — all emitted.
  • The only hand-authored production code is executor transport glue, engine/pipeline orchestration, and loader resolution.
  • All 7 runtimes stay green on vectors + samples throughout (spec-enforced conformance).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the Typra emitter and compare the existing Go seam_providers.go and Rust vector_adapters.rs implementations, which are identified as golden references. Review the provider wire files and the validate:fixtures workflow, including the rust.dispatch-regression-compile gate. Done means the selected mechanical code is emitted, runtime vectors and samples remain green, and authored seam/vector doubles or provider wire DTOs no longer remain for that scope.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, go, java, python, rust, swift, typescript
Domain
build-system, developer-experience, testing-qa, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
34/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.