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
Split from #221 (part b of three). Parent issue has the full sweep context. This is the soundness-sensitive half — do not start it before (a) #227 and (c) land, and review it against the rejected-approaches history.
The pattern
An Application-derived subscriber (App : Application) subscribes to an app-scoped instance that is not a literal static field. The existing clsIsApp exemption already accepts a static source for an Application subscriber; here the source is resolved from application-scoped state (verified: PaletteHelper().GetThemeManager() returns an IThemeManager bound to the app's own merged ResourceDictionary, PaletteHelper.cs:22-26) — genuinely process-lifetime, just reached through a resolver call instead of a static field.
Design guardrails (fixed at split time — READ FIRST)
oracle-known-fps.md "Rejected approaches" documents why a broad clsIsStatic subscriber exemption was reverted as unsound: a static-class subscriber says nothing about a lambda capturing a shorter-lived local. This sub-issue must not reintroduce that shape.
The loosening applies only when the subscriber class itself derives from Application (the existing clsIsApp gate — keep it byte-for-byte); what loosens is only the source check: from "literal static" to "app-scoped resolver result".
The handler must be a method-group of the App class itself (no lambdas capturing locals — that is the exact hole the rejected approach had).
Negative controls in the sample: (1) same subscription from a non-Application class → still flagged; (2) an Application subscriber whose handler is a lambda capturing a local disposable → still flagged.
Acceptance
Sample with the App shape (silent), plus both negative controls (flagged), CI assertions all three ways.
A short note update to docs/notes/oracle-known-fps.md explaining why this is NOT the rejected clsIsStatic broadening (subscriber gate unchanged, source list curated, method-group only).
Split from #221 (part b of three). Parent issue has the full sweep context. This is the soundness-sensitive half — do not start it before (a) #227 and (c) land, and review it against the rejected-approaches history.
The pattern
An
Application-derived subscriber (App : Application) subscribes to an app-scoped instance that is not a literalstaticfield. The existingclsIsAppexemption already accepts a static source for an Application subscriber; here the source is resolved from application-scoped state (verified:PaletteHelper().GetThemeManager()returns anIThemeManagerbound to the app's own mergedResourceDictionary,PaletteHelper.cs:22-26) — genuinely process-lifetime, just reached through a resolver call instead of a static field.Evidence: MaterialDesignInXamlToolkit
src/MahMaterialDragablzMashUp/App.xaml.cs:10,22.Design guardrails (fixed at split time — READ FIRST)
oracle-known-fps.md"Rejected approaches" documents why a broadclsIsStaticsubscriber exemption was reverted as unsound: a static-class subscriber says nothing about a lambda capturing a shorter-lived local. This sub-issue must not reintroduce that shape.Application(the existingclsIsAppgate — keep it byte-for-byte); what loosens is only the source check: from "literal static" to "app-scoped resolver result".PaletteHelper.GetThemeManager()(match by containing type + method name). Extending the list requires a new confirmed sibling — same policy as the Precision gap: CommandManager.RequerySuggested (weak-referenced WPF static event) flagged as a hard error #223 weak-event allowlist.Acceptance
docs/notes/oracle-known-fps.mdexplaining why this is NOT the rejectedclsIsStaticbroadening (subscriber gate unchanged, source list curated, method-group only).Refs:
docs/notes/oracle-sweep-2026-07-10.md(MaterialDesignInXamlToolkit section),docs/notes/field-notes-patterns.mdentry 15.