Problem
tdbin refuses any union whose variant carries named fields. Our production schema fails on the very first union:
$ typediagram verify docs/models/live-ipc.td
0:0 error tdbin: variant 'OpenRange' must be bare or a single tuple field in v0
The offending declaration is ordinary typeDiagram DSL that --to rust, --to typescript, --to csharp etc. all accept:
union FindSimilarInput {
OpenRange {
path: String
start_byte: Int
end_byte: Int
}
Snippet {
snippet: String
language: String
}
}
This is not a rare shape. In one schema we have four of them, and they are all load-bearing wire types:
| Union |
Variants with fields |
FindSimilarInput |
OpenRange { path, start_byte, end_byte }, Snippet { snippet, language } |
AnalysisState |
Running { started_at_ms }, Errored { message } |
RequestId |
Number { value }, String { value } |
MergeVerdict |
AiOrHuman { reason } |
Because verify aborts at the first one, tdbin currently covers zero percent of our schema. There is no incremental adoption path — not "most types work", but "the file is rejected".
Why this looks like a generator gap, not a format gap
docs/tdbin-wire-format.html already specifies the encoding:
"Records and struct-unions are pointer-encoded as separate objects."
and the evolution rules already talk about payload variants:
"Appending bare or payload variants to unions (if discriminant width unchanged)"
So the wire format contemplates struct-shaped variants. The restriction appears to live in the emitter/verifier, phrased as a v0 limitation.
Ask
Support struct-form union variants in encode / decode / verify, encoded per the existing struct-union pointer rules: discriminant in the data section, variant payload as a pointer to a struct laid out by the normal [TDBIN-REC-ALLOC] rules.
If that genuinely cannot land in v0, then at minimum:
- Make the error message say what the workaround is, and
- Do not abort the whole file — report every unsupported declaration in one pass so a consumer can see the total scope of the problem instead of fixing one and re-running.
Rewriting each variant into a named side record is not an acceptable workaround for us: the .td file is the single source of truth for the JSON wire shape and the Rust/TS types, and flattening the unions changes the JSON representation that shipped clients already depend on.
Problem
tdbin refuses any union whose variant carries named fields. Our production schema fails on the very first union:
The offending declaration is ordinary typeDiagram DSL that
--to rust,--to typescript,--to csharpetc. all accept:This is not a rare shape. In one schema we have four of them, and they are all load-bearing wire types:
FindSimilarInputOpenRange { path, start_byte, end_byte },Snippet { snippet, language }AnalysisStateRunning { started_at_ms },Errored { message }RequestIdNumber { value },String { value }MergeVerdictAiOrHuman { reason }Because
verifyaborts at the first one, tdbin currently covers zero percent of our schema. There is no incremental adoption path — not "most types work", but "the file is rejected".Why this looks like a generator gap, not a format gap
docs/tdbin-wire-format.htmlalready specifies the encoding:and the evolution rules already talk about payload variants:
So the wire format contemplates struct-shaped variants. The restriction appears to live in the emitter/verifier, phrased as a v0 limitation.
Ask
Support struct-form union variants in
encode/decode/verify, encoded per the existing struct-union pointer rules: discriminant in the data section, variant payload as a pointer to a struct laid out by the normal[TDBIN-REC-ALLOC]rules.If that genuinely cannot land in v0, then at minimum:
Rewriting each variant into a named side record is not an acceptable workaround for us: the
.tdfile is the single source of truth for the JSON wire shape and the Rust/TS types, and flattening the unions changes the JSON representation that shipped clients already depend on.