Claude: changes for issue #46 #55
No reviewers
Labels
No labels
breaking-change
bug
documentation
duplicate
enhancement
good first issue
help wanted
performance
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/ATProto.NET!55
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/issue-46"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Requested in #46.
@claude-bot Please review.
🤖 On it — follow along in the action run; the reply will link the full session transcript.
RegisterUnionVariant only augments a type that already carries [JsonPolymorphic]; without it the registration is silently ignored (writes emit {}, reads throw NotSupportedException). And CreateOptions() is not the options instance GetCollection<T> uses, so runtime-registered variants do not reach RecordCollection<T>. Both caveats are now stated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>Reviewed the branch, verified the fix empirically, and pushed one follow-up commit.
Verdict: the fix is correct
The bug is real and the diagnosis is exact. I reverted the two source files to
main, kept the new test file, and ran it — all 6 tests fail with precisely the exception the CHANGELOG cites:On the branch, all 6 pass. So these are genuine regression tests, not tests written to match the new code.
Removing the factory is the right call, not a workaround.
CanConvertclaimed everyIAtProtoUnionimplementor andCreateConverterreturnednull— System.Text.Json rejects that combination outright, so the factory could never have worked for any type it claimed. Union discrimination genuinely comes from[JsonPolymorphic]/[JsonDerivedType]plusLexiconTypeRegistry.ApplyUnionVariants; the factory contributed nothing.Blast radius is contained. I grepped the whole repo: no SDK type implemented
IAtProtoUnion, so the breakage only ever hit user code that opted into the marker — which matches issue #46.UnionJsonConverterFactorywasinternal, so its removal is not a public-API break, andIAtProtoUnionstays public. Classifying this underFixedrather thanBreaking changesis correct.Build and tests:
dotnet build→ 0 errors; the new<see cref="LexiconTypeRegistry.RegisterUnionVariant{TBase, TDerived}(string)"/>resolves with no CS1574. Full unit suite: 1000 passed, 0 failed.Two problems I found in the new docs section — fixed in
62fbc4bThe PR's new "Union Types" section told readers to use
LexiconTypeRegistry.Instance.RegisterUnionVariant(...)for open unions. Both halves of that advice were misleading, so I corrected them on the branch rather than just flagging them:RegisterUnionVariantsilently no-ops without[JsonPolymorphic]on the base.ApplyUnionVariantsreturns early whentypeInfo.PolymorphismOptions is null, which is exactly the case for the "truly open, no compile-time arms" union a reader would picture. I confirmed with a scratch test: serialization emits{"u":{}}— all derived properties silently dropped — and deserialization throwsNotSupportedException: Deserialization of interface or abstract types is not supported. Silent data loss on write is the worse half.CreateOptions()is not the options instance the documented API uses.RecordCollection<T>hardcodesAtProtoJsonDefaults.Optionsat four call sites, as doRepoClientandXrpcClient, andAtProtoJsonDefaultsnever consults the registry.GetCollection<T>takes no options parameter, so there is no way to feed the registry's options in. The recipe sat in a document whose entire subject isGetCollection<T>, where it cannot take effect. Runtime registration does work for Jetstream's typed decoding (JetstreamModels.cs:163) and for directJsonSerializercalls — the docs now say exactly that.Neither is a regression from this PR; both are pre-existing registry limitations. But this PR is what points users at that path, so the caveats belong with it.
One follow-up worth its own issue
The real asymmetry is that
AtProtoJsonDefaults.OptionsandLexiconTypeRegistry.CreateOptions()are now near-identical except that only the latter carries theApplyUnionVariantsmodifier — so plugin-registered union variants never reach the main client path. Wiring the registry'sTypeInfoResolverintoAtProtoJsonDefaultswould close that, but it has subtle caching semantics (AtProtoJsonDefaults.Optionsis a??=-cached singleton, so late registrations wouldn't apply, whereas the registry hands back a fresh options object each time it's invalidated). That's a behavior change beyond issue #46's scope, so I documented the limitation instead of changing it unilaterally.Branch
claude/issue-46is updated and green; the change is docs-only, so no CHANGELOG entry was added per the repo's doc-only exemption — and the existing #46 entry already covers the docs section.⏱ 4m 29s · 25 turns · tokens: 37.9k in / 11.7k out (+948.0k cache-read)
📜 Full session transcript