You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
From the second verified review of PR #26 (finding R2-1, CONFIRMED). Decision-first: the registration shape needs a maintainer seal before more client families pile onto it.
Finding.AddOpenCode registers the typed OpenCodeClient transient over the factory client, and SessionsClient as a transient resolving a hiddenOpenCodeClient per resolution (OpenCodeServiceCollectionExtensions.cs:53). Three lifetime hazards follow:
Root-provider retention — MS.Ext.DI tracks every transient IDisposable; a background service resolving from the root provider accumulates container-tracked OpenCodeClient instances until shutdown.
Scope-disposal poisoning — a consumer storing a scope-resolved SessionsClient beyond its scope gets ObjectDisposedException on every later call; SessionsClient is not IDisposable, so nothing signals the constraint, and Pipeline.Dispose sets _disposed = true unconditionally even on the borrowed-transport path where it owns nothing.
Split pipelines — injecting both OpenCodeClient and SessionsClient yields two unrelated pipelines; configuring/disposing one never affects the other.
Plus: the hand-grown one-line-per-family sub-client registration has no roster contract test, so the next generated client family silently lags DI until a consumer hits resolution failure.
Design space to weigh at the seal: scoped vs transient lifetimes; whether the borrowed-transport Pipeline.Dispose should no-op _disposed; resolving sub-clients from the sameOpenCodeClient instance (e.g. via a scoped root); a generated or contract-tested registration roster (the Session 21 note already flags generator-emitted registrations as a trigger-based option).
Trigger: the first real DI consumer beyond the sandbox, or the next Extensions batch — whichever comes first. The hazards are live today but only bite consumers holding clients across scopes.
Milestone: M2 (the Extensions package grows in parallel with breadth; the shape must seal before more families multiply the registration list).
Superseded by the Q92 seal (research log Session 24, ADR-0010): the registration goes singleton-first without IHttpClientFactory, which resolves all three lifetime hazards by construction. This issue closes with the reshape PR that opens the M3 runway; the roster contract test carries over into that PR as this issue's one live remainder.
Activity
docs: seal Q92 (ADR-0010) and open M3 — simplicity-first construction…
Blind-Striker commentedon Aug 15, 2026
Superseded by the Q92 seal (research log Session 24, ADR-0010): the registration goes singleton-first without IHttpClientFactory, which resolves all three lifetime hazards by construction. This issue closes with the reshape PR that opens the M3 runway; the roster contract test carries over into that PR as this issue's one live remainder.