Skip to content

feat: PoC oficially proven?#16

Merged
PhysShell merged 4 commits into
mainfrom
claude/zen-pasteur-76hfs1
Jun 16, 2026
Merged

feat: PoC oficially proven?#16
PhysShell merged 4 commits into
mainfrom
claude/zen-pasteur-76hfs1

Conversation

@PhysShell

@PhysShell PhysShell commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Introduced enhanced resource disposal detection that analyzes conditional execution paths to identify potential memory leaks in unmanaged resource handling.
    • Added legacy mode option via script flags to revert to previous flat-detection behavior.
  • Tests

    • Added comprehensive test fixtures and validation for various disposal patterns and leak scenarios.
  • Documentation

    • Updated proposal documentation with detailed milestone context and feature specification.

PhysShell and others added 4 commits June 16, 2026 16:22
…e), exempt dispose-optional types, default the wrappers to flow
…on leak

Pin the real GTM CatalogService.GetProductsFromCatalogWODocuments finding: a
local UnitOfWork (IDisposable) used only through member access to build a
returned DEFERRED IQueryable. The bare `uow` never escapes, so the flow
detector keeps it tracked and reports OWN001 (disposed on no path) — a leak a
naive `using` cannot fix (the deferred query would run after dispose).

- frontend/roslyn/samples/UnitOfWorkFlowSample.cs: self-contained distillation
  of the GTM method, plus the using-var/materialize fix that must stay silent.
