PyQt6 sequential QApplication lifetime reproducer
=================================================

Purpose
-------

This package contains a small PyQt-only reproducer for QSplitterHandle Python
wrappers that stop being marked deleted after a QApplication is destroyed and
a new QApplication is constructed in the same process.

No application or product source code is included. The reproducer does not
call a Qt method on any object after its parent has been deleted and does not
attempt to force a crash.

Run
---

Use a fresh Python process for each command:

    py -3.12 minimal_repro.py single
    py -3.12 minimal_repro.py recreate

The script defaults to QT_QPA_PLATFORM=offscreen. For the Windows plugin:

    set QT_QPA_PLATFORM=windows
    py -3.12 minimal_repro.py single
    py -3.12 minimal_repro.py recreate

The JSON result is printed to stdout. A valid recreate boundary requires the
weak reference to the first QApplication wrapper to be dead and
QApplication.instance() to be None before the second application is created.

Observed result
---------------

On PyQt6 6.11.0 / PyQt6-Qt6 6.11.2 / PyQt6-sip 13.12.0, the single mode marks
all 16 handles deleted in both epochs. The recreate mode marks 16/16 handles
deleted under the first application and 0/16 under the second, while the
second epoch still reports 16/16 deleted splitters and 16/16 destroyed-slot
callbacks.

The offscreen comparison was repeated in 12 fresh processes per mode with the
same result in all 24 runs and empty stderr. One run per mode with the Windows
QPA plugin produced the same result. PyQt6 6.7.1 showed the same behavior.

Files intended for submission
-----------------------------

- minimal_repro.py: complete reproducer.
- single-pyqt6-6.11.0-final.json: offscreen single-app output.
- recreate-pyqt6-6.11.0-final.json: offscreen recreated-app output.
- single-pyqt6-6.11.0-windows-qpa-final.json: Windows QPA control.
- recreate-pyqt6-6.11.0-windows-qpa-final.json: Windows QPA reproduction.
- README.txt: this file.
- SHA256SUMS.txt: attachment hashes.

Safety notes
------------

- The destroyed callback is a class-defined zero-argument @pyqtSlot().
- It only changes a Python Boolean and receives no QObject argument.
- After DeferredDelete, the script reads only sip.isdeleted() and that Boolean.
- It contains no native pointer dereference, debugger control, or crash trigger.
- The output contains no username, hostname, absolute path, product name,
  patient data, credentials, keys, or environment-variable dump.

Environment used for the attached current-version outputs
---------------------------------------------------------

- Windows 11 10.0.26200, 64-bit
- CPython 3.12.14, 64-bit
- PyQt6 6.11.0
- PyQt6-Qt6 6.11.2
- Qt compile-time/runtime 6.11.0/6.11.2
- PyQt6-sip 13.12.0
