Skip to content

fix(extractor): curated app-scoped source exemption for the Application subscriber (Closes #228)#232

Merged
PhysShell merged 3 commits into
mainfrom
claude/plans-tasks-review-u77dfs
Jul 11, 2026
Merged

fix(extractor): curated app-scoped source exemption for the Application subscriber (Closes #228)#232
PhysShell merged 3 commits into
mainfrom
claude/plans-tasks-review-u77dfs

Conversation

@PhysShell

Copy link
Copy Markdown
Owner

Что и зачем

Issue #228 (под-задача (b) родительского #221, самая деликатная по soundness): App : Application, подписывающийся на PaletteHelper().GetThemeManager() — app-scoped, процессно-живой инстанс, доставаемый через resolver-вызов, а не литеральный static-член, — тонул в общий source == "injected" и давал OWN001-warning (FP MaterialDesign MahMaterialDragablzMashUp/App.xaml.cs из sweep'а #201). Подписка ничего не промоутит: подписчик сам процессно-живой, источник привязан к состоянию самого приложения. Narrowing инвертирует каждое свойство, утопившее отвергнутый clsIsStatic (см. «Rejected approaches»): гейт подписчика — байт-в-байт прежний clsIsApp; источник — только курируемый allowlist resolver'ов (ровно PaletteHelper.GetThemeManager, расширение — по одному подтверждённому родственнику, как в #223), резолвится семантически через local-binding ресивера (var-инициализатор / is-pattern, касты и ! очищаются), любой недоказуемый шаг = сегодняшний честный warning; хендлер — только method group самого App-класса, лямбда отвергается сразу (дыра «захватил локал — пришпилил навсегда» закрыта by construction).

Тип изменения

  • fix — исправление бага

Как проверено

  • python tests/run_tests.py — 276/276
  • ruff check . и mypy
  • локально через настоящий экстрактор (.NET 8, dotnet-install): сэмпл даёт ровно 3 контрольных warning'а (NotAnApp, LambdaApp, CuratedOnlyApp), оба позитива (App, DirectApp) молчат; полный дифф старого/нового экстрактора по всем существующим сэмплам — байт-в-байт идентичен (0 регрессий); точные CI-ассерты прогнаны против живого вывода

Связанные issue

Closes #228. Родитель: #221 (части (a) #227 и (c) #229 — отдельными PR). Найдено sweep'ом #201.

Чеклист

  • изменение покрыто тестом/селфтестом — AppScopedSourceSample.cs: 2 позитива (pattern-local и direct-receiver формы) + 3 негативных контроля на каждую грань гейта, CI-ассерты в обе стороны
  • README/docs обновлены — docs/notes/oracle-known-fps.md: секция «What DID ship next to it (issue Self-owned source (b): Application-derived subscriber with a curated app-scoped source (careful clsIsApp loosening) #228)» рядом с отвергнутым clsIsStatic, почему это не он
  • коммиты в conventional-commit стиле

🤖 Generated with Claude Code

https://claude.ai/code/session_01LsWw4Ay8KLTHFom1HvRu3U


Generated by Claude Code

…on subscriber (#228)

An App : Application subscribing to PaletteHelper().GetThemeManager() — an
app-scoped, process-lived instance reached through a resolver call instead of
a literal static member — was tiered "injected" and warned OWN001 (the
MaterialDesign MahMaterialDragablzMashUp App.xaml.cs FP from the issue #201
sweep). The subscription promotes nothing: the subscriber IS the process-lived
object and the source is bound to the app's own state.

The narrowing inverts every property that made the rejected clsIsStatic
broadening unsound (oracle-known-fps.md "Rejected approaches"):
- subscriber gate unchanged — byte-for-byte the existing clsIsApp;
- source loosens only to a CURATED resolver allowlist (exactly
  PaletteHelper.GetThemeManager for now; grown one confirmed sibling at a
  time, like the #223 weak-event list), resolved semantically through the
  receiver's local binding (var-initializer or is-pattern designation,
  casts/! peeled) — any unprovable step keeps today's honest warning;
- handler must be a METHOD GROUP of the App class itself — a lambda is
  rejected outright, closing the captures-a-local hole that sank clsIsStatic.

Pinned by AppScopedSourceSample.cs: two silent positives (is-pattern local +
direct-invocation receiver) and three flagged controls (non-App subscriber,
lambda handler, non-curated resolver), each edge of the gate, wired into the
wpf-extractor CI job. The rejected-approaches note gains a "what DID ship next
to it" section distinguishing this narrowing.

Verified locally with the real extractor (.NET 8): the sample yields exactly
the three control warnings; a full-sample-set diff of old vs new extractor
output is byte-identical (zero regression). Gates: run_tests 276/276, ruff,
mypy, yaml all green.

Closes #228

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsWw4Ay8KLTHFom1HvRu3U
{
var helper = new PaletteHelper();
if (helper.GetThemeManager() is { } themeManager)
themeManager.ThemeChanged += OnTheme; // OWN001 warning
{
var counter = new int[1];
if (new PaletteHelper().GetThemeManager() is { } themeManager)
themeManager.ThemeChanged += (s, e) => counter[0]++; // OWN001 warning
Comment thread frontend/roslyn/samples/AppScopedSourceSample.cs Fixed
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@PhysShell, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 22 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d695351d-385e-4cb3-b196-31d0549eaa58

📥 Commits

Reviewing files that changed from the base of the PR and between d089065 and 644a88f.

📒 Files selected for processing (4)
  • .github/workflows/ci.yml
  • docs/notes/oracle-known-fps.md
  • frontend/roslyn/OwnSharp.Extractor/Program.cs
  • frontend/roslyn/samples/AppScopedSourceSample.cs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/plans-tasks-review-u77dfs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f403bdb656

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/roslyn/OwnSharp.Extractor/Program.cs
Comment thread frontend/roslyn/OwnSharp.Extractor/Program.cs
… (Codex review)

Both Codex P2s verified real, both fixed:

- Handler target must be `this`: a method group qualified with ANOTHER
  instance of the same App-derived type (`_twin!.OnTheme`) has the right
  ContainingType but pins that other instance, not the process-lived
  singleton. IsOwnMethodGroupHandler now accepts only a bare identifier
  (implicit this) or an explicit `this.X` receiver.

- Stale resolver binding: `var tm = helper.GetThemeManager(); tm =
  injectedBus; tm.ThemeChanged += H` passed on the declaration-site
  initializer alone. IsNeverReassigned kills the proof on ANY assignment
  to the local or ref/out escape anywhere in the enclosing member —
  conservative (order-insensitive), worst case keeps today's warning.

Two new flagged controls in AppScopedSourceSample.cs (TwinApp, ReassignApp)
+ CI assertions. Verified with the real extractor: all five controls warn,
both positives silent; full-sample-set output still byte-identical to main.

Refs #228

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsWw4Ay8KLTHFom1HvRu3U
public void OnStartup()
{
if (new OtherHelper().GetOtherService() is { } service)
service.ThemeChanged += OnTheme; // OWN001 warning
public void OnStartup()
{
if (new PaletteHelper().GetThemeManager() is { } themeManager)
themeManager.ThemeChanged += _twin!.OnTheme; // OWN001 warning
{
var tm = new PaletteHelper().GetThemeManager()!;
tm = _injectedBus;
tm.ThemeChanged += OnTheme; // OWN001 warning
Same-tail collision as before: main's #225 empty-Dispose block (sample +
assertions) and this branch's #228 app-scoped block appended to the same
wpf-extractor job tail. Kept both, single OK line with both suffixes.
Program.cs auto-merged (additive helpers in different regions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsWw4Ay8KLTHFom1HvRu3U
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Self-owned source (b): Application-derived subscriber with a curated app-scoped source (careful clsIsApp loosening)

3 participants