- tests/fixtures/ownir/unitofwork_flow.facts.json + tests/test_ownir.py: the
  dotnet-free bridge+core pin (OWN001 on 'uow' at the C# line, tag disposable).
- .github/workflows/ci.yml: end-to-end extractor->core assertion on the sample.

https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
…ship-transfer sample

Two follow-ups on the GTM UnitOfWork pin:

- ownir bridge: word the flow-local OWN001 from whether the local is released
  anywhere in the body (ever_released). Released on no path -> "is never
  disposed"; released on some branch but leaked on another -> "may not be
  disposed on every path". Both stay the core's OWN001 — computed in the bridge
  from the flow body the extractor already emits (no schema change, no version
  bump).

- UnitOfWorkFlowSample: add the Option B (ownership-transfer) fixes as silent
  contrasts to the materialize fix — uow returned (uowOwned) and moved out as an
  argument (uowMoved) both escape, so the flow detector does not flag them.

- tests/CI: new flow_leak_on_else fixture pins the partial-path wording dotnet-
  free; test_ownir asserts both phrasings; the FlowLocals + UnitOfWork CI steps
  assert never-vs-every-path wording on real C# and that all three fixes stay
  silent.

https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Implements P-016 B0b/B2 path-sensitive IDisposable leak detection via a new --flow-locals flag in the Roslyn extractor that emits per-method acquire/use/release/if/return flow facts. The OwnIR Python bridge ingests these facts and emits OWN001/002/003 findings. Wrapper scripts gain a --legacy escape hatch; the pipeline is validated with new C# samples, JSON fixtures, Python tests, and CI assertions.

Changes

Flow-sensitive local IDisposable leak detection (P-016 B0b/B2)

Layer / File(s) Summary
C# extractor: --flow-locals flag and flow-body lowering
frontend/roslyn/OwnSharp.Extractor/Program.cs
Adds --flow-locals CLI flag, flow-lowering helpers that lower method bodies into acquire/use/release/if/return nodes, optional-dispose exemption, a D1 gate that skips syntactic detection when flow mode is on, a flowFunctions accumulator, and a functions field in the emitted JSON facts.
C# sample files: FlowLocalsSample and UnitOfWorkFlowSample
frontend/roslyn/samples/FlowLocalsSample.cs, frontend/roslyn/samples/UnitOfWorkFlowSample.cs
Adds FlowLocalsSample with eight disposal-scenario methods (branch-leak, clean, loop-skip, escape, timer-leak, etc.) and UnitOfWorkFlowSample with CatalogService unit-of-work patterns plus minimal standalone domain/persistence stubs.
OwnIR Python bridge: flow-body ingestion and diagnostics
ownlang/ownir.py
Imports new AST nodes; validates optional functions array in load(); extends to_module() with _released_vars() and _lower_flow() to convert flow ops into loc_<n> statements with ever_released metadata; adds flow-local branch in check_facts() emitting OWN001 with "never disposed" vs "not on every path" wording.
Wrapper scripts: --legacy flag and conditional --flow-locals
scripts/own-check.ps1, scripts/own-check.sh
Adds -Legacy/--legacy switch to both scripts; both now pass --flow-locals by default and omit it in legacy mode; help text updated accordingly.
JSON fixtures and Python unit tests
tests/fixtures/ownir/flow_leak_on_else.facts.json, tests/fixtures/ownir/unitofwork_flow.facts.json, tests/test_ownir.py
Adds two flow-body fixtures (else-branch leak, UnitOfWork projection leak) and two test blocks asserting exactly one OWN001 per fixture with correct wording variants, source location, and [resource: disposable] kind tag.
CI assertions and proposal status update
.github/workflows/ci.yml, docs/proposals/P-016-deep-fact-extraction.md
Adds two wpf-extractor CI steps that run the extractor with --flow-locals against the new samples and grep-assert OWN codes, wording, and absence of clean/exempt identifiers; updates P-016 proposal Status with milestone outcomes and default-behavior notes.

Sequence Diagram(s)

sequenceDiagram
  participant User as User / CI
  participant Script as own-check.sh / .ps1
  participant Extractor as OwnSharp.Extractor (--flow-locals)
  participant FactsJSON as facts.json (functions[])
  participant OwnIR as ownlang/ownir.py (to_module + check_facts)
  participant Output as OWN001/002/003 Findings

  User->>Script: run (no --legacy)
  Script->>Extractor: dotnet run -- paths --flow-locals -o facts.json
  Extractor->>Extractor: lower method bodies into acquire/use/release/if/return
  Extractor->>FactsJSON: emit { components, functions[] }
  Script->>OwnIR: load(facts.json)
  OwnIR->>OwnIR: _lower_flow() → loc_<n> stmts + ever_released
  OwnIR->>OwnIR: check_facts() → flow-local branch
  OwnIR->>Output: Finding(OWN001, "never disposed" or "not on every path")
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PhysShell/Own.NET#14: Modifies the same to_module/check_facts JSON→AST lowering path in ownlang/ownir.py that this PR extends with functions[*].body flow-op interpretation.
  • PhysShell/Own.NET#9: Established the local-disposable OWN001 detection core logic in ownlang/ownir.py and the extractor that this PR replaces with flow-sensitive modeling.
  • PhysShell/Own.NET#10: Introduced the scripts/own-check.sh orchestration plumbing (args parsing, Stage 1 extractor invocation) that this PR extends with --legacy and --flow-locals conditional argument building.

Poem

🐇 Hop, hop through each code path I go,
Checking each Dispose() — high and low.
If acquire has no release in sight,
OWN001 fires and reveals the blight!
With --flow-locals on, no leak can hide,
This bunny tracks every branch inside. 🌿

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title uses vague and unclear phrasing ('PoC oficially proven?') with a typo ('oficially') that does not convey meaningful information about the substantial changes made to the codebase. Revise the title to clearly describe the main change, such as 'feat: Add flow-sensitive local disposal analysis (P-016)' or 'feat: Implement --flow-locals extractor mode for path-sensitive leak detection'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/zen-pasteur-76hfs1

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/roslyn/OwnSharp.Extractor/Program.cs`:
- Around line 226-229: The UsingStatementSyntax case (line 226) does not emit a
release when the using statement wraps an existing local variable, and the
disposal method matching logic (lines 243-246) only recognizes Dispose and Close
invocations but misses DisposeAsync calls including awaited variants. Fix the
using statement handler to emit a release for the variable being disposed when
using(existingLocal) is encountered, and extend the disposal method matching at
lines 243-246 to also recognize DisposeAsync method invocations so that both
synchronous and asynchronous disposal paths are properly tracked by the flow
analysis.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f46555e8-d24c-4f23-ad63-9470fceaa3d6

📥 Commits

Reviewing files that changed from the base of the PR and between 8323c77 and e9fcc49.

📒 Files selected for processing (11)
  • .github/workflows/ci.yml
  • docs/proposals/P-016-deep-fact-extraction.md
  • frontend/roslyn/OwnSharp.Extractor/Program.cs
  • frontend/roslyn/samples/FlowLocalsSample.cs
  • frontend/roslyn/samples/UnitOfWorkFlowSample.cs
  • ownlang/ownir.py
  • scripts/own-check.ps1
  • scripts/own-check.sh
  • tests/fixtures/ownir/flow_leak_on_else.facts.json
  • tests/fixtures/ownir/unitofwork_flow.facts.json
  • tests/test_ownir.py

Comment on lines +226 to +229
case UsingStatementSyntax us:
// using(...) {body}: the using local is auto-disposed (untracked); still
// lower the body so a tracked plain local used inside is seen.
return us.Statement is null || LowerFlowStmt(us.Statement, tracked, nodes);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Flow lowering currently misses valid disposal paths and can misreport leaks.

Line 226 lowers using bodies but does not emit a release for using(existingLocal).
Lines 243-246 only match direct Dispose/Close invocations and miss DisposeAsync (including await x.DisposeAsync()). With --flow-locals enabled (and D1 suppressed), these become false OWN001/OWN009-style outcomes.

Proposed fix
@@
         case UsingStatementSyntax us:
             // using(...) {body}: the using local is auto-disposed (untracked); still
             // lower the body so a tracked plain local used inside is seen.
-            return us.Statement is null || LowerFlowStmt(us.Statement, tracked, nodes);
+            if (us.Statement is not null && !LowerFlowStmt(us.Statement, tracked, nodes))
+                return false;
+            // using(existingTrackedLocal) disposes that local at scope end.
+            if (us.Expression is IdentifierNameSyntax uid
+                && tracked.Contains(uid.Identifier.Text))
+                nodes.Add(new { op = "release", var = uid.Identifier.Text, line = LineOf(us) });
+            return true;
@@
 static void EmitFlowExpr(ExpressionSyntax expr, HashSet<string> tracked, List<object> nodes)
 {
     // x.Dispose()/x.Close() on a tracked local -> release.
-    if (expr is InvocationExpressionSyntax inv
+    var call = expr switch
+    {
+        InvocationExpressionSyntax i => i,
+        AwaitExpressionSyntax { Expression: InvocationExpressionSyntax i } => i,
+        _ => null,
+    };
+    if (call is InvocationExpressionSyntax inv
         && inv.Expression is MemberAccessExpressionSyntax ma
-        && ma.Name.Identifier.Text is "Dispose" or "Close"
+        && ma.Name.Identifier.Text is "Dispose" or "Close" or "DisposeAsync"
         && ma.Expression is IdentifierNameSyntax rid
         && tracked.Contains(rid.Identifier.Text))
     {
         nodes.Add(new { op = "release", var = rid.Identifier.Text, line = LineOf(inv) });
         return;
     }

Also applies to: 243-246

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/roslyn/OwnSharp.Extractor/Program.cs` around lines 226 - 229, The
UsingStatementSyntax case (line 226) does not emit a release when the using
statement wraps an existing local variable, and the disposal method matching
logic (lines 243-246) only recognizes Dispose and Close invocations but misses
DisposeAsync calls including awaited variants. Fix the using statement handler
to emit a release for the variable being disposed when using(existingLocal) is
encountered, and extend the disposal method matching at lines 243-246 to also
recognize DisposeAsync method invocations so that both synchronous and
asynchronous disposal paths are properly tracked by the flow analysis.

@PhysShell PhysShell merged commit dc47048 into main Jun 16, 2026
17 checks passed
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.

2 participants