PyCForge 1.3.52 — Saving and startup file-read repair

Prepared from CC's current 1.3.51 source distribution.

FAULT AND CORRECTION

The 1.3.51 source reader compared an open handle's os.fstat result with
Path.stat for the pathname. CPython on Windows can report change time in
the former's st_ctime_ns and creation time in the latter. A file can therefore
fail the comparison without changing during the read. The reader is used
both when reopening saved files and by the pre-save conflict check.

Fault injection reproduced the two reported messages on unchanged data:
  Startup: The file changed while it was being read. Try again.
  Save: atomic workspace write failed: <path>
The save's hidden cause was the same read error. Disk bytes remained unchanged
and the edited document remained dirty in this reproduction.

The repaired reader compares handle metadata consistently: before reading,
after reading, and from a second handle opened through the current pathname.
The original handle stays open while the pathname is checked. Device, file
identity, size, modification time and change time remain checked. The payload
length must also match the observed size. This reads the payload once, adds
one bounded open/fstat/close operation, and keeps the 16 MiB limit and UTF-8,
NUL-byte and regular-file checks. It adds no dependencies or worker threads.

Atomic writes retain specific WorkspaceIOError messages. Other failures include
their exception type and reason, so an actual access or replacement problem
is no longer reported solely as a generic atomic-write failure.

The outside-project message in the second screenshot is a separate folder
constraint. The verified recovery is Save Python As into the existing working
folder, followed by Save Project. The recovery test preserves the outside
original, prior checkpoints and current editor text. The repair does not
silently relocate files or broaden the project's working folder.

Upstream reference for the Windows timestamp distinction:
https://github.com/python/cpython/issues/157671
This source describes the platform behavior; it is not evidence of the Python
version installed on CC's laptop.

VALIDATION

Linux, Python 3.12.14, PySide6 6.12.0, Qt offscreen. Windows metadata behavior
was simulated at the os.fstat boundary without changing os.name or pathlib.
Native Windows and macOS execution were not available. Laptop acceptance is
still required; these results are not a claim of native Windows certification.

237 focused regression tests and 19 subtests passed. They cover the 31 new
portability/workflow cases plus existing file I/O, disk conflicts, Python save
identity, Save All/exit, project archives/history, startup recovery, normal
startup and file-dialog checks. All passed in one process in 105.18 seconds.

23 Help/distribution-contract tests and 498 subtests passed separately.
Total in these two final runs: 260 tests and 517 subtests; zero failures/skips.
This is targeted validation of the affected paths, not a rerun of every
conversion test. Earlier standalone runs of the new tests overlap this total.

New coverage includes:
  - Windows-style mismatched pathname/handle ctime on stable files.
  - Genuine metadata changes during reads and pathname re-resolution.
  - Same-size replacement with matching timestamps and descriptor cleanup.
  - UTF-8 BOM, CRLF/CR, empty files, Unicode names and paths with spaces.
  - Synchronous/asynchronous open-save-reopen and real external-edit conflicts.
  - Reviewed overwrite, useful read/write failure reasons and preserved data.
  - Save Python, Save As, Save All and repeated saves of existing files.
  - Outside-project recovery, project saves and checkpoint retention.
  - Generated C saving and C-module ZIP export.
  - Complete application launch twice with persisted files and no false report.
  - Project save/restart across real process boundaries, with and without a
    bundle save after adding a module.

The source archive includes the tests and the focused logs under
evidence/windows_io_1_3_52. The final download report adds checks against the
built wheel and source archive, installed smoke results, sizes and hashes.

DOCUMENTATION AND SCOPE

The README differs from 1.3.51 only in the top version heading. Its four image
URLs, ordering, widths, prose and historical labels are preserved. The README
renderer check passed. AGENTS.md and PyCForge-README-Guidelines.txt are unchanged.
All 144 converter files are byte-identical to 1.3.51. Runtime dependencies and
entry points are unchanged. Help adds brief guidance for failed reads/saves
and the existing outside-project recovery workflow; its rendering was reviewed.

WINDOWS INSTALL AND RETEST

1. If v1.3.51 still has unsaved edits, copy that text to a safe file before
   closing it. Do not discard unsaved work to install the update.
2. In the folder containing the downloaded wheel, run:
   py -m pip install --upgrade .\pycforge-1.3.52-py3-none-any.whl
3. Launch with py -m pycforge.ide and confirm 1.3.52 in the application.
4. Confirm the saved Python files reopen. Edit an existing file, Save Python,
   edit and save it again, then restart and verify the exact saved text.
5. Test Save Python As and Save All Python. For the outside-project file,
   Save Python As into the folder named in the project message, then Save Project.
6. Transpile and save generated C; reopen the saved project and its history.

If a failure remains, retain the complete message or Startup report and the
output of py --version. No existing source files or settings need deletion.

CC alone publishes releases to PyPI from CC's own computer.
