PyCForge 1.3.30 — Explicit Runtime memory reclamation

Release scope
Adds pv_collect(PC *, size_t, const PV *, size_t *) for C callers at idle
boundaries between completed pv_call/pv_call_kw operations. Collection is
precise, non-moving, and iterative; unreachable cycles are reclaimable.
Context/module/function/class/default roots are retained automatically. The
caller must supply every PV it will still need; raw borrowed pointers require
an owning PV root. Existing callers retain arena lifetime until pv_destroy
unless they explicitly invoke collection.

The collector covers shared sequences, dictionaries/sets, objects, closures,
decorators/defaults, bound methods, class cells, super proxies, iterators/views,
module namespaces, and closed file handles. Released read buffers restore
retained-file capacity. Active calls/files, initialization, errors, terminal
failures, unknown heap references, inconsistent trace metadata, and collector
scratch-allocation failure refuse collection before any arena storage is freed.

Important boundaries
- No automatic collection inside Python loops or on allocation failure.
- Step/file-operation counters and handle serials are not reset by collection.
- Valid same-context PVs, caller-owned roots/count storage, and exclusive idle
  access are C API preconditions. Fabricated/invalid C objects are unsupported.
- Default root limit: 4096. Scratch index: one pointer per arena allocation,
  outside the arena, bounded by PYCF_RUNTIME_BYTES. No recursive graph walk.
- Internal PM/PL layouts changed. Regenerate C and rebuild callers together.
  Allocation metadata is included in the existing arena byte limit.
- Mutable defaults or other permanently rooted growing graphs remain live;
  a single long-running function call can still exhaust its resource budgets.

Measured verification
1. New collection suite: 11 native tests passed. A 2000-call workload with
   temporary containers and a cycle remained at its collected baseline under
   a 256 KiB arena. The same workload without collection reached MemoryError.
   Other witnesses cover alias identity, mutation after collection, discarded
   dictionary entries, cross-module closures/defaults, bound methods, captured
   class cells, super, iterators/views/sets, file-buffer accounting, recovered
   exceptions, a 12000-level live graph, busy/invalid-root refusal, live-file
   refusal, and injected collector allocation failure followed by successful
   retry. Refused collection preserves allocation bytes and existing errors.
2. Final ASan/UBSan collection suite: all 11 tests passed, including the
   decorator-wrapper closure case. Flags: -O1 -fsanitize=address,undefined
   -fno-omit-frame-pointer -fno-pie -no-pie. Both sanitizers halt on error;
   LeakSanitizer is disabled for host compatibility.
3. Existing arena failure-injection, Runtime provenance, and actual Qt
   diagnostics/ForgeLens navigation selection: 34 tests passed.
4. Initial file-workflow/collection run: 25 passed, 27 subtests passed; one new
   failure-injection assertion incorrectly expected bytes to be freed from a
   fully rooted graph. The fixture was corrected to allocate discarded data.
   All final collection and sanitizer tests pass with that correction.
5. HTML verifier passed: 25 Help pages in 5 categories; 61 Python examples
   (39 Runtime, 22 Typed native comparisons); 5 API examples; 4 C callers;
   2 module bundles; 3 unchanged README examples. The new C caller makes
   1000 calls, retains its first batch, collects discarded batches, and prints
   the documented result. New Help normal/narrow/example renders inspected.

Environment and limits of evidence
Linux x86_64, CPython 3.12, GCC 13.3, PySide6 with Qt offscreen. Native C
witnesses build with warning checks. These are selected regression tests, not
an assertion that the entire historical project suite was run. No native
Windows/MSVC/clang-cl/PCFC11 testing was performed.

Preservation
README SHA-256: 81408b884ec93411cd88f9734cc8cffc79bcd65751bcdfe092ea33e41addb638
UI Python files, theme/custom controls, scan and diagnostics implementations,
Typed backend, and save workflow unchanged from 1.3.29.
Dependencies unchanged: PySide6, numpy, numba, jedi, autopep8.
Runtime output/provenance validation and ForgeLens remain enabled.

Follow-on work
Automatic collection during executing functions needs live temporary roots.
Separate C-module exports, richer file profiles, Typed record boundaries,
and selected protocols/library adapters remain later conversion work.

Final package and additional regression evidence follows in the release report.

Additional regression selection
60 passed, 401 subtests passed: Runtime exception recovery/cleanup, HTML Help
contracts, scan freshness, and conversion diagnostics quick access.

Package/installed-wheel checks
Public wheel verifier passed: 867 members, 55 icons/495 assets, pure Python,
GPL-3.0-only, expected dependencies, no packaged private Ting compiler.
Isolated installed package imports as version 1.3.30. All 857 packaged app
files match source and wheel bytes; all 25 Help pages are present.
Installed selection: 35 passed, 9 deselected, including repeated-call memory
plateau/control, decorated cross-module closures, provenance integrity, and
actual Qt navigation. All 126 UI Python files match 1.3.29 byte-for-byte.

Source-archive verification and release digests are appended to the external
report after building the archive. Embedded evidence records the completed
wheel, native/sanitizer, UI, and documentation checks.
