Remove unnecessary .txt extensions from example and source files#1
Merged
Conversation
Rename the four example/source files to their real extensions so they match the names already used in the README and file headers: Program.cs.txt -> Program.cs buffer.own.txt -> buffer.own ok_pool.own.txt -> ok_pool.own bad_leak_branch.own.txt -> bad_leak_branch.own
The modules used relative imports (.parser, .cfg, ...) and run_tests.py imported the 'ownlang' package, but everything sat flat in the repo root, so 'python tests/run_tests.py' failed with ModuleNotFoundError. Move files into the layout already documented in the README: ownlang/ <- the 8 .py modules + new __init__.py tests/ <- run_tests.py examples/ <- ok_pool.own, bad_leak_branch.own examples/golden_arraypool <- buffer.own, Program.cs Now passing: 42/42 analysis, 11/11 codegen, golden PASS; and the documented CLI (python -m ownlang check/emit/cfg) works.
Ignore __pycache__/ and *.pyc (generated when running the test suite) plus the .NET bin/ and obj/ output from the golden_arraypool demo, so build artifacts stay out of the repo.
README's lead commands pointed at examples/ok_extern_calls.own and examples/bad_maybe_release.own, which never existed as files (they were only inline test cases). Add them as standalone .own files, verified with the checker here: ok_extern_calls.own -> checks clean (extern borrow/borrow_mut/consume) bad_maybe_release.own -> fires OWN009 + OWN001, cfg/emit behave as documented For demo.csproj (referenced but never shipped, and unverifiable without a .NET SDK in this sandbox) fix the README instead of adding an untested project file: show how to wrap Program.cs in a console project, and drop the demo.csproj entry from the structure tree.
Two blocking issues from code review, both reproduced before fixing: 1. Soundness hole: returning an owner while it is borrowed checked clean. 'return b' is an escape/consume of an owned resource, so under a live loan it must fail like move/consume do. The Return handler validated moved/released state but never the active loans on the returned owner. Now it fires OWN007 (mirrors move_while_borrowed/consume_while_borrowed). Added regression test return_while_borrowed; updated the OWN007 row in the README code table to list return alongside move/consume. 2. README quickstart was broken: 'cd ownlang' steps into the package dir, after which 'python -m ownlang' fails (No module named ownlang) and the examples/ paths no longer resolve. Replaced with a note to run from the repo root. Suite: 43/43 analysis (was 42 + new case), 11/11 codegen, golden PASS.
PhysShell
pushed a commit
that referenced
this pull request
Jun 14, 2026
PR #2 was authored with package-style relative imports (from . import ...) but committed as flat files, so it never actually ran. Re-home it onto the package layout established by PR #1: modules into ownlang/, buffers.py and report.py alongside, the test runner + its buffer_scratch_program.cs.txt fixture into tests/, example programs into examples/. Merge .gitignore and splice PR #1's README quickstart fix into PR #2's README. No logic changes.
PhysShell
pushed a commit
that referenced
this pull request
Jun 14, 2026
PR #2's rewritten Return handling set the owner to ESCAPED without checking for a live loan, so `borrow b as s { return b; }` returned a resource out from under an outstanding borrow with no diagnostic. PR #1 caught this on the original analysis; re-apply it, adapted to PR #2's buffer-aware Return block: returning an owner needs Own permission, so a live loan is OWN007 (as for move).
Owner
Author
|
Superseded by #3, which landed all three PRs as one linear integration on Generated by Claude Code |
PhysShell
pushed a commit
that referenced
this pull request
Jun 14, 2026
The core ownership checker already catches the main class of WPF lifetime leaks once a ViewModel is modelled as a scope (constructor = scope start, Dispose = scope end): a subscription/timer that is never disposed is OWN001, touched after dispose is OWN002. Slice #1 makes that usable without inventing WPF-specific codes: - resource declarations gain an optional, contextual 'kind "..."' attribute (no new reserved word). It is domain-neutral metadata threaded onto the owning Symbol and surfaced on diagnostics as a '[resource: <kind>]' suffix -- the seam a later WPF profile / Roslyn front-end keys off, with the core staying generic. - corpus/wpf/: two self-checking real-pattern cases (zombie ViewModel -> OWN001, handler-use-after-dispose -> OWN002) with before/after C#, case.own, expected codes and honesty notes; tests/test_wpf.py pins both the codes AND that the kind tag reaches rendered output. - docs/lifetimes.md captures the full module plan (lifetime regions, OWN-WPF catalogue, slice boundaries); README gains a business-application section. - bonus: assert_never now also guards lower_let's rhs dispatch; the strict gate caught a real 'kind' name collision in analysis.step during this work. Gate + suite green: analysis 123/123, codegen 23/23, fuzz, gallery 10/10, corpus 2/2, wpf 2/2.
PhysShell
pushed a commit
that referenced
this pull request
Jun 14, 2026
The genuinely-new analysis on top of the ownership core: it reasons about region
escape (the WPF 'zombie ViewModel promoted to App lifetime' theorem), not just
release within a scope.
Language:
- lifetime declarations with a strict order: 'lifetime Window < App;'
(transitive; cycles -> OWN036, undefined refs -> OWN030, redef -> OWN031).
- lifetime annotations on the object a function sets up and on its service
params: 'fn VM(bus: EventBus lifetime App) lifetime ViewModel'.
- a strong-capture statement: 'subscribe self to SOURCE;'
('self'/'to' contextual; only 'lifetime'/'subscribe' are reserved; '<' lexed).
Analysis (ownlang/lifetimes.py, check_lifetimes):
- region escape OWN014: if SOURCE strictly outlives self, the strong capture
promotes self to SOURCE's lifetime and it leaks. The *ordering* is what makes
it a leak -- a same/shorter-lived source is clean. Per fork B the code is
domain-neutral (OWN014 'escapes to a longer-lived region'), not WPF-branded.
- the mitigation (a disposable token released on close) is the slice-#1
acquire/release pattern, so both halves of the theorem now exist.
Wiring/tests:
- CLI 'check' runs check_lifetimes; the new Subscribe stmt is a no-op for the
loans/permissions flow and a schematic emit in codegen (both assert_never
dispatchers updated; lower_let rhs got assert_never too).
- corpus/wpf/viewmodel-escapes-to-app (before/after C# + notes); test_wpf made
tolerant of non-kinded cases. tests/test_lifetimes.py: 10 region cases.
- docs/lifetimes.md + README updated to mark slice #2 built.
Gate + suite green: mypy --strict, ruff, analysis 123/123, codegen 23/23, fuzz,
gallery 10/10, corpus 2/2, wpf 3/3, lifetimes 10/10.
PhysShell
pushed a commit
that referenced
this pull request
Jun 16, 2026
#1 --severity {error,warning} (default error): threaded through the core renderer (Finding.render/_github/_msbuild + render_finding), the ownir CLI (--severity, validated; only valid for ownir), own-check.sh, and the composite Action's new 'severity' input. A presentation choice — the finding is still the core's verdict — so a build can show leaks as advisory warnings instead of failing. Resolves P-013 open question #1. #2 scripts/own-check.ps1: a PowerShell twin of own-check.sh so Windows/VS users without bash get the same one-command pipeline (same flags/output). Docs: how-to §2B now uses --severity warning (drops the sed hack) and §4 points at own-check.ps1; P-013 scope/open-questions updated. CI: new step asserts --severity warning emits warning-level (not error) MSBuild lines. Verified locally: ownir 28/28, ruff + mypy --strict clean, severity honored in github/msbuild/human, bad/misapplied severity returns 2. https://claude.ai/code/session_01BE8MeHTtFcrTBjtMAQ7Yc6
PhysShell
added a commit
that referenced
this pull request
Jun 16, 2026
…egy-gs41zk level-2: add --severity flag + PowerShell own-check.ps1 #1 --severity {error,warning} (default error): threaded through the core renderer (Finding.render/_github/_msbuild + render_finding), the ownir CLI (--severity, validated; only valid for ownir), own-check.sh, and the composite Action's new 'severity' input. A presentation choice — the finding is still the core's verdict — so a build can show leaks as advisory warnings instead of failing. Resolves P-013 open question #1. #2 scripts/own-check.ps1: a PowerShell twin of own-check.sh so Windows/VS users without bash get the same one-command pipeline (same flags/output).
PhysShell
pushed a commit
that referenced
this pull request
Jun 18, 2026
… re-validation Leak #4 in the SystemEvents fixture: a FileStream that IS disposed, but the Dispose() sits inside the try after a may-throw call (WriteByte), so it's skipped on the exceptional path. This is CodeQL's cs/dispose-not-called-on-throw (cs/local-not-disposed also models it). Own.NET used to miss it — disposed somewhere looked balanced — until the exception-edge model (77b2edd) inserted a throw edge before each may-throw statement in a try. Re-running the oracle on this fixture should land #4 in "Agree" with CodeQL, joining #2/#3, with #1 (subscription) staying Own.NET-only. Bumps the oracle sentinel to trigger the push-run.
PhysShell
added a commit
that referenced
this pull request
Jun 21, 2026
… Q#1) (#66) DI001/DI002/DI003 keep their primary anchor at the registration site but now also name the CONSUMING CONSTRUCTOR — where the captive dependency is injected — so the developer is pointed at the code, not just the wiring. P-006 open question #1 ("anchor at the registration line, the consuming constructor, or both?") answered: both, with the path shown, like OWN014. - Extractor records each implementation's ctor location (the widest public ctor's declaration, or the class declaration for a C# 12 primary / implicit ctor) and the implementation type into ctor_file / ctor_line / ctor_type on the service fact. - Core appends ` [consumed by the '<impl>' constructor at <file>:<line>]` to the captive message (every surface) and carries it as a structured Finding.related triple, emitted as a SARIF relatedLocation — clickable + cross-file (registration in Startup.cs, ctor in EmailSender.cs). The owner named is the IMPLEMENTATION type, never the (ctor-less) service interface for an interface registration (Codex). Degrades cleanly (no tail, no related) when the location is unknown, so hand-authored facts / an older extractor still produce the prior form. ownir load() validates ctor_file/ctor_line/ctor_type. Pinned end-to-end by DiCaptiveSample.cs (explicit-ctor EmailSender:25, primary-ctor PrimaryCtorService:33, ConnectionWarmer:50, WeakCache:57) in the wpf-extractor CI job, the cross-file + interface-registration cases by tests, and the SARIF related location by tests/test_ownir.py. DI004's consumer is a resolution call site (not a ctor) — its anchor is the sibling follow-up. ruff + mypy --strict clean, ownir 113/113; DI counts unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
PhysShell
added a commit
that referenced
this pull request
Jun 22, 2026
fix(extractor): resolve-aware field disposability (mined ImageSharp FP #1/4)
PhysShell
pushed a commit
that referenced
this pull request
Jun 23, 2026
…t rebinds (Codex P2 + CodeRabbit) The first cut keyed the alias map by identifier STRING, scanned class-wide, and gated reassignment only on `=` expressions. Three holes, all flagged in review: - CodeRabbit (major) + Codex #2 — class-wide name keys conflate same-named locals across methods: an unrelated `c.Dispose()` in one method could credit a field aliased by a `c` in another (FN), and two aliases reusing a name overwrite each other. Now keyed by the LOCAL SYMBOL (model.GetDeclaredSymbol(decl)), and the dispose scan resolves the receiver symbol — so each alias is scope-exact. - Codex #1 — an alias rebound through a `ref`/`out` argument (`Swap(ref a)`) was not counted as reassigned, so a disposed-after-rebind alias wrongly credited the field (FN). The reassignment set now includes ref/out argument locals. - Iterating declarators by symbol (is ILocalSymbol) also drops non-local declarators from the map (locals-only, as intended). Direct field disposals are unchanged: a receiver that is not an alias local falls back to FieldName, exactly as before. Regression controls added: RefReboundAliasLeaks (`Swap(ref a)` then dispose -> _refRebound still leaks) and ScopedAliasNameLeak (an unrelated same-named `c` disposed in another method must not credit _scopedLeak -> it still leaks). CI asserts both, alongside the existing aliased-silent and never-disposed/`=`-rebound controls. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
PhysShell
pushed a commit
that referenced
this pull request
Jun 23, 2026
…ped); drop the SemaphoreSlim exemption Scopes this PR to the uncontentious fix and addresses the review. #1 `.Close()` releases a field — the field-disposable `disposed` scan credited a field only on Dispose()/DisposeAsync(), but the LOCAL detector (DisposesLocal and the flow detector) has always accepted Dispose/Close/DisposeAsync. That asymmetry flagged a field cleaned up by Close() as a leak. Mirror the local set on both the direct and null-conditional field-release checks. Mined: Npgsql ReplicationConnection releases its NpgsqlConnection field via `await _npgsqlConnection.Close(async: true)`. Receiver-scoped (Codex/CodeRabbit): credit only THIS instance's field or a validated alias via ThisFieldName, so `other._conn.Close()` on ANOTHER instance of the SAME class cannot mark this object's `_conn` released. (A field-symbol ContainingType check would NOT catch this — same class, same ContainingType — so the receiver is keyed syntactically; this also tightens the pre-existing Dispose path.) Dropped: the SemaphoreSlim dispose-optional change. Putting SemaphoreSlim in the shared IsDisposeOptional also affected the flow-locals detector and tripped the deliberate `semLeak` control (a prior ShareX fix explicitly decided SemaphoreSlim stays tracked for method-bounded locals, since reading AvailableWaitHandle allocates a handle Dispose must release — Codex flagged the same). A sound, field-scoped + AvailableWaitHandle-gated version is a separate decision, deferred. Regression sample CloseReleaseSample.cs: ReleasesViaClose._closedConn / _closedConnQ (direct + null-conditional Close) silent; controls still warn — LeaksUnclosed._leakedConn (never closed) and ClosesOtherInstanceField._xconn (closed only on ANOTHER instance). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
PhysShell
pushed a commit
that referenced
this pull request
Jun 27, 2026
…line Live NLog oracle re-run with the four WaitForDispose timer entries disabled confirms the CallReleasesReceiver fix cleared them at the source: leak-class own-only total 8 -> 4, and the four timers (AsyncTaskTarget _taskTimeoutTimer/ _lazyWriterTimer, AsyncTargetWrapper _lazyWriterTimer, BufferingTargetWrapper _flushTimer) appear in neither own-only nor the baselined section. The remaining NLog own-only is just the three benign-but-real undisposed fields (XmlParser _xmlSource, FileTarget _reusable*Stream), with only TimeoutContinuation _timeoutTimer baselined (its Interlocked.Exchange ref-alias is out of scope). - Delete the four now-redundant baseline entries (baseline: 13 -> 9 rules). - Document the fix landed in oracle-known-fps.md (root-cause #1 mostly-fixed). - Restore the dev scaffolding: oracle-target.txt back to the systemevents-console fixture, remove the branch from the oracle.yml push filter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019846YSZ35c7CdkWQ1qX5gm
PhysShell
pushed a commit
that referenced
this pull request
Jun 28, 2026
…+ no-op-dispose BCL wrappers Two precision fixes for the remaining open root-causes in oracle-known-fps.md. Tail 1 (root-cause #1, custom dispose-sink): release a tracked local used as the resource of a `using (existingLocal) { ... }` statement. The --flow-locals lowering already handled the `using (var x = ...)` declaration form and the MemoryPool owner statement form, but not the expression form over an already-acquired local (`var timer = new ...; using (timer) { ... }`) — it left the local looking live at method exit, a spurious OWN001. Now threads a scope-exit release onto the body's normal completion and its return/throw exits (no acquire — the local was acquired at its `new`). Clears protobuf-net's assorted/ Silverlight Page.xaml.cs `timer` (baseline entry marked fix-landed, pending a live-oracle re-run to confirm-and-delete). Tail 2 (root-cause #2, no-op Dispose): extend the StringWriter/StringReader field exemption to BCL pass-through wrappers. A StreamReader/StreamWriter/ BinaryReader/BinaryWriter field whose every construction wraps an in-memory backing (MemoryStream/StringWriter/StringReader) cascades disposal only to managed memory, so it is dispose-optional. Closed allowlist of those four adapters (GZipStream/CryptoStream own native/extra resource — stay flagged); a path building `new StreamReader(path)` (a real handle) keeps the field flagged. Does NOT clear Newtonsoft's _textWriter (a third-party JsonTextWriter wrapper whose Dispose we can't prove is pass-through without body analysis — the soundness wall); that stays baselined, with the reasoning recorded so it isn't unsoundly suppressed. Corpus fixtures: local-dispose-via-using-statement, field-noop-dispose-wrapper (each: before.cs caught / after.cs clean, proving the exemption stays narrow). Docs: new no-op-dispose-wrapper.md; oracle-known-fps.md root-causes #1/#2 and baseline annotations updated. Selftests: oracle 31/31, corpus 29/29, validate_contrib 16/16, ruff clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019846YSZ35c7CdkWQ1qX5gm
10 tasks
PhysShell
pushed a commit
that referenced
this pull request
Jun 28, 2026
…dev config Ran the cross-tool oracle on protobuf-net (via the push-trigger dev fallback; the token can't workflow_dispatch) to confirm whether the using-statement local-release fix clears the assorted/ Silverlight Page.xaml.cs `timer` FP. Result: NOT cleared — the finding is still emitted and still baselined. Re-triage of the real source shows the prior baseline reason was a misdiagnosis read from COMMENTED-OUT code: the only `using (timer)` block is commented out, and `timer` is a Stopwatch (RunTest) / a DispatcherTimer local (btnRunTest_Click) — neither is IDisposable. So the using-fix does not apply; the entry stays baselined as a non-product sample FP, and the real open question is why a non-IDisposable timer-shaped local is flagged at all (a precision follow-up needing a local repro). - Corrected the baseline entry reason and oracle-known-fps.md (root-cause #1 + the per-finding row). - Reverted the dev-only oracle config (oracle.yml push branch + oracle-target.txt back to the systemevents-console fixture). Selftests: oracle 31/31, corpus 30/30. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019846YSZ35c7CdkWQ1qX5gm
PhysShell
pushed a commit
that referenced
this pull request
Jun 28, 2026
Cross-reference the tracked precision follow-up (non-IDisposable timer local flagged OWN001) from the baseline entry and oracle-known-fps.md root-cause #1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019846YSZ35c7CdkWQ1qX5gm
PhysShell
pushed a commit
that referenced
this pull request
Jun 30, 2026
…pwatch), not an FP Cracked the mechanism behind issue #161 from the core side: the finding renders via the flow-locals path (ownir.py rkind=="flow-local"), whose extractor candidate gate REQUIRES ImplementsIDisposable. The raw protobuf source shows the file has no `using System.Diagnostics;` — it has `using Nuxleus.Performance;` and uses `Stopwatch.UnitPrecision` / `UnitPrecision.NANOSECONDS` / `timer.Scope = () => …`. So `Stopwatch` is `Nuxleus.Performance.Stopwatch`, a custom IDisposable scope-timer (you can only `using` an IDisposable), NOT System.Diagnostics.Stopwatch. `Stopwatch timer = new Stopwatch()` is genuinely never disposed — the disposing `using (timer) { … }` block is commented out — so the OWN001 is a REAL leak the extractor correctly flagged. It stays baselined as NON-PRODUCT sample (assorted/ Silverlight demo), like the NetTranscoder `sync` entry — reclassified from FP to true-but-benign-sample. The earlier "missed using" and "non-IDisposable Stopwatch FP" readings were both wrong; issue #161 is closed as invalid. Corrected the baseline entry reason, oracle-known-fps.md root-cause #1, the per-finding verdict row, and the disposition summary (Baselined FP 6→5, true-but-benign sample 2→3). oracle selftest 31/31. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019846YSZ35c7CdkWQ1qX5gm
PhysShell
pushed a commit
that referenced
this pull request
Jul 3, 2026
Both reviewers converged; all corrections are factual/design refinements (no forks): - Crate DAG: own-codegen is a SIBLING of own-diagnostics (both consume own-cfg/own-analysis), not chained through it. Codegen is verdict-independent (AST/CFG-driven, matching Python codegen.generate), so the old own-diagnostics -> own-codegen edge would have forced diagnostics to re-export solver internals. Added a fitness function locking codegen !-> diagnostics (and !-> analysis for now). (Codex P2, CodeRabbit #1) - Oracle: do NOT reuse scripts/oracle_compare.py as the parity oracle — it is cross-tool fuzzy (leak-only, +-N line tolerance, coarse severity) and would mask off-by-one/label/subject/exit-status divergences. Spec a new exact harness over status+stdout+stderr+SARIF/JSON, with an exit/crash gate first, exact set-equality incl. evidence label text, and intra-tie ordering. (Codex P1, CodeRabbit #4) - CFG seam does not exist yet: python cfg prints human text, not JSON. Add+freeze a canonical cfg --format json before the ratchet uses that seam; added as migration step 0. (Codex P2) - State: arena+CoW likely wins this procedural workload; bench largest real function, wall-clock + RSS. Prior art: clippy lint-pass registry, prusti-viper encoding boundary. Repo-layout revisit trigger. (CodeRabbit #2/#3/#5/#6)
8 tasks
PhysShell
pushed a commit
that referenced
this pull request
Jul 4, 2026
Closes 3 of 4 open questions with sourced findings; #1 and #3 retain a 5-minute empirical residual (run on real Linux), not a design blocker. - gVisor x toolchain: LIKELY OK (277/351 syscalls; runtimes regression- tested). Residual: run gate.toml under runsc, watch for "Bad system call". Known gaps flagged (io_uring off, iptables partial, no KVM-in-sandbox). - Kata 2026: CLOSED — ~100-300ms boot, ~130-200MB/pod, needs KVM, no native egress, guest-kernel patch-currency required. Its edge is containerd/K8s drop-in; with no K8s here it adds overhead without advantage over direct Firecracker (L1) or Sandlock (L2). Fills the deep-research Kata gap. - QUIC/HTTP3 egress: CLOSED default — blanket UDP block suffices; CLI agent tools are TCP-first and fall back cleanly. Don't build MITM-CA/L7 proxy until a hard QUIC dependency appears. Residual: confirm nothing hangs. - TCO self-host vs managed: CLOSED — both cheap in $ at N=1; the fork is purpose/trust/offline, not cost. For a for-the-soul self-use project, build self-host; the L2 MVP is days not weeks. E2B is benchmark, not target. Also fixes the §6 trigger-table (an earlier note blockquote split the table mid-rows). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LMA4JwvgPBCZuEbAiG5LJL
This was referenced Jul 12, 2026
PhysShell
added a commit
that referenced
this pull request
Jul 14, 2026
… object "Who holds this object" is ill-posed for an object reachable from many roots: there are as many answers as there are paths, and the shortest is an arbitrary pick. Reporting one of them was the tool's real weakness — the first version happily pointed at a prototype held by the stack while the leak was eight hops away through a delegate's invocation list. `roots` now samples the retained instances (--sample, default 200), computes every one's shortest path in a SINGLE BFS (breadth-first from the whole root set gives each node its shortest path for free), and reports the paths as a RANKED HISTOGRAM. On the live target this finds the leak on its own: #1 25/50 (50.0%) — via [static-event], 7 hops System.Object[] BrokerDataClasses.Property.KernelProperty BrokerDataClasses.Property.GBProperty (.fGBProperty) System.ComponentModel.PropertyChangedEventHandler (.PropertyChanged) System.Object[] (._invocationList) System.ComponentModel.PropertyChangedEventHandler BrokerDataClasses.GTD (._target) #4 1/50 (2.0%) — via [stack] — noise, and labelled as such Parent pointers are stored as addresses, not labels; type and field names are resolved only for the sampled paths. Carrying a label per node would cost hundreds of MB on a 4M-object heap. The run also exposes the remaining limit, and the README now says so plainly: the histogram partitions by SHORTEST path, so an object held by two references at once is attributed to the nearer one. Here 50% of the GTDs land under the static event and 44% under a static List<Object> — most likely many are held by BOTH, and detaching the event alone would not free them. "Which single reference, if cut, frees this object" is a different, well-posed question with a standard answer this tool does not implement: a dominator tree with retained sizes (Lengauer-Tarjan / Cooper-Harvey-Kennedy — what Eclipse MAT and dotMemory are built on). That is the honest next step. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PjQnE1FDucd6vBVQbFswiE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rename the four example/source files to their real extensions so they
match the names already used in the README and file headers:
Program.cs.txt -> Program.cs
buffer.own.txt -> buffer.own
ok_pool.own.txt -> ok_pool.own
bad_leak_branch.own.txt -> bad_leak_branch.own