diff --git a/PORT_STATUS.md b/PORT_STATUS.md index 2af86b5..c81f702 100644 --- a/PORT_STATUS.md +++ b/PORT_STATUS.md @@ -1,4 +1,3044 @@ -## Latest revision (generated compatibility patch refreshed; VC6 frontier in object.c) +## Publication preparation: complete patch and regression checks + +Date: 2026-10-26 UTC. User explicitly authorized commit and push to the existing Gitea `main`. Fetched `gitea/main`; pre-publication divergence was `0 0`. Reviewed the root publication unit: ignored `cpython/` source is represented by the tracked compatibility patch; ignored `MSVC600/` and build output remain local. The unrelated empty untracked `tp_mro` file is excluded. + +Publication checks discovered the existing untracked `cpython/Include/internal/pycore_win9x_loadlibrary.h`, already referenced by patched source but absent from the previous generated patch. Regenerated the complete patch using an isolated temporary index containing all tracked nested modifications plus that reviewed new header; no changes to the real nested index. Verified byte equality with that isolated staged diff, checked and applied it against an isolated pristine upstream HEAD index, and verified the restored header bytes exactly. This supersedes the earlier tracked-only patch equality check; `git diff` alone cannot capture an untracked new header. + +All 159 changed/new standalone Python regression scripts passed with their required source/header arguments (evidence: `build/manual-20261026-type-add-method/publication-tests-correct-argv.json`). An initial argument-free batch was invalid for scripts requiring positional paths and was rerun correctly; its invocation errors are not source regressions. Full shell harness remains blocked by the lifecycle scan guard as documented below. Final staging checks also report pre-existing trailing spaces inside three newly tracked source-order test fixtures (`find-name-in-mro`, `get-subclasses-index`, `type-new-get-bases-winner`), in addition to the generated patch's required single-space context markers; left fixture content unchanged and all 159 tests pass. Latest compile probe remains 108/109, blocked in `typeobject.c(6231)`; no linked interpreter or target-runtime claim. + +--- + +## Manual continuation: descriptor registration and hash override C89 locals + +Date: 2026-10-26 UTC. Workspace `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; CPython `v3.11.16`, HEAD `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Actual MSVC6 compiler exercised through Wine using the existing project probe. Preserved the existing dirty/untracked work; no reset, clean, stash, commit or push. Direct narrowly scoped edits, no parallel implementation lane. + +Evidence directory: `build/manual-20261026-type-add-method/`. Baseline: 88 standalone typeobject regression scripts passed; forced-fresh probe exit 2, `total=109 compiled=108 cached=0 skipped=0`, first errors at `typeobject.c(5789)` (`PyObject`/`name`) and `(5801)` (`err`). `before-probe.log` preserves diagnostics; `typeobject.before.c` and `before-hashes.json` preserve pre-edit source evidence. + +Three strict RED/GREEN slices, each followed by a real forced-fresh compiler probe: + +1. `type_add_method()`: move only `name` and `err` declarations to the opening block. Existing branch assignments, creation calls and reference cleanup remain in place. New `scripts/vc6-typeobject-add-method-locals-c89.test.py` failed before the edit (exit 1, expected opening-declarations assertion), then passed (exit 0); 89 standalone typeobject tests passed. Compiler cleared those errors and advanced to line 5845 (`dict`); probe exit 2. +2. `type_add_members()` and `type_add_getset()`: declare `dict` at entry but retain `dict = type->tp_dict` after the same NULL guard. New `scripts/vc6-typeobject-add-descriptors-dict-c89.test.py` failed for both declarations before editing (exit 1), then passed both functions (exit 0). Compiler cleared both errors and advanced to line 5952 (`r`); probe exit 2. +3. `overrides_hash()`: declare `int r;` at entry; retain the first dictionary lookup after `assert(dict != NULL)` and retain the conditional second lookup and result/error propagation. New `scripts/vc6-typeobject-overrides-hash-r-c89.test.py` failed before editing (exit 1), then passed (exit 0). Final forced-fresh probe exit 2, `total=109 compiled=108 cached=0 skipped=0`; first errors now `typeobject.c(6231)` C2275 `PyObject` and C2065 `bases`. Later `dict`/`doc` errors remain untouched. See `final-probe.log`. + +Exact probe invocation for each log: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh`. Logs: `before-probe.log`, `after-probe.log`, `descriptors-after-probe.log`, `final-probe.log`. + +Final standalone coverage: 91 `scripts/vc6-typeobject-*.test.py` scripts passed, zero failed (`final-tests.json`). These are source-structure/order regressions, not interpreter runtime tests. Full `bash scripts/vc6-probe-pythoncore-frontier.test.sh` was attempted but blocked before execution by the Hermes lifecycle guard: scan budget exhausted at remote-read depth 1. It is NOT reported as passing; its embedded tests were not extracted or reconstructed. Nested `git diff --check` and the outer check excluding the generated patch passed. The final unfiltered outer check exits 2 on single-space unified-diff context lines inside the regenerated `.patch` file; nested source whitespace remains clean. Kept these required context markers intact rather than corrupting the byte-equal patch. The exact session delta is in `source.diff`; only `cpython/Objects/typeobject.c` changed among all pre-existing files inventoried under scripts/, cpython/Objects/ and compat/ before intentional compatibility-patch regeneration. + +Regenerated `compat/msvc600/cpython-3.11.16-vc6-headers.patch` from the complete nested `git diff`; verified byte equality against a fresh diff. The complete patch passes `git apply --cached --check` against an isolated pristine HEAD index (exit 0), without touching the user's real Git index or working tree. Prior patch backed up in the evidence directory. Files changed by this session: the C source, three new standalone regressions, the compatibility patch and this status entry. + +Compile-only progress: still no linked pythoncore/python.exe, Wine interpreter execution or actual Windows 98 SE validation. Next narrow slice: fresh-confirm and isolate the `bases` declaration in the function at `typeobject.c(6231)`. No completion percentage or runtime compatibility claimed. + +--- + +## `object_new()` `obj` C89 declaration slice (frontier advances) + +Date: 2026-10-26 UTC. Requested `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before editing. Nested CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved all pre-existing outer/nested dirty and untracked paths; no reset, clean, stash, discard, commit, push, or publication. + +Forced-fresh pre-change probe: `mkdir -p build/cron-20261026-recheck; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-recheck/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The first stable errors were `typeobject.c(4673)` C2275 `PyObject` / C2065 `obj` for a declaration after statements. Full capture: `build/cron-20261026-recheck/probe.log`. + +One authenticated Codex CLI 0.153.4 coding lane followed strict TDD. New `scripts/vc6-typeobject-object-new-obj-c89.test.py` failed before production edit (RED exit 1: `object_new: obj must be in the opening declaration block (C89)`). Minimal source change in `cpython/Objects/typeobject.c`: declare `PyObject *obj;` in `object_new()`'s opening block and replace the original initialized declaration with `obj = type->tp_alloc(type, 0);` at the same execution point. Focused regression passed (exit 0); all 87 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Exact-delta/preservation verification passed; all 286 other pre-existing dirty/untracked files remained unchanged. Nested `git diff --check -- Objects/typeobject.c` passed (exit 0); the new-test no-index whitespace check emitted no diagnostics (exit 1 because files differ). + +The first delegated probe attempt exited 1 before compilation because Wine used a read-only runtime lock path. Parent retried with a writable runtime: `mkdir -p /home/ubuntu/r build/cron-20261026-after-object-new-obj; chmod 700 /home/ubuntu/r; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-after-object-new-obj/probe.log 2>&1` — compiler probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The former line-4673 errors cleared; first remaining diagnostics advance to `typeobject.c(4897)` C2275 `PyTypeObject` / C2065 `newto`, a separate declaration family left untouched. Capture: `build/cron-20261026-after-object-new-obj/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-object-new-obj-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. No completed port is claimed. Next frontier: fresh-confirm and isolate only the `typeobject.c(4897)` `newto` declaration family. + +--- + +## `PyType_Type` designated-initializer C89 slice (frontier advances) + +Date: 2026-10-26 UTC. Requested `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the CPython 3.11.16/MSVC6 reference before editing. CPython baseline: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved extensive pre-existing outer and nested dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. + +Forced-fresh pre-change command: `mkdir -p /home/ubuntu/r build/cron-20261026-fresh-designator; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-fresh-designator/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; first stable diagnostics were `typeobject.c(4474)` and `(4520)`, C2059 on `.nb_or` and `.tp_vectorcall`. `_blake2/blake2s_impl.c` compiled. Capture: `build/cron-20261026-fresh-designator/probe.log`. + +One focused authenticated Codex CLI 0.153.4 coding lane used strict TDD. Added `scripts/vc6-typeobject-static-initializers-c89.test.py`; against the original `typeobject.c` snapshot the corrected fixture fails as expected with `type_as_number: designated initializer is not VC6/C89 compatible` (exit 1). Minimal production change in `cpython/Objects/typeobject.c` converts the exact two unsupported designated initializers to positional structure initializers while checking all 36 `PyNumberMethods` and 48 `_typeobject` field mappings against the actual header layout. Focused fixture passes (exit 0); all 86 `scripts/vc6-typeobject-*.test.py` tests pass (exit 0); nested and outer scoped `git diff --check` pass (exit 0). Preservation verification: 4,901 pre-existing files byte-identical, only intended C source changed among prior files, Git indexes unchanged, and no status edits by the coding lane. The status log's attempted probe initially could not create Wine server locks with a repository-local runtime (exit 1); parent reran with `/home/ubuntu/r`. + +Forced-fresh post-change command: `mkdir -p build/cron-20261026-after-designator; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-after-designator/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`. Former line-4474/4520 designated-initializer diagnostics cleared; first stable diagnostics now advance to `typeobject.c(4673)` C2275 `PyObject` / C2065 `obj`, a separate declaration family left untouched. Capture: `build/cron-20261026-after-designator/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-static-initializers-c89.test.py`, and this status record. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution. No completed port is claimed. + +--- + +## `_PyType_GetSubclasses()` `obj` C89 declaration slice (frontier advances) + +Date: 2026-10-26 UTC. Requested `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the profile's `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before editing. CPython baseline is tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved the extensive pre-existing outer and nested dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. + +Forced-fresh pre-change command: `mkdir -p /home/ubuntu/r build/cron-20261026-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-current-reprobe/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors in `cpython/Objects/typeobject.c`: line 4228 C2143 before `type`, line 4229 C2065 `obj`. Capture: `build/cron-20261026-current-reprobe/probe.log`. + +One focused authenticated Codex CLI 0.153.4 lane was used, no commits. Strict TDD: new `scripts/vc6-typeobject-get-subclasses-obj-c89.test.py` failed before production edit (reported exit 1: `obj` absent from opening C89 declarations); source snapshot verified unchanged during RED. Minimal production edit in `cpython/Objects/typeobject.c` hoists `PyObject *obj;` into `_PyType_GetSubclasses()`'s entry locals and changes only its point-of-use declaration to `obj = PyWeakref_GET_OBJECT(ref);`, retaining evaluation timing and control flow. The lane updated only the directly coupled `get-subclasses` structural fixtures for the added local and assignment. Focused four `scripts/vc6-typeobject-get-subclasses-*.test.py` tests pass (exit 0); all 85 `scripts/vc6-typeobject-*.test.py` regressions pass (exit 0). Nested `git diff --check -- Objects/typeobject.c` and outer `git diff --check -- scripts/vc6-typeobject-get-subclasses-*.test.py` pass (exit 0). No changes to unrelated pre-existing paths were reported by the lane's snapshot check. + +Forced-fresh post-change command: `mkdir -p /home/ubuntu/r build/cron-20261026-after-obj; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-after-obj/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`. The line-4228/4229 errors cleared. First remaining compiler diagnostics are now `typeobject.c(4474)` C2059 on designated initializer `.nb_or`, followed by another at line 4520; the next frontier is a distinct VC6 language-feature blocker, left untouched. Capture: `build/cron-20261026-after-obj/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-subclasses-obj-c89.test.py`, the directly coupled `get-subclasses` index/ref/subclasses regression fixtures, and this status record. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter run, or Windows 98 SE execution. No completed port is claimed. + +--- + +## Diagnostics-only: requested BLAKE2 frontier stale; current typeobject blocker + +Date: 2026-10-26 UTC. Requested path `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the CPython 3.11.16/MSVC6 reference before action. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved extensive pre-existing outer/nested work; no reset, clean, stash, discard, commit, push, or publication. + +The requested `_blake2/blake2s_impl.c` sequence is no longer current. Its recorded condition was rechecked with forced-fresh command `mkdir -p /home/ubuntu/r build/cron-20261026-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiles. The first errors now remain in `cpython/Objects/typeobject.c` at line 4228 (C2143 before `type`) and 4229 (C2065 `obj`); prior reported blockers at lines 4214–4227 are cleared. Full capture: `build/cron-20261026-current-reprobe/probe.log`. + +No implementation was attempted because the current frontier is in a different source file/function than the requested slice and the checked-in local `MSVC600/VC98/bin/VCVARS32.BAT` path is absent (check exit 1). No test or production files were changed by this run. This is diagnostics-only, not a TDD implementation cycle. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: obtain the external MSVC600 launcher and then strictly test-first isolate the actual `typeobject.c` line-4228/4229 declaration family, after checking that recorded source state again. No completed port is claimed. + +--- + +## `_PyType_GetSubclasses()` loop index `i` C89 declaration slice (frontier advances) + +Date: 2026-10-25 20:39 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved existing work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: v3.11.16, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyType_GetSubclasses()` declaration frontier was re-probed forced-fresh and remained valid but advanced: `_blake2/blake2s_impl.c` compiled; first stable errors moved to the late `Py_ssize_t i = 0;` at `typeobject.c(4223)`. Exact pre-change command: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-blake2-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Compiler diagnostics: C2275 `Py_ssize_t`, C2146 before `i`, C2065 undeclared `i`; subsequent `ref`/`obj` declarations were separate later blockers. The prior `_blake2` frontier is stale; `typeobject.c` is current. Capture: `build/cron-current-blake2-reprobe/probe.log`. + +Coding delegation: Hermes delegation provider could not start (Anthropic credentials unavailable); authenticated Codex CLI 0.153.4 was used as one focused coding lane. Strict TDD RED observed before production edit: new `scripts/vc6-typeobject-get-subclasses-index-c89.test.py` failed exit 1 with `_PyType_GetSubclasses: i must be declared in the opening declaration block (C89)`; source equality against pre-RED snapshot was confirmed. Minimal production change in `cpython/Objects/typeobject.c`: declare `Py_ssize_t i;` with opening locals and replace late initialized declaration with `i = 0;` at the original point. The directly coupled `scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py` expectation was minimally widened to allow the new opening local. Leave later `ref`/`obj` blockers untouched. Focused test and coupled test passed (exit 0); all 83 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Parent independently reran these and both nested/outer scoped `git diff --check`; all exit 0. + +Forced-fresh post-change command: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-blake2-after-i/probe.log 2>&1` — exit 2; summary still `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `i` diagnostics cleared. First stable remaining diagnostics advance to `typeobject.c(4225)` C2275 `PyObject` / C2065 `ref`, then line 4228 C2143 and 4229 C2065 `obj`; `ref` is the next distinct declaration family and remains untouched. Capture: `build/cron-current-blake2-after-i/probe.log`. + +Files changed by the slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-subclasses-index-c89.test.py`, narrowly updated `scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py`, and this `PORT_STATUS.md` entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: force-fresh confirm and isolate only `_PyType_GetSubclasses()`'s `ref` C89 declaration. No completed port is claimed. + +--- + +## `_PyType_GetSubclasses()` `subclasses` C89 declaration slice (frontier advances) + +Date: 2026-10-25 UTC. User-requested checkout `/home/ubuntu/projects/python-win9x` is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Before changes, read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved existing dirty/untracked changes; no reset, clean, stash, discard, commit, push, or publication. + +Forced-fresh pre-change command: `mkdir -p /home/ubuntu/r build/cron-20261026-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics at `cpython/Objects/typeobject.c(4214)`: C2275 `PyObject` and C2065 `subclasses`; later errors in this function include separate declarations. Capture: `build/cron-20261026-current-reprobe/probe.log`. + +Hermes coding delegation attempted once but failed before launch because Anthropic credentials are unavailable. Authenticated Codex CLI 0.153.4 was used as one focused coding lane with strict TDD. New `scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py` failed before production edit (RED exit 1: `_PyType_GetSubclasses: subclasses must be declared at function entry (C89)`). The minimal production edit in `cpython/Objects/typeobject.c` declares `PyObject *subclasses;` at function entry and replaces only the late initialized declaration with `subclasses = self->tp_subclasses;` after the existing allocation-failure guard, preserving read timing. Focused test passed; all 82 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Preservation verification confirmed 282 pre-existing dirty/untracked files unchanged; nested and outer scoped `git diff --check` passed (exit 0). + +Forced-fresh post-change command: `mkdir -p /home/ubuntu/r build/cron-20261026-after-subclasses; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-after-subclasses/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The former `subclasses` diagnostics cleared; first remaining blocker advances within `_PyType_GetSubclasses()` to `Py_ssize_t i` at line 4223 (C2275/C2146/C2065), followed by the separate `ref` declaration at 4224 and `obj` declaration at 4227; these remain untouched. Full capture: `build/cron-20261026-after-subclasses/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution. Next frontier: force-fresh confirm and isolate only `_PyType_GetSubclasses()`'s loop-index `i` declaration. No completed port is claimed. + +--- + +## `type_dealloc()` `et` C89 declaration slice (frontier advances) + +Date: 2026-11-17 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` does not exist; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16/MSVC6 reference before acting. CPython baseline is tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved existing work; no reset, clean, stash, discard, commit, push, or publication. Outer working tree was already extensively dirty/untracked; nested CPython also had extensive pre-existing modifications. + +Forced-fresh pre-change command: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261117-current-reprobe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable diagnostics at `cpython/Objects/typeobject.c(4191)`: C2275 `PyHeapTypeObject` and C2065 `et`; member-access errors cascade. Exact output captured in the log. + +Hermes coding delegation was attempted but failed before launch because configured Anthropic credentials are unavailable; authenticated Codex CLI is installed, but delegated tool cannot select its provider. Implemented one narrow strict-TDD slice directly. RED Python structural assertion failed as expected (exit 1): `type_dealloc: et must be declared at function entry (C89)`. Minimal production edit in `cpython/Objects/typeobject.c`: add `PyHeapTypeObject *et;` at function entry and replace only the initialized declaration with `et = (PyHeapTypeObject *)type;` at the same point after `PyObject_Free((char *)type->tp_doc);`. Focused assertion passed (exit 0); all 81 applicable `scripts/vc6-typeobject-*.test.py` tests passed (0 failures, exit 0); `git -C cpython diff --check -- Objects/typeobject.c` passed (exit 0). + +Forced-fresh post-change probe: same command with capture `build/cron-20261117-after-et.log` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former line-4191 `et` diagnostics cleared. Next first stable diagnostics advance to `typeobject.c(4214)` in `_PyType_GetSubclasses()`: C2275 `PyObject` and C2065 `subclasses`; later declarations are separate and untouched. Files changed: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-dealloc-et-c89.test.py`, and `PORT_STATUS.md`; probe logs are build artifacts. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter run, or Windows 98 SE execution. Next frontier: fresh-confirm and isolate only `_PyType_GetSubclasses()` `subclasses` declaration. No completed port is claimed. + +--- + + + +Date: 2026-10-25 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read the current `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved the extensive existing dirty/untracked workspace; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh command: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-run/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics reconfirm at `cpython/Objects/typeobject.c(4191)`: C2275 `PyHeapTypeObject` and C2065 `et`; subsequent member-access errors cascade. Full capture: `build/cron-20261025-run/probe.log`. The expected `MSVC600/VC98/bin/VCVARS32.BAT` path is absent (test exit 1), although the project probe itself successfully invoked the configured compiler. + +One focused coding subagent was attempted, as required, but delegation failed before starting because the configured Anthropic provider has no credentials. No alternate coding CLI was available through the delegation workflow; no code or test edits were made. The exact `et` frontier is confirmed, but this run is diagnostics-only rather than a TDD implementation slice. Files changed by this run: `PORT_STATUS.md` only; the compiler log is a build artifact. This is compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: perform one strict-TDD, narrowly scoped `et` declaration slice with an available authenticated coding lane; then run applicable regressions and another forced-fresh probe. No completed port is claimed. + +--- + +## Diagnostics-only: current compiler frontier reconfirmed at `typeobject.c(4191)` + +Date: 2026-10-25 UTC. Requested `/home/ubuntu/projects/python-win9x` does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference. Preserved existing work: outer checkout has 153 status entries (many modified/untracked), and nested CPython has 131; no reset, clean, stash, discard, commit, push, or publication. Baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Local VC6 launcher `MSVC600/VC98/bin/VCVARS32.BAT` is absent (check exit 1). + +The requested `_blake2/blake2s_impl.c` condition is stale: forced-fresh command `mkdir -p /home/ubuntu/r build/cron-20261025-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-current-reprobe/probe.log 2>&1` returned probe exit 2, summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics remain in `cpython/Objects/typeobject.c(4191)`: C2275 `PyHeapTypeObject` and C2065 `et`, with subsequent member-access diagnostics cascading. Full capture: `build/cron-20261025-current-reprobe/probe.log`. + +The required focused coding subagent could not start because configured Anthropic credentials are unavailable; Claude CLI is absent, and no alternate authenticated coding CLI was used. No source or tests were changed. Files changed by this run: `PORT_STATUS.md` only; probe log is a build artifact. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution. Next frontier: restore the external local-only MSVC600 launcher/toolchain, then use a focused strict-TDD coding lane to isolate the `et` declaration at `typeobject.c(4191)`; no completed port is claimed. + +--- + +## `type_getattro()` local descriptor getter C89 declaration slice (frontier advances) + +Date: 2026-10-25 UTC. The requested `/home/ubuntu/projects/python-win9x` path is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before editing. CPython checkout verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved extensive pre-existing work (outer repo has many dirty/untracked paths; CPython has many modified files); no reset, clean, stash, discard, commit, push, or publication. Anthropic coding delegation unavailable (no credentials); implementation done directly with TDD. + +Forced-fresh pre-change probe: `mkdir -p /home/ubuntu/r build/cron-20261025-current-reprobe && XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2s_impl.c` compiled; first stable errors at `cpython/Objects/typeobject.c(4025)`: C2275 `descrgetfunc`, C2146 before `local_get`, C2065 `local_get`, then C2063 at call. VC6 banner independently verified through Wine: `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86` (exit 0). + +Strict TDD: new `scripts/vc6-typeobject-type-getattro-local-get-c89.test.py` failed before production edit (RED exit 1, assertion that `local_get` must precede statements in its block). The sole production edit in `cpython/Objects/typeobject.c` declares `descrgetfunc local_get;` before the block's statements, then assigns `local_get = Py_TYPE(attribute)->tp_descr_get;` at the original evaluation point. Focused test passed (exit 0); parent independently ran all 81 `scripts/vc6-typeobject-*.test.py` tests with the source path argument (81 passed, 0 failed, exit 0). `git -C cpython diff --check -- Objects/typeobject.c` passed (exit 0). + +Forced-fresh post-change command: `mkdir -p /home/ubuntu/r build/cron-20261025-after-type-getattro; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-after-type-getattro/probe.log 2>&1` — exit 2; summary still `total=109 compiled=108 cached=0 skipped=0`. The former line-4025 diagnostics cleared. First remaining stable family advances to `typeobject.c(4191)`: C2275 `PyHeapTypeObject` and C2065 `et`; subsequent member-access errors cascade. Full capture: `build/cron-20261025-after-type-getattro/probe.log`. + +Files changed by this run: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-getattro-local-get-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `et` declaration at `typeobject.c(4191)`. No completed port is claimed. + +--- + +## `_PyType_Lookup()` cache-update `entry` C89 declaration slice (frontier advances) + +Date: 2026-10-25 UTC. Requested `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16/Win9x/MSVC6 reference. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. + +Forced-fresh pre-change probe: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic: `cpython/Objects/typeobject.c(3927)` C2143 at the late initialized `struct type_cache_entry *entry`; subsequent errors begin at line 4024. Full log: `build/cron-20261025-autonomous-reprobe/probe.log`. + +One authenticated Codex CLI 0.153.4 coding lane followed strict TDD. New `scripts/vc6-typeobject-lookup-cache-entry-c89.test.py` failed before source edit (RED exit 1: `_PyType_Lookup cache update: entry must precede statements (C89)`). The sole production change in `cpython/Objects/typeobject.c` declares `entry` before the cache-update block statements and changes the initialized declaration into `entry = &cache->hashtable[h];` immediately after the unchanged hash recalculation. Focused test passed; parent independently ran all 80 `scripts/vc6-typeobject-*.test.py` tests (80 passed, 0 failed). The lane's first post-change probe attempt failed before compilation because Wine tried to create a lock under a read-only runtime path (exit 1); parent retried with `/home/ubuntu/r` and forced fresh successfully. + +Post-change probe command (same as above): exit 2; `total=109 compiled=108 cached=0 skipped=0`. The former line-3927 diagnostic cleared. First remaining diagnostics are in `typeobject.c(4025)`: C2275 `descrgetfunc`, C2146 before `local_get`, C2065 `local_get` (later errors are cascading/additional blockers). Capture: `build/cron-20261025-after-cache-entry/probe.log`. Nested and outer scoped `git diff --check` passed (exit 0); exact source delta and preservation of all other baseline tracked/untracked paths, including pre-existing `PORT_STATUS.md` edits, were independently checked. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-lookup-cache-entry-c89.test.py`, and this status entry. Compiler-probe progress only; no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm then isolate the `lookup_maybe_method()` `descrgetfunc local_get` declaration. No completed port is claimed. + +--- + +## `find_name_in_mro()` loop-index `i` C89 declaration slice (frontier advances) + +Date: 2026-10-25 UTC. The requested `/home/ubuntu/projects/python-win9x` path is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read the current status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. MSVC600 launcher/banner verified through Wine: `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86` (exit 0). + +Forced-fresh pre-change probe command: `mkdir -p /home/ubuntu/r build/cron-20261025-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-current-reprobe/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics at `cpython/Objects/typeobject.c(3865)`: C2143 for C99 `for (Py_ssize_t i...)` and C2065 undeclared `i`; later `typeobject.c` diagnostics are independent/later. Capture: `build/cron-20261025-current-reprobe/probe.log`. + +Hermes coding delegation could not start because Anthropic credentials are unavailable. One authenticated Codex CLI 0.153.4 lane followed strict TDD. The focused pre-existing `scripts/vc6-typeobject-find-name-in-mro-c89.test.py` first failed because its expectation was stale: it placed `if` directly after `res`, while `n` was already hoisted. The lane repaired this fixture expectation and observed RED specifically on loop-local `i` before changing production code. It then hoisted only `Py_ssize_t i;` into `find_name_in_mro()`'s opening declarations and changed the loop initializer to `for (i = 0; ...)`; the directly coupled `scripts/vc6-typeobject-find-name-in-mro-n-c89.test.py` expectations were updated. Parent independently reran all 79 `scripts/vc6-typeobject-*.test.py`: 79 passed, 0 failed (exit 0). Outer and nested `git diff --check` passed (exit 0). Delegated hash verification reports only `cpython/Objects/typeobject.c`, the focused find-name fixture, and the coupled n fixture differ from the pre-lane snapshot; all other pre-existing modified/untracked files, including this status file before this entry, remained unchanged. + +Forced-fresh after-change command: `mkdir -p /home/ubuntu/r build/cron-20261025-after-find-name-i; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-after-find-name-i/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former diagnostics at `typeobject.c(3865)` cleared. First remaining diagnostic is `typeobject.c(3927)` C2143, followed by a distinct C2275/C2146/C2065 family at line 4024 (`descrgetfunc local_get`) and later declaration errors; these are untouched. Full capture: `build/cron-20261025-after-find-name-i/probe.log`. + +Files changed by the implementation slice: `cpython/Objects/typeobject.c`, `scripts/vc6-typeobject-find-name-in-mro-c89.test.py`, `scripts/vc6-typeobject-find-name-in-mro-n-c89.test.py`, and this status record. This is compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution. Next: inspect and isolate the actual `typeobject.c(3927)` blocker after a fresh confirmation. No completed port is claimed. + +--- + +## Diagnostics-only: recorded `find_name_in_mro()` state conflicts with checkout + +Date: 2026-10-25 UTC. The requested `/home/ubuntu/projects/python-win9x` path is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing local state; no reset, clean, stash, discard, commit, push, or publication. CPython tag/commit verified as `v3.11.16`, `41388c9cb160d0886d5ca00d2e6c8782608a4549`; compiler launcher exists and prior recorded banner is MSVC 12.00.8804. + +The requested `_blake2/blake2s_impl.c`-frontier condition is not current: forced-fresh command `mkdir -p /home/ubuntu/r build/cron-20261025-blake2-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261025-blake2-reprobe/probe.log 2>&1` returned probe exit 2, summary `total=109 compiled=108 cached=0 skipped=0`; the first blocker is `cpython/Objects/typeobject.c`, with first diagnostic family at line 3865: C2143 on C99 `for (Py_ssize_t i...)`, undeclared `i` (C2065), and cascades. `_blake2/blake2s_impl.c` has local modifications and remains untouched. Full log: `build/cron-20261025-blake2-reprobe/probe.log`. + +The recorded `find_name_in_mro()` mro/res fix is not reliably present in the checked-out source state: its existing focused regression `python3 scripts/vc6-typeobject-find-name-in-mro-c89.test.py cpython/Objects/typeobject.c` fails exit 1 at the opening-declaration assertion (also reports a Python invalid-escape SyntaxWarning). No production implementation was attempted because repository state is heavily dirty, source-list probe does not isolate the recorded target, and the fixture/source mismatch means the recorded frontier cannot safely be presumed. One 78-test loop attempt stopped at that first failing fixture; no full regression pass is claimed. Nested `git -C cpython diff --check -- Objects/blake2/blake2s_impl.c` and outer `git diff --check -- PORT_STATUS.md` both exit 0. No files outside this status record were changed by this run; probe output is an untracked build artifact. + +Compiler-probe progress only. No `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution. Next: reconcile the existing `find_name_in_mro` fixture and local production diff against prior work without overwriting any of it; then establish a narrowly targeted forced-fresh probe for the actual typeobject frontier before choosing a single slice. No completed port is claimed. + +--- + +## `find_name_in_mro()` `mro`/`res` C89 declaration slice (frontier advances) + +Date: 2026-06-05 UTC. The requested `/home/ubuntu/projects/python-win9x` path is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before action. Preserved all pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. VC6 launcher/banner: `wine cmd /c 'call Z:\\home\\ubuntu\\Organized\\Legacy-Ports\\Projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` — exit 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20260605-frontier-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20260605-frontier-reprobe/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiles. First stable diagnostic family in `typeobject.c(3842)` was C2275 `PyObject` / C2065 `mro`; next late `PyObject *res` at 3857 also failed, followed by separate `n`/`i` declarations at 3861–3862. Capture: `build/cron-20260605-frontier-reprobe/probe.log`. + +One coding-agent workflow was attempted: Hermes delegation failed because Anthropic credentials are unavailable. Authenticated Codex CLI 0.153.4 was used for the single focused lane. Strict TDD: new `scripts/vc6-typeobject-find-name-in-mro-c89.test.py` failed before production edit (RED exit 1, assertion that `mro` and `res` must be declared at function entry); after the minimal change the test passed (exit 0). Only the `mro` and `res` declarations were hoisted into function-entry locals and their initializers moved to their original points. Parent independently ran all 78 `scripts/vc6-typeobject-*.test.py` files; 78 passed, 0 failed (exit 0). Nested production and outer new-test `git diff --check` passed (exit 0). Codex verified 278 pre-existing files preserved; reviewed full CPython diff and it includes extensive earlier local modifications, with this slice limited to `find_name_in_mro()` plus the focused new test. + +Forced-fresh post-change command: `mkdir -p build/cron-20260605-after-find-name-in-mro; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20260605-after-find-name-in-mro/probe.log 2>&1` — exit 2. Former `mro`/`res` diagnostics cleared; first stable blocker advances to `typeobject.c(3863)` C2275/C2146/C2065 for `Py_ssize_t n`, followed by C99 loop-index `i` diagnostics at 3864. Left untouched. Capture: `build/cron-20260605-after-find-name-in-mro/probe.log`. + +Files changed in this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-find-name-in-mro-c89.test.py`, and this status record. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `n` declaration in `find_name_in_mro()`. No completed port is claimed. + +--- + +## `PyType_GetModuleByDef()` `ht`/`module` C89 declaration slice (frontier advances) + +Date: 2026-10-24 UTC. The requested `/home/ubuntu/projects/python-win9x` path is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before action. Preserved all existing modified/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains v3.11.16, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`; MSVC600 local bundle is present. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261024-followup/runtime; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-followup/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The recorded `PyType_GetModuleByDef()` frontier remained current: first stable errors at `typeobject.c(3807)` C2143 and `(3808)` C2275/C2065 for late `PyHeapTypeObject *ht` / `PyObject *module` declarations. + +One authenticated Codex CLI 0.153.4 coding lane used strict TDD and preserved pre-existing state. New `scripts/vc6-typeobject-get-module-by-def-ht-module-c89.test.py` failed against unchanged source (RED exit 1, expected opening-declarations assertion). The minimal production change declares `ht` and `module` with existing function-entry locals and changes their initializers to assignments at the original point after the static-type skip. Directly coupled index, mro, and n fixtures were updated for the changed declarations/assignments. Focused regression passed (exit 0); parent independently reran all 77 `scripts/vc6-typeobject-*.test.py` tests (77 passed, 0 failed, exit 0). Both nested production and outer test `git diff --check` commands exited 0. Snapshot verification reported no unrelated pre-existing modified/untracked paths changed. + +Forced-fresh after-change command: `mkdir -p build/cron-20261024-after-ht-module; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-ht-module/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The `ht`/`module` diagnostics cleared. First stable diagnostics now occur in `find_name_in_mro()` at `typeobject.c(3842)` (C2275 `PyObject`, C2065 `mro`), followed by `res` at 3857 and C99 `n`/`i` declarations at 3861–3862. These are a distinct next function/frontier and remain untouched. Full capture: `build/cron-20261024-after-ht-module/probe.log`. + +Files changed in this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-get-module-by-def-ht-module-c89.test.py`; updated `scripts/vc6-typeobject-get-module-by-def-index-c89.test.py`, `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py`, `scripts/vc6-typeobject-get-module-by-def-n-c89.test.py`; and this status record. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm then isolate only the first C89 declaration family in `find_name_in_mro()`. No completed port is claimed. + +--- + +## `PyType_GetModuleByDef()` loop-index `i` C89 declaration slice (frontier advances) + +Date: 2026-10-24 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` was absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved existing dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Outer HEAD remains `35caf1a558e6b2c5bf501894d8972f8b0dd828a6`. VC6 launcher/banner check: `wine cmd /c 'call Z:\home\ubuntu\Organized\Legacy-Ports\Projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` — exit 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. + +The status-recorded frontier was stale. Forced-fresh pre-change command: `mkdir -p build/cron-20261024-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-current-reprobe/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic family was `typeobject.c(3799)`: C2143 on the C99 `for (Py_ssize_t i = ...)` initializer and C2065 undeclared `i`; dependent loop/syntax errors followed. Capture: `build/cron-20261024-current-reprobe/probe.log`. + +One authenticated Codex CLI 0.153.4 coding lane used strict TDD. New `scripts/vc6-typeobject-get-module-by-def-index-c89.test.py` failed before source edit (RED exit 1, expected assertion that `i` must be in the opening C89 locals). The sole production change in `cpython/Objects/typeobject.c` hoists `Py_ssize_t i;` alongside existing `mro` and `n` locals and changes the loop initializer to `i = 0`; loop bounds, increment, body, and evaluation order are otherwise unchanged. The existing `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py` and `scripts/vc6-typeobject-get-module-by-def-n-c89.test.py` fixtures were narrowly updated to include the added declaration and preserve the loop form. The focused new regression passed (exit 0); parent reran all 76 `scripts/vc6-typeobject-*.test.py` tests (76 passed, 0 failed; exit 0). Nested and outer scoped `git diff --check` passed (exit 0). + +Forced-fresh post-change command: `mkdir -p /home/ubuntu/r build/cron-20261024-after-index; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-index/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`. The `i` diagnostics cleared. First stable diagnostics advance to `typeobject.c(3807)` C2143 before `type`, then line 3808 C2275 `PyObject` / C2065 `module` and `ht` in the separate late `PyHeapTypeObject *ht` / `PyObject *module` declarations; these were left untouched. Full capture: `build/cron-20261024-after-index/probe.log`. An initial delegated probe attempt used a repository-local XDG runtime and failed before compilation due Wine server lock/socket setup (exit 1); parent reran with `/home/ubuntu/r` and obtained the valid forced-fresh result above. + +Files changed in this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-get-module-by-def-index-c89.test.py`; updated `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py` and `scripts/vc6-typeobject-get-module-by-def-n-c89.test.py`; and this status entry. This is compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the next `PyType_GetModuleByDef()` late declaration family at lines 3807–3808. No completed port is claimed. + +--- + +## `PyType_GetModuleByDef()` `mro` C89 declaration slice (frontier advances) + +Date: 2026-10-24 12:00 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before changes. Preserved pre-existing local work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261024-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-current-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The `typeobject.c` first stable diagnostics were line 3788 C2143 before `type`, line 3790 C2065 `mro`, and then distinct later `n`/`i` errors at lines 3796–3797. Capture: `build/cron-20261024-current-reprobe/probe.log`. + +One authenticated Codex CLI 0.153.4 coding lane followed strict TDD and preserved state. New `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py` failed against unchanged source (RED exit 1: `mro must be declared at function entry (C89)`); `cmp` confirmed source unchanged during RED. The only production edit declares `PyObject *mro;` before the assertion and assigns `mro = type->tp_mro;` at its original evaluation point. Focused test passed (exit 0); all 74 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). Parent independently repeated both checks and scoped outer/nested `git diff --check` (all exit 0). Snapshot verification found all 273 other pre-existing modified/untracked files unchanged. + +Forced-fresh after-change command: `mkdir -p build/cron-20261024-after-get-module-by-def-mro/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-after-get-module-by-def-mro/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-get-module-by-def-mro/probe.log 2>&1` — probe exit 2; summary unchanged `total=109 compiled=108 cached=0 skipped=0`. Former `mro` errors cleared. First stable blocker advances to line 3797 C2275 `Py_ssize_t`, C2146 before `n`, and C2065 `n`; the separate C99 loop initializer `i` at 3798 follows. Both untouched. Capture: `build/cron-20261024-after-get-module-by-def-mro/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `Py_ssize_t n` declaration in `PyType_GetModuleByDef()`. No completed port is claimed. + +--- + +## `PyType_GetModule()` `et` C89 declaration slice (frontier advances) + +Date: 2026-10-24 09:48 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing dirty/untracked paths; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261116-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261116-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261116-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic family: `cpython/Objects/typeobject.c(3756)` C2275 `PyHeapTypeObject` and C2065 `et`; dependent C2223 diagnostics cascade in `PyType_GetModule()`. Capture: `build/cron-20261116-current-reprobe/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD and preserved all prior changes. New `scripts/vc6-typeobject-get-module-et-c89.test.py` failed against unchanged production source (RED exit 1, expected declaration-placement assertion). The only production change declares `PyHeapTypeObject *et;` at `PyType_GetModule()` entry and changes the original cast declaration into `et = (PyHeapTypeObject*)type;` at the same execution point. Focused test passed (exit 0); all 73 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). `git -C cpython diff --check -- Objects/typeobject.c` passed (exit 0); check of the new untracked test emitted no whitespace diagnostics (git `--no-index` returned 1 because files differ). + +Forced-fresh after-change command: `mkdir -p build/cron-20261116-after-get-module-et/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261116-after-get-module-et/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261116-after-get-module-et/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former `PyType_GetModule()` diagnostics cleared. First remaining blocker advances to `PyType_GetModuleByDef()` at `typeobject.c(3788)`, C2143 before `type` and C2065 `mro`, followed by separate late `Py_ssize_t n` and loop-index errors at 3796–3797; untouched. Capture: `build/cron-20261116-after-get-module-et/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-module-et-c89.test.py`, and this status record. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `PyType_GetModuleByDef()` `mro` declaration family. No completed port is claimed. + +--- + +## `PyType_FromModuleAndSpec()` `memb` C89 loop declaration slice (frontier advances) + +Date: 2026-10-23 22:51 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before changes. Preserved existing modifications/untracked work; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change compiler probe: `mkdir -p build/cron-20260603-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20260603-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20260603-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic family: `cpython/Objects/typeobject.c(3452)` C2143 before `type`, then C2065 `memb`; subsequent member-access diagnostics cascade. Capture: `build/cron-20260603-reprobe/probe.log`. + +Hermes delegation was unavailable because no Anthropic credentials were configured. One authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) performed the isolated implementation work with preservation checks. Strict TDD: new `scripts/vc6-typeobject-from-module-and-spec-memb-c89.test.py` failed against the unchanged production source at its declaration-placement assertion (RED, exit 1); the pre-edit `typeobject.c` snapshot comparison confirmed it was unchanged. The minimal production change declares `const PyMemberDef *memb;` at the start of the `Py_tp_members` block and changes the loop header to `for (memb = slot->pfunc; ...)`, keeping initialization/evaluation at the original loop point. No other behavior or fixture changed. Focused GREEN passed (exit 0); all 69 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Delegated hash/snapshot verification reported all 268 other pre-existing dirty paths unchanged and the production delta exact. Scoped outer/nested `git diff --check` passed (exit 0). + +Forced-fresh post-change probe command: `mkdir -p build/cron-20260603-after-memb/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20260603-after-memb/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20260603-after-memb/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former line-3452 errors cleared. First remaining stable errors advance to `typeobject.c(3493)` C2143 before `const`, followed by C2065 `s`; this separate late `const char *s` declaration in `PyType_FromModuleAndSpec()` is untouched. Full capture: `build/cron-20260603-after-memb/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-from-module-and-spec-memb-c89.test.py`, and this status record. Compiler-frontier probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `PyType_FromModuleAndSpec()` `const char *s` declaration family at line 3493. No completed port is claimed. + +--- + +## `type_vectorcall()` `tstate` C89 declaration slice (frontier advances) + +Date: 2026-11-16 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the active-profile CPython Win9x/MSVC6 reference. Preserved all existing dirty/untracked changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: v3.11.16, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261116-frontier/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261116-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261116-frontier/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable blocker: `cpython/Objects/typeobject.c(3409)`, C2275 `PyThreadState` and C2065 `tstate` in `type_vectorcall()`. Full capture: `build/cron-20261116-frontier/probe.log`. + +Strict TDD via one authenticated Codex CLI fallback lane (Hermes delegation provider unavailable: Anthropic credentials missing). New `scripts/vc6-typeobject-type-vectorcall-tstate-c89.test.py` failed before production edit as expected (RED exit 1, missing opening declaration assertion). Hoisted only `PyThreadState *tstate;` to the opening declarations and retained `_PyThreadState_GET()` at the existing fallback execution point. The existing `scripts/vc6-typeobject-type-vectorcall-nargs-c89.test.py` required a narrow expectation update for that declaration placement. Focused regression passed; all 68 `scripts/vc6-typeobject-*.test.py` passed (exit 0); outer and nested `git diff --check` passed. The first full regression attempt had one stale fixture expectation (67 pass/1 fail); after the coupled expectation update the full run was clean. + +Forced-fresh post-change command: `mkdir -p build/cron-20261116-after-tstate/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261116-after-tstate/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261116-after-tstate/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Former line-3409 C2275/C2065 errors cleared. Next stable blocker advances to `typeobject.c(3452)`: C2143 missing `;` before `type`, C2065 `memb`, followed by cascading member-access errors; left untouched. Full capture: `build/cron-20261116-after-tstate/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-vectorcall-tstate-c89.test.py`, adjusted `scripts/vc6-typeobject-type-vectorcall-nargs-c89.test.py`, and this status record. Compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution. Next: force-fresh confirm and isolate only the new `typeobject.c(3452)` declaration/initializer family. No completed port is claimed. + +--- + +## `type_vectorcall()` `tstate` declaration frontier (diagnostics only) + +Date: 2026-11-15 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before work. Preserved all pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh probe: `mkdir -p build/cron-20261115-frontier/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261115-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261115-frontier/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The first stable diagnostic is `cpython/Objects/typeobject.c(3407)`: C2275 `PyThreadState` and C2065 `tstate`, corresponding to `type_vectorcall()`'s late initialized `PyThreadState *tstate`. The old `type_new()` frontier is stale. Full capture: `build/cron-20261115-frontier/probe.log`. + +The Hermes coding subagent could not start (Anthropic credentials unavailable). The authenticated Codex CLI fallback was launched in an ephemeral workspace-write lane, but its session/result was not retrieved in this run; no delegated changes are claimed as verified. Existing regressions: all 66 `scripts/vc6-typeobject-*.test.py` passed (exit 0); focused `scripts/vc6-typeobject-vectorcall-maybe-c89.test.py` passed (exit 0). `python3 -m pytest scripts/vc6-typeobject-*.test.py -q` could not run because pytest is not installed (exit 1). A broad `*vectorcall*` invocation initially failed four fixtures because they require source-path arguments; with one supplied path, three applicable vectorcall tests passed but the range-object fixture was given the wrong source path and failed. This was an invocation error, not an established product regression. `git -C cpython diff --check -- Objects/typeobject.c` exited 0. No source/test modifications by this run are confirmed; this status record and the forced probe log were written. + +Compiler-probe progress only. No linked `pythoncore`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution. Next: inspect/retrieve delegated lane outcome; if absent or no valid result, TDD only the `type_vectorcall()` `tstate` declaration placement, run targeted regressions and forced-fresh compiler probe. No completed port is claimed. + +--- + +## `type_new()` `type`/`res` C89 declaration slice + +Date: 2026-10-23 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference first. Preserved pre-existing dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261023-recheck/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261023-recheck/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics at `typeobject.c(3373)` C2275 `PyObject` / C2065 `type`, then C2143 at 3374 and C2065 `res` at 3375; later separate `PyThreadState` diagnostics at 3405. Full capture: `build/cron-20261023-recheck/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed TDD. New `scripts/vc6-typeobject-type-new-c89.test.py` failed before source edit as expected (RED exit 1, assertion that declarations must be in opening block). Hoisted only `PyObject *type` and `int res` into `type_new()` declarations; assignments remain at their original execution points. Narrowly updated directly coupled `type-new-args` and `type-new-ctx` fixture expectations. Focused test plus both coupled tests passed; all 66 `scripts/vc6-typeobject-*.test.py` passed (exit 0). Nested source `git diff --check` passed; outer check for three affected fixtures passed. Changes: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-c89.test.py`, and updated `scripts/vc6-typeobject-type-new-args-c89.test.py` / `scripts/vc6-typeobject-type-new-ctx-c89.test.py`. + +Post-change VC6 probe was not run: `MSVC600/VC98/bin/VCVARS32.BAT` is absent. Thus no compiler progress is verified for this slice; no `pythoncore`/`python.exe` link, Wine interpreter run, or Windows 98 SE run. Next frontier remains the recorded type_new local declarations, including the later `PyThreadState *tstate` family, and requires restoring the local-only compiler bundle for actual post-change probe. No completed port is claimed. + +--- + +## Diagnostics-only: `type`/`res` frontier reconfirmed; compiler bundle absent + +Date: 2026-10-23 09:56 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing dirty and untracked work; no reset, clean, stash, discard, commit, push, or publication. Baseline verified: CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The current recorded frontier was re-probed forced-fresh. Command: `mkdir -p build/cron-20261109-frontier-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261109-frontier-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable errors reconfirmed at `cpython/Objects/typeobject.c(3373)`: C2275 `PyObject` and C2065 `type`; line 3374 C2143 before `type`; line 3375 C2065 `res`. The later `PyThreadState`/`tstate` errors at 3405 are a separate later family. Full capture: `build/cron-20261109-frontier-reprobe/probe.log`. + +`MSVC600/VC98/bin/VCVARS32.BAT` remains absent (file check exit 1), so the actual VC6 compiler banner/probe cannot be executed and no source slice can be safely verified. No coding subagent, source edit, or regression edit was made; this run is diagnostics-only and not a TDD cycle. Files changed by this run: `PORT_STATUS.md` only; probe log is an untracked build artifact. Compiler-frontier probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution. Next frontier: restore the external local-only MSVC600 bundle, then add a RED placement regression and isolate only the `type`/`res` declaration family, run focused regressions, and force-fresh probe. No completed port is claimed. + +--- + +## Diagnostics-only: current `type`/`res` frontier confirmed; VC6 bundle unavailable + +Date: 2026-11-06 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing local changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh command: `mkdir -p build/cron-20261106-refresh/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261106-refresh/probe.log 2>&1` — probe exit 2; `_blake2/blake2s_impl.c` compiled. First stable errors reconfirm at `cpython/Objects/typeobject.c(3373)`: C2275 `PyObject` / C2065 `type`, followed by line 3374 C2143 before `type` and line 3375 C2065 `res`. Later diagnostics include line 3405 `PyThreadState`/`tstate`; left untouched. Capture: `build/cron-20261106-refresh/probe.log`. + +`MSVC600/VC98/bin/VCVARS32.BAT` is absent (check returned absent). Therefore no implementation slice could be safely verified with the required actual compiler, and no source/test was changed. The single Hermes coding-delegation attempt failed to start because the configured Anthropic provider has no credentials; no fallback coding CLI was invoked. Files changed by this run: `PORT_STATUS.md` only; the forced probe log is an untracked build artifact. This is diagnostics-only, not a TDD cycle. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: restore the external local-only MSVC600 bundle, add a RED declaration-placement regression, then isolate only the `type`/`res` declarations at lines 3373–3375, run focused regressions, and force-fresh probe. No completed port is claimed. + +--- + +## Diagnostics-only: `type_new()` context frontier advanced to `type`/`res`; VC6 bundle missing + +Date: 2026-10-23 UTC. Requested `/home/ubuntu/projects/python-win9x` is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` first. Preserved all existing local modifications and untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` frontier is stale. Forced-fresh probe command: `mkdir -p build/cron-current-20261106/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-20261106/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics now reconfirm at `cpython/Objects/typeobject.c(3373)`: C2275 `PyObject` and C2065 `type`; next line 3374 C2143 before `type`, then line 3375 C2065 `res`. Later independent errors include line 3405 `PyThreadState`/`tstate`; subsequent diagnostics are not part of this first blocker. Full capture: `build/cron-current-20261106/probe.log`. + +The external compiler launcher `MSVC600/VC98/bin/VCVARS32.BAT` is absent (checked; exit 1), so no safe code slice with required post-edit VC6 verification was available. No coding subagent or source/test edit was made. Applicable regressions: all 65 `scripts/vc6-typeobject-*.test.py` scripts passed (exit 0); `git -C cpython diff --check -- Objects/typeobject.c` passed (exit 0). Files changed by this run: `PORT_STATUS.md` only; probe output is an untracked build artifact. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: restore the external MSVC600 compiler bundle, then add a RED declaration-placement regression and isolate only the `type`/`res` declarations at `typeobject.c(3373–3375)`, verify applicable regressions and force-fresh probe. No completed port is claimed. + +--- + +## `type_new()` context declaration C89 slice (frontier advances) + +Date: 2026-10-23 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved pre-existing local modifications/untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change probe: `mkdir -p build/cron-20261106-frontier-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261106-frontier-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261106-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable diagnostics at `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, C2059 at `{`; subsequent member diagnostics cascade. The actual `MSVC600/VC98/bin/VCVARS32.BAT` launcher is absent, confirmed by file check (exit 1), so no coding delegation requiring compiler-backed confirmation was appropriate. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`) followed strict TDD under workspace-write/ephemeral, with explicit preservation constraints. + +RED: `python3 scripts/vc6-typeobject-type-new-ctx-c89.test.py` against unchanged production source exited 1 at the expected opening-declaration assertion. The old fixture only extracted the initializer and did not establish its placement. GREEN: hoisted only `type_new_ctx ctx;` into `type_new()`'s declaration block; replaced the original `{0}` initializer with `memset(&ctx, 0, sizeof(ctx));` at the original post-parse point, preserving zeroing and the existing field assignments' order. Updated the directly coupled argument-prefix fixture. Focused test passed, and all 65 `scripts/vc6-typeobject-*.test.py` scripts passed (exit 0). Snapshot check verified all 263 other pre-existing dirty/untracked files byte-identical, including `PORT_STATUS.md` before this record. `git -C cpython diff --check -- Objects/typeobject.c` exited 0. + +Forced-fresh after-change probe: `mkdir -p build/cron-20261106-after-type-new-ctx/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261106-after-type-new-ctx/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261106-after-type-new-ctx/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The former line-3365 context declaration errors cleared; first remaining blocker advances to `typeobject.c(3373)` C2275 `PyObject` / C2065 `type`, followed by C2143/C2065 for `res` at 3374–3375. These distinct declarations remain untouched. Captures are in the two build directories. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. + +Files changed by this slice: `cpython/Objects/typeobject.c`; `scripts/vc6-typeobject-type-new-ctx-c89.test.py`; directly coupled `scripts/vc6-typeobject-type-new-args-c89.test.py`; and this status record. Next frontier: fresh-confirm and isolate the separate `type`/`res` declarations beginning at `typeobject.c(3373)`. No completed port is claimed. + +--- + +## Diagnostics-only: `type_new_ctx` declaration frontier reconfirmed; VC6 bundle absent + +Date: 2026-10-22 23:19 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing work; no reset, clean, stash, discard, commit, push, or publication. Baseline verified: CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh command: `mkdir -p build/cron-20261029-run-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-run-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics remain at `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, and C2059 at `{`; following C2224 member errors cascade. Capture: `build/cron-20261029-run-reprobe/probe.log`. `MSVC600/VC98/bin/VCVARS32.BAT` remains absent (check exit 1), preventing safe compiler-backed implementation verification. No coding subagent or source/test changes were appropriate; this is diagnostics-only and not a TDD cycle. Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: restore the external local-only MSVC600 bundle, then test-first hoist only `type_new_ctx ctx` into the C89 declaration block, run focused regressions, and force-fresh probe. No completed port is claimed. + +--- + +Date: 2026-10-29 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved all existing changes; no reset, clean, stash, discard, commit, push, or publication. CPython remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded state was rechecked and remains current: forced-fresh command `mkdir -p build/cron-20261029-recheck/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-recheck/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors reconfirm at `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, and C2059 at `{`; following member-access errors cascade. Capture: `build/cron-20261029-recheck/probe.log`. + +No implementation was safe: prerequisite `MSVC600/VC98/bin/VCVARS32.BAT` is absent in the working checkout. No test/code changes and no coding-agent delegation were made; this remains diagnostics-only, not a TDD cycle. Files changed by this run: `PORT_STATUS.md` only. Compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution. Next frontier: restore the local external MSVC600 compiler bundle, then add a RED regression for hoisting `type_new_ctx ctx` into the C89 declaration block, implement only that placement fix, run focused regressions and a forced-fresh VC6 probe. No completed port is claimed. + +--- + +Date: 2026-10-29 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16/MSVC6 reference at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing changes and untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh current-frontier probe: `mkdir -p build/cron-20261029-fresh-frontier; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-fresh-frontier/probe.log 2>&1` — exit 2; source-list run compiles 108 of 109 entries with zero cached/skipped, and `_blake2/blake2s_impl.c` compiled. First stable blocker reconfirms `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, and C2059 at `{`; subsequent field errors are cascading. Full capture: `build/cron-20261029-fresh-frontier/probe.log`. + +No implementation or regression test was changed. The prerequisite local compiler launcher `MSVC600/VC98/bin/VCVARS32.BAT` is absent (file check returned absent), so post-edit VC6 verification is unavailable in this workspace; did not delegate code changes that could not be independently checked against the actual compiler frontier. No test cycle was claimed. Files changed by this run: `PORT_STATUS.md` only. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: once the external MSVC600 bundle/launcher is restored, add a focused RED test for placing `type_new_ctx ctx` in the declaration block, then make only that declaration-placement change, run its focused test and applicable regressions, and force-fresh probe again. No completed port is claimed. + +--- + +## Diagnostics-only: `type_new_ctx` blocker reconfirmed; coding model unavailable + +Date: 2026-10-22 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved the pre-existing dirty/untracked workspace (136 outer status entries); no reset, clean, stash, discard, commit, push, or publication. CPython remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh probe command: `mkdir -p build/cron-20261022T-current-frontier-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022T-current-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics reconfirm `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, and C2059 at `{`; following field errors cascade. Capture: `build/cron-20261022T-current-frontier-reprobe/probe.log`. + +The previously recorded `type_new_ctx` initializer issue is stale as a defect family: existing local code already uses `{0}` and explicit assignments; the current actual issue is the declaration occurring after statements. A single focused Codex lane was attempted but could not run because the selected model was at capacity (exit 1, per existing `build/codex-type-new-ctx.log`). The local VC6 bundle path `MSVC600/VC98/bin/VCVARS32.BAT` is also absent, so no coding delegation or implementation/test slice was safe. No source/test files changed. + +Files changed this run: `PORT_STATUS.md` only. This is compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: use a runnable coding lane to add a placement-focused RED test for `type_new_ctx ctx`, then narrowly hoist that declaration while leaving initialization/field assignments at their execution point. No completed port is claimed. + +--- + +## Diagnostics-only: `type_new_ctx` frontier reconfirmed; coding lane blocked + +Date: 2026-10-22 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16/MSVC6 reference at `~/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing changes and untracked files. No reset, clean, stash, discard, commit, push, or publication. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh probe command: `mkdir -p build/cron-current-frontier-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable blocker reconfirms `typeobject.c(3365)` designated initializer for `type_new_ctx ctx`, with C2275/C2146/C2065/C2059, followed by cascading diagnostics; later errors include C99 declarations. Capture: `build/cron-current-frontier-reprobe/probe.log`. + +Coding-delegation prerequisites: `codex-cli 0.153.4`, authenticated (`codex login status` reported `Logged in using ChatGPT`); checkout already contained 136 dirty/untracked paths. One focused Codex CLI coding lane was attempted with strict-TDD instructions and exact scope, but stopped before edits because the selected model was at capacity (Codex exit 1; capture `build/codex-type-new-ctx.log`). No production code or tests changed in this run. This run therefore remains diagnostics-only; no test cycle was claimed. + +Files changed by this run: this `PORT_STATUS.md` entry only. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: inspect the `type_new_ctx` definition and isolate the designated initializer when a coding lane can execute. No completed port is claimed. + +--- + +## `type_new()` argument local C89 declaration slice (frontier advances) + +Date: 2026-10-21 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved all pre-existing dirty/untracked files; no reset, clean, stash, discard, commit, push, or publication. Nested CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change VC6/Wine command: `mkdir -p build/cron-20261021-frontier-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-frontier-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics were `typeobject.c(3355)` C2143 before `type`, then C2065 for `name`, `bases`, `orig_dict` at 3357–3359. Capture: `build/cron-20261021-frontier-reprobe/probe.log`. + +Anthropic subagent delegation was unavailable (no credentials); one authenticated Codex CLI 0.153.4 fallback lane performed strict TDD. New `scripts/vc6-typeobject-type-new-args-c89.test.py` failed before the production edit (RED exit 1 at the expected declaration-placement assertion); source comparison confirmed the C file remained unchanged during RED. The only production change hoists `PyObject *name, *bases, *orig_dict;` into the opening declaration block of `type_new()`; argument assertions and `PyArg_ParseTuple` remain at their original execution point. Focused regression passed, and all 64 `scripts/vc6-typeobject-*.test.py` regressions passed individually. Snapshot verification reported 263 other pre-existing dirty/untracked files unchanged, including `PORT_STATUS.md` until this entry was added. Outer and nested `git diff --check` both exited 0. + +Forced-fresh after-change command: `mkdir -p build/cron-20261021-after-type-new-args/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-after-type-new-args/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-after-type-new-args/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former errors at 3355–3359 cleared. First stable blocker advances to the distinct `type_new_ctx ctx` C99 designated initializer at `typeobject.c(3365)` (C2275/C2146/C2065/C2059); later declarations also remain. Capture: `build/cron-20261021-after-type-new-args/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-args-c89.test.py`, and this status entry. Compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: separately evaluate and isolate the `type_new_ctx` designated initializer; untouched in this slice. No completed port is claimed. + +--- + +## `type_new_get_bases()` `base` local C89 declaration slice (frontier advances) + +Date: 2026-10-21 21:40 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before work. Preserved all existing dirty and untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261029-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261029-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors were `typeobject.c(3336)` C2275 `PyTypeObject` / C2065 `base` in `type_new_get_bases()`; following diagnostics begin at `type_new()` line 3354. Capture: `build/cron-20261029-current-reprobe/probe.log`. + +Coding delegation was attempted once via Hermes but the configured Anthropic provider had no credentials. The authenticated Codex CLI fallback inspected the task and found the initial suggested function name was wrong: the actual line-3336 frontier is `type_new_get_bases()`, not `type_new_impl()`. That lane stopped without edits; resuming it was unavailable. Following the requested actual-frontier instruction, strict TDD was then performed in the parent workspace. New `scripts/vc6-typeobject-type-new-get-bases-base-c89.test.py` failed before the production edit (RED exit 1 at the expected opening-declaration assertion). The sole production change declares `PyTypeObject *base;` alongside the existing opening locals and changes the later initialized declaration to `base = best_base(ctx->bases);` at the same evaluation point. Directly affected `type_new_get_bases()` fixture expectations were narrowly updated in the existing index, new-bases, and winner regression scripts. Focused regression passed; all 63 `scripts/vc6-typeobject-*.test.py` scripts passed (0 failures). Outer `git diff --check` and nested `git -C cpython diff --check -- Objects/typeobject.c` passed (exit 0). + +Forced-fresh after-change command: `mkdir -p build/cron-20261029-after-get-bases-base/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261029-after-get-bases-base/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-after-get-bases-base/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former line-3336 C2275/C2065 errors are cleared. First stable diagnostic advances to `typeobject.c(3355)` C2143 (missing `;` before `type`) with related C2065 undeclared `name`, `bases`, and `orig_dict` at 3357–3359 in the following `type_new()` function; left untouched. Capture: `build/cron-20261029-after-get-bases-base/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-type-new-get-bases-base-c89.test.py`; narrowly adjusted `scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py`, `scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py`, and `scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py`; and this status entry. This is compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: fresh-confirm and isolate only the `type_new()` `name`, `bases`, `orig_dict` declaration family beginning at line 3355. No completed port is claimed. + +--- + +## `type_new_init()` C89 local declaration slice (frontier advances) + +Date: 2026-10-28 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261028-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261028-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261028-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable errors: `typeobject.c(3219)` C2275/C2065 for initialized `PyTypeObject *type`; related C2223 at 3224; next declaration family at 3226 (`PyHeapTypeObject *et`). Capture: `build/cron-20261028-current-reprobe/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, ephemeral workspace-write; no commit) followed TDD. New `scripts/vc6-typeobject-type-new-init-c89.test.py` first failed against unchanged source (RED exit 1, expected opening-declaration assertion; `cmp` verified unchanged `typeobject.c`). Minimal production edit hoisted only `PyTypeObject *type` and `PyHeapTypeObject *et` into the function's opening declarations and changed their later initialized declarations to assignments at the same execution points. Focused test passed (exit 0); all 58 `scripts/vc6-typeobject-*.test.py` tests passed individually (0 failures). Snapshot hash check confirmed only `cpython/Objects/typeobject.c` changed among existing paths and only the new focused regression was added; pre-existing dirty `PORT_STATUS.md` and all other pre-existing paths remained byte-identical during the coding lane. Outer and nested `git diff --check` both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261028-after-type-new-init/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261028-after-type-new-init/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former line-3219/3226 diagnostics cleared. First current stable diagnostics advance to `typeobject.c(3286)` C2275/C2065 for `PyObject *new_bases` in `type_new_impl()`; later C99 loop initializer at 3294 is separate and left untouched. The targeted source compiled with those later errors. Capture: `build/cron-20261028-after-type-new-init/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-init-c89.test.py`, and this entry in `PORT_STATUS.md`. Compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only `type_new_impl()`'s `new_bases` declaration. No completed port is claimed. + +--- + +## `type_new_get_slots()` `new_slots` declaration C89 slice (frontier advances) + +Date: 2026-10-27 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all existing modifications/untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The formerly recorded `typeobject.c(3025)` loop-index frontier had cleared. Forced-fresh pre-change probe command: `mkdir -p build/cron-20261027-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261027-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261027-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Initial blocker was `cpython/Objects/typeobject.c(3185)` C2275 (`PyObject`) / C2065 (`new_slots`), in `type_new_get_slots()`. Log: `build/cron-20261027-current-reprobe/probe.log`. + +Anthropic-backed delegation was unavailable (missing credentials); one authenticated Codex CLI 0.153.4 fallback lane followed TDD. New `scripts/vc6-typeobject-type-new-get-slots-new-slots-c89.test.py` first failed against unchanged C source (RED exit 1, expected opening-declaration assertion; `cmp` verified unchanged source). Minimal edit moves only `PyObject *new_slots;` from just before its first use to the opening declarations of `type_new_get_slots()`. No expressions or behavior changed. Focused GREEN passed (exit 0); all 57 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Snapshot verification confirmed only `cpython/Objects/typeobject.c` and that new test changed; all 11,461 other pre-existing paths preserved byte/mode-identically. `git diff --check` and `git -C cpython diff --check -- Objects/typeobject.c` both exited 0. + +Forced-fresh after-change probe: `mkdir -p build/cron-20261027-after-get-slots; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261027-after-get-slots/probe.log 2>&1` — exit 2; summary unchanged at `total=109 compiled=108 cached=0 skipped=0`. Former line-3185 errors cleared. First current errors are `typeobject.c(3219)` C2275 (`PyTypeObject`) and C2065 (`type`), with related C2223 at 3224; this distinct `type_new_slots_impl()` declaration family was left untouched. Capture: `build/cron-20261027-after-get-slots/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-get-slots-new-slots-c89.test.py`, and this status record. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only `type_new_slots_impl()`'s `type` declaration. No completed port is claimed. + +--- + +## `type_new_descriptors()` C89 loop-index slice (frontier advances) + +Date: 2026-10-21 06:08 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing modified/untracked work; no reset, clean, stash, discard, commit, push, or publication. Nested CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A forced-fresh VC6/Wine probe verified the prior `type_new_classmethod()` frontier had cleared and `_blake2/blake2s_impl.c` compiled. First stable errors were at `cpython/Objects/typeobject.c(3025)`, C2143 on the C99 `for (Py_ssize_t i...)` initializer and dependent undeclared `i`/syntax diagnostics. Exact command: `mkdir -p build/cron-20261024-frontier-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-frontier-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Capture: `build/cron-20261024-frontier-reprobe/probe.log`. + +The Hermes coding subagent provider was unavailable (Anthropic credentials missing); one authenticated Codex CLI fallback lane (`codex-cli 0.153.4`) followed strict TDD. New `scripts/vc6-typeobject-type-new-descriptors-index-c89.test.py` failed against unchanged source (RED exit 1; expected opening-local assertion), and a byte comparison confirmed `cpython/Objects/typeobject.c` remained unchanged before implementation. The sole production edit hoists `Py_ssize_t i;` into `type_new_descriptors()`'s opening declarations and reuses it in the loop initializer, preserving the loop bounds, increment, body, and behavior. Focused GREEN passed (exit 0); all 56 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). Preservation verification confirmed all 4,871 other snapshotted pre-existing paths byte-identical. Scoped nested and outer `git diff --check` both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261024-after-type-new-descriptors/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-after-type-new-descriptors/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-type-new-descriptors/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; the former line-3025 diagnostics cleared. First remaining stable blocker advances to `typeobject.c(3185)`, C2275 `PyObject` / C2065 `new_slots`, in `type_new_slots_impl()`; untouched. Subsequent diagnostics also remain untouched. Capture: `build/cron-20261024-after-type-new-descriptors/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-descriptors-index-c89.test.py`, and this status entry. This is compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only `type_new_slots_impl()`'s `new_slots` declaration. No completed port is claimed. + +--- + +## `type_new_staticmethod()` `static_func` C89 declaration slice (frontier advances) + +Date: 2026-10-24 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing modified and untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD and did not edit this status file. Before implementation, all 53 existing `scripts/vc6-typeobject-*.test.py` fixtures passed. New `scripts/vc6-typeobject-type-new-staticmethod-c89.test.py` failed against unchanged source (RED exit 1; expected assertion that `static_func` must be in the opening declaration block; `cmp` verified the C file unchanged). Minimal production edit hoists `PyObject *static_func;` into `type_new_staticmethod()`'s initial local declarations and changes the later initialized declaration to assignment at the same call point. Focused test passed (exit 0); all 54 typeobject fixtures passed (exit 0). Delegated `diff -u` verified only that declaration/assignment delta in `cpython/Objects/typeobject.c`; outer `git diff --check` and nested `git -C cpython diff --check -- Objects/typeobject.c` both exited 0. + +Forced-fresh pre-change VC6/Wine command: `mkdir -p build/cron-20261024-frontier/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-frontier/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors were `typeobject.c(2973)` C2275 (`PyObject`) and C2065 (`static_func`). After-change forced-fresh command: `mkdir -p build/cron-20261024-after-staticmethod/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-after-staticmethod/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-staticmethod/probe.log 2>&1` — exit 2; same summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The staticmethod diagnostics cleared. First remaining stable blocker is now `typeobject.c(3001)` C2275 (`PyObject`) and C2065 (`method`) in the following classmethod helper; left untouched. Full captures are in the two paths above. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-staticmethod-c89.test.py`, and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only the `type_new_classmethod()` `method` declaration. No completed port is claimed. + +--- + +## `type_new_set_doc()` `tp_doc` C89 declaration slice (frontier advances) + +Date: 2026-10-23 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing dirty/untracked changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh before-change VC6/Wine probe command: `mkdir -p build/cron-20261023-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261023-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261023-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics were `typeobject.c(2946)` C2143 (late `char *tp_doc`) and C2065 `tp_doc` at 2947. Capture: `build/cron-20261023-reprobe/probe.log`. + +One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD and did not edit this status file. New `scripts/vc6-typeobject-type-new-set-doc-tp-doc-c89.test.py` failed against unchanged production source (RED exit 1, expected opening-declaration assertion). The minimal production change declares `char *tp_doc;` with opening locals and changes the later initialized declaration into `tp_doc = (char *)PyObject_Malloc(size);` at the same point, preserving allocation order/control flow. Initial regression run found two directly related fixtures expecting the old layout; narrowly updated only those expectations. First corrected full rerun still exposed a mistaken extra `size` token in the size fixture's normalized expectation; removed only that extra token, then reran cleanly. The focused test passed (exit 0); all 53 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). `git diff --check` and `git -C cpython diff --check -- Objects/typeobject.c` both exited 0. Baseline snapshot check from the coding lane confirmed the other 123 pre-existing outer-repository files were unchanged before the two necessary fixture updates; PORT_STATUS remained untouched until this record. + +After-change forced-fresh probe: `mkdir -p build/cron-20261023-after-tp-doc/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261023-after-tp-doc/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261023-after-tp-doc/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `type_new_set_doc()` diagnostics at 2946/2947 cleared. First remaining stable errors are in the next function `type_new_staticmethod()` at `typeobject.c(2973)`, C2275 `PyObject` and C2065 `static_func`; left untouched. Capture: `build/cron-20261023-after-tp-doc/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-type-new-set-doc-tp-doc-c89.test.py`; narrowly updated `scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py` and `scripts/vc6-typeobject-type-new-set-doc-size-c89.test.py`; and this status entry. This is compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm, then isolate only `type_new_staticmethod()`'s `static_func` declaration family. No completed port is claimed. + +--- + +## `type_new_set_doc()` size declaration C89 slice (frontier advances) + +Date: 2026-10-20 UTC. The requested `/home/ubuntu/projects/python-win9x` checkout is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16/MSVC6 legacy reference. Preserved prior local work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A forced-fresh pre-change VC6/Wine probe disproved the older `_blake2/blake2s_impl.c` frontier: that source compiled. Exact command: `mkdir -p build/cron-20261023-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261023-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261023-reprobe/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`. First stable diagnostics were `typeobject.c(2944)` C2275/C2146/C2065 for late `Py_ssize_t size`; capture: `build/cron-20261023-reprobe/probe.log`. + +One focused coding-delegation attempt stopped because the existing `doc_str` regression expected the late initialized `size` declaration. Strict TDD was maintained: new `scripts/vc6-typeobject-type-new-set-doc-size-c89.test.py` failed against unchanged production source (RED exit 1; expected missing opening declaration). Updated only the directly related `scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py` expectation to require the hoisted declaration and its same-point assignment, then changed only `cpython/Objects/typeobject.c`: added `Py_ssize_t size;` to `type_new_set_doc()`'s opening declarations and changed `Py_ssize_t size = strlen(doc_str) + 1;` to `size = strlen(doc_str) + 1;` at the original execution point. Initial post-edit regression run exposed the old test's expected body needing that same narrow update; after updating it, all 52 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0), including both directly related tests. `git diff --check` and `git -C cpython diff --check -- Objects/typeobject.c` each exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261023-after-size/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261023-after-size/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261023-after-size/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `size` diagnostics cleared. First remaining stable diagnostic is `typeobject.c(2946)` C2143, followed by undeclared `tp_doc` at 2947: the later declaration `char *tp_doc` now follows the `size` assignment. Left untouched as a distinct declaration family. Capture: `build/cron-20261023-after-size/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-type-new-set-doc-size-c89.test.py`; narrowly updated `scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py`; and this status entry. This is compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: fresh confirm, then isolate only the `type_new_set_doc()` `tp_doc` declaration. No completed port is claimed. + +--- + +## `type_new_set_doc()` doc_str C89 declaration slice (frontier advances) + +Date: 2026-10-22 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change VC6/Wine probe command: `mkdir -p build/cron-20261022-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261022-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022-reprobe/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled. First stable diagnostics were `typeobject.c(2937)` C2143/C2065 for late `const char *doc_str`, with related declarations downstream. Exact capture: `build/cron-20261022-reprobe/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) applied strict TDD. New `scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py` failed against unchanged source as expected (RED exit 1). The only production change hoists `const char *doc_str;` to `type_new_set_doc()`'s opening declarations and changes the later initialized declaration to assignment at the original conversion point. Focused GREEN passed; all 51 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). Preservation verification confirmed all 121 pre-existing dirty/untracked paths byte-identical; only the intended production source and new test differ. `git diff --check` and `git -C cpython diff --check` both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261022-after-doc-str/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261022-after-doc-str/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022-after-doc-str/probe.log 2>&1` — exit 2. Former `doc_str` errors cleared; first diagnostics advance to `typeobject.c(2944)` C2275/C2146/C2065 for the distinct late `Py_ssize_t size` declaration in the same function; it remains untouched. Capture: `build/cron-20261022-after-doc-str/probe.log`. This is compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then isolate only the `type_new_set_doc()` `size` declaration family. No completed port is claimed. + +--- + +## Diagnostics-only: `type_new_set_module()` module local confirmed; regression fixture conflict + +Date: 2026-10-21 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved existing work; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced VC6/Wine probe disproved the older `_blake2/blake2s_impl.c` frontier: `_blake2/blake2s_impl.c` compiled successfully and the first stable diagnostic family is `cpython/Objects/typeobject.c(2872)`, C2275 (`PyObject` illegal use as an expression) and C2065 (`module` undeclared), in `type_new_set_module()`. Exact command: `mkdir -p build/cron-20261021-refresh/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-refresh/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First diagnostic capture: `build/cron-20261021-refresh/probe.log` (first errors at log lines 1266/1268). Baseline tag and commit commands both verified the values above. + +One focused coding lane was attempted: Hermes delegation was unavailable because the configured Anthropic provider has no credentials; authenticated `codex-cli 0.153.4` then inspected the target. It found the existing untracked regression `scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py` asserts the entire function body including the separate late `module` declaration. The coding lane stopped before edits to preserve all pre-existing local work. No production code or tests changed; no TDD test was run, and the frontier was not advanced. This record is the only path changed by this run. Next action: a narrowly scoped strict-TDD slice may update that directly affected regression expectation together with a new/focused test and the `module` declaration, while preserving unrelated local changes; alternatively remain diagnostics-only if safe isolation cannot be guaranteed. Compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. No completed port is claimed. + +--- + +## `type_new_set_module()` globals declaration C89 slice (frontier advances) + +Date: 2026-10-21 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the legacy-toolchain CPython 3.11.16/MSVC6 reference before work. Preserved all pre-existing changes; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh pre-change forced VC6/Wine probe confirmed the recorded `type_new_set_module()` globals frontier. Command: `mkdir -p build/cron-20261021-frontier-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-frontier-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-frontier-reprobe/probe.log 2>&1` — exit 2; first stable diagnostics `typeobject.c(2866)` C2275/C2065 for late `PyObject *globals`; distinct `module` declaration diagnostics at 2871 follow. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD. New `scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py` failed against unchanged source (RED exit 1, expected opening-declaration assertion). The sole production change hoists `PyObject *globals;` into the opening block and converts its later initialized declaration into assignment at the same evaluation point. The distinct `module` declaration and all control flow remain unchanged. Focused GREEN passed; all 49 `scripts/vc6-typeobject-*.test.py` regressions passed. Snapshot verification confirmed the exact source delta and all 4,864 other snapshotted pre-existing files unchanged. Outer and nested `git diff --check` both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261021-after-globals/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-after-globals/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-after-globals/probe.log 2>&1` — exit 2. The former globals diagnostics cleared; first remaining diagnostic family advances to `typeobject.c(2872)` C2275/C2065 for the separate `PyObject *module` declaration, left untouched. Additional later diagnostics begin at line 2936. Probe output is captured in the two directories above. Compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py`, and this status entry. Next frontier: force-fresh confirm and handle only the separate `module` declaration family. No completed port is claimed. + +--- + +## Diagnostics-only: `type_new_set_module()` globals frontier confirmed; coding delegation unavailable + +Date: 2026-10-20 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the active-profile CPython 3.11.16/Win9x/MSVC6 reference before acting. Preserved all existing modifications and untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change probe command: `mkdir -p /home/ubuntu/r build/cron-20261020-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261020-current-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics are `typeobject.c(2866)` C2275 (`PyObject` illegal use as expression) and C2065 (`globals` undeclared), then separate C2275/C2065 at line 2871 for `module`. Full capture: `build/cron-20261020-current-reprobe/probe.log`. + +Attempted the required single focused coding-subagent lane, but delegation could not start: configured Anthropic provider has no credentials. Following the delegation fallback guidance, did not substitute an unrequested/unauthenticated external coding CLI. Consequently no implementation or tests were changed; do not treat the frontier as advanced. This run is diagnostics-only. No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Files changed this run: `PORT_STATUS.md` only. Next frontier: strict-TDD fix only the `globals` declaration in `type_new_set_module()` when an approved coding lane is available; leave the separate `module` declaration untouched. No completed port is claimed. + +--- + +## `type_new_alloc()` heap-type local C89 slice (frontier advances) + +Date: 2026-10-20 06:08 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing modified/untracked work; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `type_new_alloc()` frontier was re-probed before changes. Exact command: `mkdir -p build/cron-20261020-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261020-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261020-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors: `typeobject.c(2802)` C2275 (`PyHeapTypeObject`) and C2065 (`et`), with subsequent C2223 consequences. Capture: `build/cron-20261020-reprobe/probe.log`. + +One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD, preserving pre-existing changes and not editing this status file. New `scripts/vc6-typeobject-type-new-alloc-heap-type-c89.test.py` failed against unchanged production source (RED exit 1; expected opening-declaration assertion). The single production change declares `PyHeapTypeObject *et;` in the opening local block and assigns the cast to `et` at its original point after the `type == NULL` check, preserving allocation and validation order. Focused regression passed (exit 0); all 48 `scripts/vc6-typeobject-*.test.py` tests passed (suite exit 0). Independent snapshot/diff verification confirmed the complete source delta is just this declaration/assignment adjustment, the only new path is the focused test, and all 247 other pre-existing modified/untracked files remained byte-identical. Outer and nested `git diff --check` both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261020-after-type-new-alloc/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261020-after-type-new-alloc/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261020-after-type-new-alloc/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `typeobject.c` compiled. The former line-2802 diagnostics are gone. First remaining stable errors advance to `typeobject.c(2866)` C2275/C2065 for late `PyObject *globals` in `type_new_set_module()`, then the distinct `module` declaration at 2871; both untouched. Capture: `build/cron-20261020-after-type-new-alloc/probe.log`. Wine emitted a long AF_UNIX socket-path warning because the repository-local runtime path exceeds 108 bytes; compilation continued through all 108 units and captured diagnostics. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-alloc-heap-type-c89.test.py`, and this status entry. Next frontier: isolate only `type_new_set_module()`'s first `globals` declaration at line 2866 after fresh confirmation. No completed port is claimed. + +--- + +## `type_new_slots_impl()` C89 local declaration slice (frontier advances) + +Date: 2026-10-20 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before work. Preserved all pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. The earlier recorded `_blake2/blake2s_impl.c` frontier was stale: forced-fresh probing compiled that file and first stopped at `type_new_slots_impl()` in `cpython/Objects/typeobject.c` line 2746, C2275 on late `PyObject *new_slots`. CPython baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) used strict TDD. New `scripts/vc6-typeobject-type-new-slots-impl-c89.test.py` failed against unchanged source (RED exit 1, expected opening-declaration assertion); a byte comparison confirmed `cpython/Objects/typeobject.c` unchanged before implementation. The minimal source change hoists `PyObject *new_slots;` into the function's opening declaration block and changes the later initialized declaration to assignment at its original evaluation point. The focused test passed, and all 47 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). The delegation snapshot check confirmed all 246 other pre-existing dirty/untracked files remained byte-identical. Nested and outer scoped `git diff --check` both exited 0. + +Forced-fresh before-change command: `mkdir -p build/cron-run-frontier/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-run-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-run-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic: `typeobject.c(2746)` C2275 (`PyObject` illegal use as an expression). Capture: `build/cron-run-frontier/probe.log`. + +After-change forced-fresh command: `mkdir -p build/cron-run-after-slots-impl/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-run-after-slots-impl/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-run-after-slots-impl/probe.log 2>&1` — actual probe exit 2; same summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The line-2746 diagnostics are gone; first remaining blocker advances to `typeobject.c(2802)` C2275 (`PyHeapTypeObject`), left untouched. Capture: `build/cron-run-after-slots-impl/probe.log`. This is compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-slots-impl-c89.test.py`, and this status record. Next frontier: force-fresh confirm and isolate only the current `typeobject.c(2802)` declaration family. No completed port is claimed. + +--- + +## `type_new_slots_bases()` C89 loop-index slice (frontier advances) + +Date: 2026-10-19 23:32 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile `python-3-win9x-msvc6.md` reference before acting. Preserved all existing outer and detached CPython work. No reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior recorded `type_new_copy_slots()` frontier had already cleared. Forced-fresh VC6/Wine probe confirmed `_blake2/blake2s_impl.c` compiled and the first current blocker was `type_new_slots_bases()` line 2698: C2143 on the C99 `for (Py_ssize_t i = 0; ...)` declaration. The first attempted invocation did not run because its log directory had not been created (redirection exit 1); retried with the capture directory present. Successful pre-change command: `mkdir -p /home/ubuntu/r build/cron-20261019-fresh-frontier; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-fresh-frontier/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Capture: `build/cron-20261019-fresh-frontier/probe.log`. + +One authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD, without touching status or committing. New `scripts/vc6-typeobject-type-new-slots-bases-index-c89.test.py` failed against the unchanged production source (RED exit 1, expected assertion that the loop index must be declared before statements). The minimal source change declares `Py_ssize_t i;` after `nbases` and reuses it in `for (i = 0; ...)`, preserving bounds, body, and flow. Parent independently reran the focused regression (exit 0) and all 45 `scripts/vc6-typeobject-*.test.py` tests (exit 0). `git -C cpython diff --check -- Objects/typeobject.c` and a trailing-whitespace/newline check on the new test passed (exit 0). The delegated lane's `git diff --no-index --check` for the untracked test returned 1 because `--no-index` signals file difference; no whitespace diagnostics were emitted. Source comparison to its immediate pre-lane snapshot showed only the intended function-local C89 delta. + +After-change forced-fresh command: `mkdir -p /home/ubuntu/r build/cron-20261019-after-slots-bases-index; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-after-slots-bases-index/probe.log 2>&1` — probe exit 2; same summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-2698 loop errors are gone. First remaining diagnostics are `typeobject.c(2705)` C2143 on the distinct `PyTypeObject *base` late declaration, then C2065 `base` at 2708 and consequent C2223 diagnostics at 2708/2713; left untouched. Capture: `build/cron-20261019-after-slots-bases-index/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-slots-bases-index-c89.test.py`, and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only the `type_new_slots_bases()` `base` declaration at line 2705. No completed port is claimed. + +--- + +## `type_new_visit_slots()` C89 loop-index slice (frontier advances) + +Date: 2026-10-19 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved all existing local changes. No reset, clean, stash, discard, commit, push, or publication. CPython baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Hermes coding delegation was unavailable (Anthropic credentials missing). One authenticated Codex CLI lane inspected the actual function and stopped without edits because it found no preexisting loop-index local to safely reuse. A fresh forced VC6/Wine probe reconfirmed the frontier at `type_new_visit_slots()` line 2583: C2143 on `for (Py_ssize_t i...)`, cascading C2065 `i`; `_blake2/blake2s_impl.c` compiled. Probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Capture: `build/cron-current-reprobe/probe.log`. + +Implemented the narrow C89 fix directly under strict TDD. New regression `scripts/vc6-typeobject-type-new-visit-slots-index-c89.test.py` was created and run against unchanged production source (RED exit 1 at the expected missing function-scope `i` assertion). The minimal production edit declares `Py_ssize_t i;` with `type_new_visit_slots()` locals and changes only the loop initializer to `i = 0`, preserving bound, increment, body, and behavior. Focused regression passed (exit 0); all 43 `scripts/vc6-typeobject-*.test.py` tests passed (suite exit 0). Nested `git diff --check -- Objects/typeobject.c` and outer check for the new regression both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-after-type-new-visit-slots/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-after-type-new-visit-slots/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-after-type-new-visit-slots/probe.log 2>&1` — exit 2; same summary `total=109 compiled=108 cached=0 skipped=0`. The former line-2583 errors are gone; first remaining error is `typeobject.c(2630)` C2275/C2146/C2065 for the distinct `Py_ssize_t j` declaration in `type_new_copy_slots()`, with a separate loop-index error there. Full capture: `build/cron-after-type-new-visit-slots/probe.log`. This is compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-visit-slots-index-c89.test.py`, and this status entry. Next frontier: force-fresh confirm and isolate only the `type_new_copy_slots()` line-2630 `j` declaration family. No completed port is claimed. + +--- + +## `best_base()` `base_i` C89 declaration slice (frontier advances) + +Date: 2026-10-19 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the profile CPython Win9x/MSVC6 reference before work. Preserved all pre-existing local changes; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A forced-fresh pre-change VC6/Wine probe confirmed the status-recorded `base_i` frontier. Exact command: `mkdir -p build/cron-20261019-frontier-refresh/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-frontier-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-frontier-refresh/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors were `typeobject.c(2226)` C2275 (`PyTypeObject`) and C2065 (`base_i`), followed by C2223 consequences at 2228/2235. Source inspection confirmed this declaration belongs to `best_base()`, not `mro_check()`. + +Hermes coding delegation could not start because Anthropic credentials are unavailable. One authenticated Codex CLI lane (`codex-cli 0.153.4`, `codex exec --sandbox workspace-write --ephemeral`) applied strict TDD. New `scripts/vc6-typeobject-best-base-base-i-c89.test.py` failed against unchanged production source (RED exit 1, expected declaration-placement assertion); `cmp` against the pre-edit `typeobject.c` snapshot exited 0. The single production change declares `PyTypeObject *base_i;` at the beginning of the loop body and assigns the cast only after successful `PyType_Check(base_proto)`, preserving validation and cast timing. The focused test passed (exit 0); all 42 `scripts/vc6-typeobject-*.test.py` tests passed individually (suite exit 0). A SHA-256 preservation check confirmed that only `cpython/Objects/typeobject.c` and the new regression test differ from the pre-lane snapshot; every other existing file, including this status file, was byte-identical. Scoped nested and outer `git diff --check` both exited 0. No commit or publication. + +After-change forced-fresh probe command: `mkdir -p build/cron-20261019-after-best-base/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-after-best-base/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-after-best-base/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The original `best_base()` errors at lines 2226/2228/2235 are gone; first remaining `typeobject.c` diagnostics are at line 2583 (C2143/C2065 loop-index family), followed by separate C89 declaration families at lines 2629 and beyond. The compiler capture also logs a too-long repository-local Wine socket path warning during some units, but completes 108 compilations and the `typeobject.c` diagnostics are reliable. Full capture: `build/cron-20261019-after-best-base/probe.log`. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: force-fresh isolate the first line-2583 defect family. No completed port is claimed. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-best-base-base-i-c89.test.py`, and this status entry. + +--- + +## Current frontier refreshed: `mro_check()` `base_i` declaration + +Date: 2026-10-19 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Before diagnostics, read this status, `README.md`, and the profile CPython Win9x/MSVC6 reference. Preserved all pre-existing dirty/untracked work. No reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded `mro_check()` `base_i` frontier remains current. Two forced-fresh VC6/Wine invocations ran with `VC6_FRONTIER_FORCE=1` and repository-local `XDG_RUNTIME_DIR`; both exited 2 during compilation. In both, `_blake2/blake2s_impl.c` had already compiled, and first stable diagnostics were `typeobject.c(2226)` C2275 (`PyTypeObject`) and C2065 (`base_i`), followed by C2223 consequences at lines 2228/2235. Captures: `build/cron-20261019-blake2-reprobe/probe.log` and `build/cron-20261019-basei-red/probe.log`. Summary in each: `total=109 compiled=108 cached=0 skipped=0`. + +Implementation was not started in this run; no source or regression test was changed. The available compiler-probe frontier is precisely this C89 `base_i` declaration within `mro_check()`. Next action: one focused strict-TDD slice for `base_i` only, using the single-lane coding delegation workflow. Current state is compiler-probe progress only: there is no linked `pythoncore`/`python.exe`, no Wine interpreter execution, and no real Windows 98 SE execution. No completed port is claimed. + +--- + +## `mro_check()` base local C89 slice (frontier advances) + +Date: 2026-10-19 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` was absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved all existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261019-mro-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-mro-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-mro-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors were `typeobject.c(2072)` C2275 (`PyTypeObject`) and C2065 (`base`), followed by C2223 at line 2078. + +One focused Codex CLI coding lane (`codex-cli 0.153.4`, workspace-write/ephemeral) performed a strict-TDD slice after Hermes delegation was unavailable (Anthropic credentials absent). New `scripts/vc6-typeobject-mro-check-c89.test.py` failed against unchanged source as expected (RED exit 1), asserting that `base` must be declared before statements in the loop. The only production change declares `PyTypeObject *base;` before the type-check and assigns `(PyTypeObject*)obj` after successful `PyType_Check(obj)`, preserving cast/validation timing. Focused test passed; all 41 `scripts/vc6-typeobject-*.test.py` tests passed. Scoped nested and outer `git diff --check` passed. Preservation verification reports all 240 other pre-existing dirty/untracked files byte-identical; exact delta and checks are captured under `build/cron-20261019-after-mro-check/`. + +After-change forced-fresh command: `mkdir -p build/cron-20261019-after-mro-check/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-after-mro-check/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-after-mro-check/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-2072 errors are gone; first remaining diagnostics advance to `typeobject.c(2226)` C2275/C2065 for `base_i`, with C2223 consequences at lines 2228/2235. Full capture: `build/cron-20261019-after-mro-check/probe.log`. Compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter run, or real Windows 98 SE execution. Files changed by the slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-mro-check-c89.test.py`, and this status entry. Next frontier: isolate only the verified `base_i` declaration family after fresh confirmation. No completed port is claimed. + +--- + +## Diagnostics-only: recorded MRO frontier is stale; current first blocker is `mro_check()` + +Date: 2026-10-19 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing local work; no reset, clean, stash, discard, commit, push, or publication. CPython remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `mro_implementation()` line-2072 frontier was not current: that line is now in `mro_check()`, and the declarations at `mro_implementation()` lines 1964 and 2015 are block-leading declarations, not the first current blocker. Existing fresh captures `build/cron-20261019-verify-frontier/probe.log` and `build/cron-20261019-after-result/probe.log` both showed the first stable diagnostic at `typeobject.c(2072)`, C2275 (`PyTypeObject`) and C2065 (`base`), followed by cascading C2223 at 2078. The requested coding delegation provider was unavailable (no Anthropic credentials); its authenticated Codex CLI fallback independently confirmed that the blocker is outside the requested function. No source or regression test was changed. + +The exact proposed after-change probe command first failed before compilation with exit 1 due Wine socket setup (`sock_init: ERROR in sock_check_pollhup()`; wineserver lock creation returned read-only filesystem). Retried with a short repository-local runtime directory. Exact successful fresh diagnostic command: `mkdir -p build/cron-20261019-final-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-final-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-final-reprobe/probe.log 2>&1` — exit 2. The source-list frontier summary is `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics remain `typeobject.c(2072)` C2275/C2065 for `PyTypeObject *base` in `mro_check()`, with downstream C2223; subsequent independent diagnostics include `typeobject.c(2225)`. Full capture: `build/cron-20261019-final-reprobe/probe.log`. + +All 40 `scripts/vc6-typeobject-*.test.py` regressions passed individually (exit 0), captured in `build/codex-mro-diagnostics/typeobject-tests.log`. Preservation snapshot verified all 241 pre-existing modified/untracked files remained byte-identical before this status entry. Files changed by this run: this `PORT_STATUS.md` record only; no compatibility code or tests. Next step is a new narrowly scoped C89 slice for the actual `mro_check()` line-2072 declaration, after re-scoping task to that function; do not modify the unrelated `mro_implementation()` declarations. This remains compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution. No completed port is claimed. + +--- + +## `mro_implementation()` slow-path result declaration C89 slice (frontier advances) + +Date: 2026-10-19 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile reference `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved pre-existing work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified unchanged: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh before-change VC6/Wine probe confirmed the prior population-loop index fix and identified `mro_implementation()` line 2019 `PyObject *result` declaration as the first stable blocker. Exact command: `mkdir -p build/cron-20261019-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-current-reprobe/probe.log 2>&1` — exit 2. `_blake2/blake2s_impl.c` compiled; initial diagnostic family was C2275/C2065 at line 2019 (`PyObject`/`result`). Full capture: `build/cron-20261019-current-reprobe/probe.log`. + +One focused Codex CLI lane (`codex-cli 0.153.4`, `codex exec --sandbox workspace-write --ephemeral`) followed strict TDD. New `scripts/vc6-typeobject-mro-implementation-result-c89.test.py` failed against unchanged production source (RED exit 1, expected missing function-entry declaration assertion); the source remained unchanged before RED. The only production edit adds `PyObject *result;` to `mro_implementation()`'s opening declarations and changes the later initialized declaration to `result = PyList_New(1);` at its original evaluation point. The fast-path tuple allocation remains distinct and unchanged. The initial all-typeobject regression run exposed six tests asserting the prior declaration block; their fixtures were narrowly updated to include the new hoisted local and the updated allocation expression. Final focused test passed; all 40 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Preservation verification confirmed exactly the intended source delta and all 239 other prior modified/untracked files byte-identical, including the prior contents of `PORT_STATUS.md`. + +After-change forced-fresh probe: `mkdir -p build/cron-20261019-after-result/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-after-result/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-after-result/probe.log 2>&1` — exit 2. The line-2019 `result` diagnostics are gone; first remaining diagnostics advance to `typeobject.c(2072)` C2275 (`PyTypeObject`) and C2065 (`base`), with consequent C2223 at line 2078. Full capture: `build/cron-20261019-after-result/probe.log`. Scoped nested and outer `git diff --check` both exited 0. No `pythoncore`/`python.exe` link, Wine interpreter run, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed in this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-mro-implementation-result-c89.test.py`; narrowly adjusted six directly related MRO implementation tests (`bases`, `fast-path-index`, `index`, `merge-index`, `n`, and `to-merge`); and this status entry. Next frontier: force-fresh confirm, then isolate only the `typeobject.c(2072)` `base` declaration family. No completed port is claimed. + +--- + +## `mro_implementation()` population-loop C89 index slice (frontier advances) + +Date: 2026-10-19 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified unchanged: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior recorded frontier was force-fresh confirmed. Before-change command: `mkdir -p build/cron-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-reprobe/probe.log 2>&1` — exit 2. `_blake2/blake2s_impl.c` compiled; first stable diagnostic was `typeobject.c(2013)` C2143 on the C99 `for (Py_ssize_t i = 0; ...)` population-loop initializer. The pre-existing function-scope `i` permits reusing the index. One focused authenticated Codex CLI lane (`codex exec`, workspace-write/ephemeral; configured Anthropic delegation unavailable) followed strict TDD. New `scripts/vc6-typeobject-mro-implementation-population-index-c89.test.py` failed against unchanged production source (RED exit 1 with its expected loop-index assertion); `cmp` against the pre-edit `typeobject.c` snapshot exited 0. The sole production edit changes the loop initializer to `for (i = 0; ...)`, preserving loop bounds/body and initialization. All 39 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). A preservation check verified all 238 other pre-existing modified/untracked files unchanged and `typeobject.c` differs only by the intended one-line edit. + +After-change forced-fresh probe: `mkdir -p build/cron-after-mro-population-index/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-after-mro-population-index/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-after-mro-population-index/probe.log 2>&1` — exit 2. `_blake2/blake2s_impl.c` compiled; former line-2013 C2143 is gone. First remaining stable diagnostics advance to `typeobject.c(2019)` C2275/C2065 for the separate `PyObject *result` declaration; untouched. Full capture: `build/cron-after-mro-population-index/probe.log`. `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- PORT_STATUS.md scripts/vc6-typeobject-mro-implementation-population-index-c89.test.py` exited 0. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-mro-implementation-population-index-c89.test.py`, and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirmation and isolate only the `typeobject.c(2019)` result declaration. No completed port is claimed. + +--- + +## MRO implementation merge-loop index: fresh confirmation only; coding lane unavailable + +Date: 2026-10-18 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and searched for the specified CPython Win9x/MSVC6 reference; that file was unavailable in the workspace. Preserved all existing tracked modifications and untracked files. No reset, clean, stash, discard, commit, push, or publication. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `to_merge` fix remains effective. A forced-fresh VC6/Wine probe compiled `_blake2/blake2s_impl.c` and advanced to the distinct C99 loop-index declaration at `typeobject.c(2013)` in `mro_implementation()`. Command: `mkdir -p build/cron-current-refresh/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-refresh/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; first diagnostic family C2143 at line 2013, with cascading C2143/C2059; next independent error at line 2019 (`result`) left untouched. Full capture: `build/cron-current-refresh/probe.log`. + +One focused implementation delegation was attempted but the configured Anthropic provider could not start due to missing credentials. The authenticated Codex CLI was started as the single fallback lane; it did not provide results during this run, so no production or test files were changed. Independently ran all 37 `scripts/vc6-typeobject-*.test.py` tests; all passed (exit 0). Nested `git diff --check -- Objects/typeobject.c` passed (exit 0). + +Files changed this run: `PORT_STATUS.md` only. This is diagnostic progress; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: strict-TDD isolated C89 fix for only the `mro_implementation()` line-2013 loop index, using the actual compiler evidence above. No completed port is claimed. + +--- + +## `mro_implementation()` `to_merge` C89 declaration slice (frontier advances) + +Date: 2026-10-18 UTC. The instructed checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved pre-existing dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified unchanged at `v3.11.16`, `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced probe confirmed the recorded `mro_implementation()` frontier: `_blake2/blake2s_impl.c` compiled; first stable errors were `typeobject.c(2006)` C2275/C2065/C2100 on late `PyObject **to_merge`. Before-change command: `mkdir -p build/cron-current-refresh/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-refresh/probe.log 2>&1` — probe exit 2, summary `total=109 compiled=108 cached=0 skipped=0`. + +One focused Codex CLI implementation lane used strict TDD. New `scripts/vc6-typeobject-mro-implementation-to-merge-c89.test.py` failed against unchanged production source (RED exit 1; expected opening-declaration assertion). The only production change adds `PyObject **to_merge;` to the opening declaration block and turns its allocation declaration into assignment at its original point after duplicate validation. Allocation/error handling order is unchanged. Four existing focused MRO declaration tests required narrow expected-block updates for the additional hoisted local; their semantic assertions were retained. Focused test and all 37 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). Applicable outer and nested `git diff --check` passed (exit 0). + +After-change forced-fresh command: `mkdir -p build/cron-after-to-merge/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-after-to-merge/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-after-to-merge/probe.log 2>&1` — probe exit 2, same summary; the former line-2006 errors are gone. First remaining diagnostic is C2143 at `typeobject.c(2013)` for a separate C99 loop index, left untouched. Full capture: `build/cron-after-to-merge/probe.log`. No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-mro-implementation-to-merge-c89.test.py`; narrowly adjusted `scripts/vc6-typeobject-mro-implementation-bases-c89.test.py`, `scripts/vc6-typeobject-mro-implementation-fast-path-index-c89.test.py`, `scripts/vc6-typeobject-mro-implementation-index-c89.test.py`, and `scripts/vc6-typeobject-mro-implementation-n-c89.test.py`; and this status entry. Next frontier: force-fresh confirmation, then isolate only the `typeobject.c(2013)` loop-index family. No completed port is claimed. + +--- + + +Date: 2026-10-18 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` does not exist; used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and active-profile reference `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved pre-existing dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced probe established the prior `_blake2/blake2s_impl.c` frontier had advanced: that file compiled, and the first current stable blocker was the second C99 loop-index declaration in `mro_implementation()` at `typeobject.c(1985)`, C2143. One focused Codex CLI implementation lane (`codex-cli 0.153.4`, authenticated ChatGPT, `--sandbox workspace-write --ephemeral`) followed strict TDD after Hermes delegation was unavailable (Anthropic credentials missing). New regression `scripts/vc6-typeobject-mro-implementation-fast-path-index-c89.test.py` failed against unchanged source (RED exit 1, expected C89 declaration assertion); `cmp` of `cpython/Objects/typeobject.c` against its pre-edit snapshot exited 0. The minimal production change reuses existing function-scope `i` in the single-base fast-path loop, preserving initialization timing, bounds, increment, and body. No other blocker was changed. + +Exact verification: +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change command: `mkdir -p build/cron-20261018-latest-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-latest-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-latest-reprobe/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First compiler diagnostic: `typeobject.c(1985)` C2143 on the second loop-index declaration. Capture: `build/cron-20261018-latest-reprobe/probe.log`. +- TDD RED: new focused test before production edit — exit 1, expected assertion that fast-path loop must reuse function-scope `i`; source `cmp` against snapshot — exit 0. +- GREEN/regressions: focused test — exit 0. `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test"; ...; done` — exit 0; all 36 typeobject tests passed. +- After-change forced-fresh command: `mkdir -p build/cron-20261018-after-mro-fast-index/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-mro-fast-index/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-mro-fast-index/probe.log 2>&1` — exit 2; same summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-1985 diagnostics are gone. First remaining diagnostic is `typeobject.c(2006)` C2275/C2065/C2100 on the separate `PyObject **to_merge` declaration; untouched. Capture: `build/cron-20261018-after-mro-fast-index/probe.log`. +- Preservation verification: SHA-256/mode snapshot confirmed exactly the production source and new focused regression changed; all 11,374 other pre-existing files remained byte-identical, including this status file, at implementation verification. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c` (one loop-index declaration removal/reuse), new `scripts/vc6-typeobject-mro-implementation-fast-path-index-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then isolate only the `to_merge` declaration at `typeobject.c(2006)`. No completed port is claimed. + +--- + +## First mro_implementation loop-index C89 slice + +Date: 2026-10-18 UTC. Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read this status, `README.md`, and the active-profile `python-3-win9x-msvc6.md` reference. Preserved existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded MRO declaration frontier required fresh confirmation. The first attempt used an overly long project-local Wine runtime path and exited 2 before compiler diagnostics (`socket path ... exceeds 108 bytes`); the successful fresh retry used `XDG_RUNTIME_DIR="$PWD/build/r1/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/r1/probe.log 2>&1` and exited 2 at `mro_implementation()` line 1960: C2143 for the first C99 loop index declaration `for (Py_ssize_t i = 0; ...)`. `_blake2/blake2s_impl.c` passed; summary `total=109 compiled=108 cached=0 skipped=0`. A single authenticated Codex CLI lane (`codex-cli 0.153.4`, OpenAI) implemented only this frontier using strict TDD. New focused test was run against unchanged production source and failed as expected (RED exit 1); production byte comparison was unchanged (exit 0). The minimal source change hoisted `Py_ssize_t i;` to `mro_implementation()`'s opening declarations and retained `i = 0` in the original loop initializer. Existing declaration-order expectations in two directly related tests were narrowly updated. The focused test and all 35 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). Snapshot verification covered 235 pre-existing modified/untracked files and passed; exact production delta was independently compared and passed. Root and nested `git diff --check` both returned 0. A supplementary `git diff --no-index --check /dev/null ` returned 1 because `--no-index` signals the new-file difference despite empty diagnostics; do not interpret that as a whitespace failure. + +After-change forced-fresh probe command: `mkdir -p build/r2/runtime; XDG_RUNTIME_DIR="$PWD/build/r2/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/r2/probe.log 2>&1` — exit 2, summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-1960 diagnostics are gone. First remaining stable diagnostic family advances to `mro_implementation()` line 1985, the second C99 loop-index declaration (`for (Py_ssize_t i = 0; i < k; i++)`); left untouched. Full capture: `build/r2/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-mro-implementation-index-c89.test.py`; narrowly updated `scripts/vc6-typeobject-mro-implementation-bases-c89.test.py` and `scripts/vc6-typeobject-mro-implementation-n-c89.test.py`; and this status entry. This is compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm, then isolate only the second `mro_implementation()` loop declaration at line 1985. No completed port is claimed. + +--- + +## Diagnostics-only run: MRO declaration frontier confirmed; implementation delegation unavailable + +Date: 2026-10-18 UTC. Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read this status, `README.md`, and attempted the relevant legacy-toolchain reference lookup; `references/python-3-win9x-msvc6.md` was unavailable in the workspace. Preserved all existing dirty/untracked work. No reset, clean, stash, discard, commit, push, or publication. CPython remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The old `_blake2/blake2s_impl.c` frontier is not active: forced-fresh MSVC600/Wine probe compiled `_blake2/blake2s_impl.c` and advanced to `typeobject.c(1958)`. Probe command: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First diagnostics: C2275/C2146/C2065 at line 1958 for late `Py_ssize_t n`; subsequent C2143/C2065/C2059 at line 1959 are the separate C99 loop index `i`. Additional later MRO errors remain untouched. Full capture: `build/cron-20261018-current-reprobe/probe.log`. + +Attempted the required single focused coding delegation for only the first declaration family; delegation could not start because the configured Anthropic provider lacks credentials. No production or regression-test changes were made. Applicable regression diagnostics: all 33 `scripts/vc6-typeobject-*.test.py` passed (command loop exit 0). Baseline tag and commit rechecked unchanged. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Compiler-probe progress only. + +Files changed this run: `PORT_STATUS.md` only; compiler capture is under `build/cron-20261018-current-reprobe/`. Next frontier: perform one strict-TDD slice for only the `typeobject.c(1958)` `n` declaration when an approved coding delegation provider is available; leave `i` and subsequent families separate. No completed port is claimed. + +--- + +## vectorcall_maybe() C89 declaration slice (frontier advances) + +Date: 2026-10-18 UTC. Existing checkout used: `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read the status, README, and the legacy-toolchain reference lookup was attempted but the file was unavailable at both expected locations (`/home/ubuntu/.hermes/profiles/maxwell/skills/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` and workspace `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`). Existing dirty/untracked work preserved. No reset, clean, stash, discard, commit, push, or publication. CPython baseline: `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, OpenAI, workspace-write/ephemeral) followed strict TDD. Fresh pre-edit forced probe reconfirmed `vectorcall_maybe()` as first stable frontier; `_blake2/blake2s_impl.c` compiled, followed by C2143 at `typeobject.c(1719)` and cascading declaration diagnostics. New focused test failed against unchanged production source (exit 1, expected opening declaration assertion). The only source change hoists `int unbound`, `self`, `func`, and `retval`; assignments remain at original evaluation points, and lookup failure control flow is unchanged. Focused GREEN and all 32 `scripts/vc6-typeobject-*.test.py` scripts passed (exit 0). The implementation lane independently compared the full `typeobject.c` against its pre-edit snapshot and confirmed its source delta is confined to this function. + +Exact probe records: +- Before: `mkdir -p build/cron-20261018-reprobe-blake/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-reprobe-blake/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-reprobe-blake/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; first errors at `typeobject.c(1719)` C2143, then C2275/C2065 for declarations at 1720–1727. Capture: `build/cron-20261018-reprobe-blake/probe.log`. +- After: `mkdir -p build/cron-20261018-after-vectorcall-maybe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-vectorcall-maybe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-vectorcall-maybe/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; all prior `vectorcall_maybe()` diagnostics cleared. First remaining errors advance to `typeobject.c(1956)` in a separate MRO declaration family (`bases`, `n`, C99 loop index); untouched. Capture: `build/cron-20261018-after-vectorcall-maybe/probe.log`. + +No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE test occurred. This is compiler-probe progress only. Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-vectorcall-maybe-c89.test.py`, and this status record. Next frontier: force-fresh confirm the first `typeobject.c(1956)` declaration family before selecting a single narrow follow-up. No completed port is claimed. + +--- + +## vectorcall_method() C89 declaration slice (frontier advances) + +Date: 2026-10-18 UTC. Baseline: CPython `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c8782608a4549` (verified with `git -C cpython describe --tags --exact-match HEAD` and `git -C cpython rev-parse HEAD`, exit 0). Parent-reported before probe found first stable diagnostics at `typeobject.c` lines 1694+ (C2143 late declaration and cascade). + +Strict TDD: added the focused script before changing source. `python3 scripts/vc6-typeobject-vectorcall-method-c89.test.py` returned exit 1 (RED), with `AssertionError: vectorcall_method: all locals must precede assert in the opening declaration block (C89)`. Hoisted only this function's local declarations; initializer assignments remain at their original evaluation points, preserving executable statement order and behavior. The same command then returned exit 0 (GREEN), output `vectorcall_method C89 declarations and unchanged assignment/evaluation/control flow: PASS`. + +`for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` returned exit 0; all 31 scripts passed (27 PASS output lines; four silent successes). Exact changed paths: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-vectorcall-method-c89.test.py`, and `PORT_STATUS.md` (this prepended record only). Post-slice forced-fresh probe command: `mkdir -p build/cron-20261018-after-vectorcall-method; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-vectorcall-method/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`, `_blake2/blake2s_impl.c` compiled. The prior `vectorcall_method()` diagnostics cleared; first blocker now advances to `vectorcall_maybe()` at `typeobject.c(1719)` C2143, with cascade through its late local declarations. Capture: `build/cron-20261018-after-vectorcall-method/probe.log`. No pythoncore/python.exe link, Wine interpreter execution, or Windows 98 SE runtime test occurred. This is compiler-probe progress only; no completed port is claimed. + +--- + +## Latest verified slice (`subtype_dealloc()` GC-branch `type_needs_decref`; frontier advances) + +Date: 2026-10-18 01:28 UTC + +Used existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before work. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior non-GC `type_needs_decref` fix was force-fresh confirmed; the first diagnostics were the distinct GC-branch C2143 at `typeobject.c(1486)` and consequent C2065 at line 1496. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, `--sandbox workspace-write --ephemeral`) used strict TDD. New `scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py` failed against unchanged production source (exit 1) because the GC path's declaration remained after statements. The only production change hoists `int type_needs_decref;` to `subtype_dealloc()`'s opening declaration block and changes the GC-path initialized declaration to assignment at the same original evaluation point. The non-GC branch, evaluation order, and control flow are unchanged. The agent corrected a test fixture's escaped-backslash issue, reran RED against a saved pre-edit source, and verified GREEN. All pre-existing paths and this status file were preserved during the delegated lane. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261018-gc-type-needs-decref-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-gc-type-needs-decref-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-gc-type-needs-decref-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(1486)` C2143 and `(1496)` C2065 `type_needs_decref`. Capture: `build/cron-20261018-gc-type-needs-decref-reprobe/probe.log`. +- TDD RED: focused regression against unchanged source — exit 1 on the expected missing function-entry declaration. GREEN: `python3 scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py` — exit 0. +- Regressions: `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" >/dev/null || exit 1; done` — exit 0; all 29 passed. Scoped `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py` — exit 0. An independent exact-source comparison verified only the declaration addition and its assignment split; no other previously dirty path was altered by the implementation lane. +- After-change forced-fresh command: `mkdir -p build/cron-20261018-after-gc-type-needs-decref/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-gc-type-needs-decref/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-gc-type-needs-decref/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Both former GC-branch diagnostics are gone. First remaining diagnostic is `typeobject.c(1636)` C2275/C2146/C2065 for `descrgetfunc f`, a separate untouched declaration family. Capture: `build/cron-20261018-after-gc-type-needs-decref/probe.log`. +- No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred; this is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then isolate only the first `typeobject.c(1636)` `descrgetfunc` declaration family. No completed port is claimed. + +--- + +## Latest verified slice (`subtype_dealloc()` non-GC `type_needs_decref` declaration; frontier advances) + +Date: 2026-10-18 UTC + +Used existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference first. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior `type_needs_decref` frontier was force-fresh confirmed: `_blake2/blake2s_impl.c` compiled, then VC6 reported C2143 at `typeobject.c(1359)` and a consequent C2065 at line 1372. The configured Hermes coding delegation could not start because Anthropic credentials are unavailable. Per the delegation workflow, the authenticated Codex CLI (`codex-cli 0.153.4`) handled one focused strict-TDD lane. New `scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py` failed against unchanged production source (exit 1) on the expected non-GC block-entry declaration assertion. The only production change declares `int type_needs_decref;` at the start of the non-GC branch and changes the prior initialized declaration to assignment at its existing evaluation point. The separate GC-branch declaration and all control flow remain untouched. The focused regression and all 28 `scripts/vc6-typeobject-*.test.py` tests passed. Both repository diff checks passed. A hash comparison confirmed all 98 outer tracked-dirty/untracked files captured before work were unchanged; the nested source change was separately inspected and is limited to the intended declaration/assignment delta. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh probe: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; first diagnostics `typeobject.c(1359)` C2143 and `(1372)` C2065 `type_needs_decref`; `_blake2/blake2s_impl.c` compiled. +- TDD RED: `python3 scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py` before production edit — exit 1 with expected block-entry declaration assertion; `git diff --exit-code -- cpython/Objects/typeobject.c` — exit 0, confirming source unchanged during RED. +- GREEN/regressions: focused regression after edit — exit 0. `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all 28 tests passed. +- After-change forced-fresh probe: `mkdir -p build/cron-20261018-after-type-needs-decref/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-type-needs-decref/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-type-needs-decref/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Both former non-GC branch errors are gone. Next first diagnostic is the separate GC-branch C2143 at `typeobject.c(1486)`, followed by C2065 `type_needs_decref` at line 1496; untouched. Full captures are in `build/cron-20261018-current-reprobe/probe.log` and `build/cron-20261018-after-type-needs-decref/probe.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py` and `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then isolate only the distinct GC-branch `type_needs_decref` declaration at line 1486. No completed port is claimed. + +--- + +## Latest verified slice (`subtype_traverse()` managed-dict `err` declaration; frontier advances) + +Date: 2026-10-18 UTC + +Used existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read `PORT_STATUS.md`, `README.md`, and active-profile `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before changes. Preserved all prior local work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `type_call()` frontier was stale. A forced-fresh probe confirmed the first stable error family at `typeobject.c(1235)` inside `subtype_traverse()`'s managed-dict branch: C2143 late declaration, then C2065 `err` at line 1236. One focused delegated implementation lane was attempted via the Hermes provider but could not start because Anthropic credentials are unavailable. The installed authenticated Codex CLI (`codex-cli 0.153.4`) completed one focused strict-TDD lane instead. New `scripts/vc6-typeobject-subtype-traverse-err-c89.test.py` was run against unchanged production source and failed on the expected missing function-entry declaration assertion (RED). The only production change hoists `int err;` into `subtype_traverse()`'s opening declarations and replaces the later initialized declaration with assignment at the same point after the existing assert. The separate `traverse_slots()` local `err`, evaluation point, error propagation, and control flow are preserved. The focused test and all 27 `scripts/vc6-typeobject-*.test.py` regressions passed. A byte-preservation check verified 226 other pre-existing dirty/untracked files were unchanged and `typeobject.c` contains exactly the requested source delta. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh probe: `mkdir -p build/cron-20261018-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-reprobe/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; first captured diagnostic `typeobject.c(1235)` C2143, followed by C2065 `err` at line 1236. `_blake2/blake2s_impl.c` compiled. +- TDD RED: `python3 scripts/vc6-typeobject-subtype-traverse-err-c89.test.py` before source edit — exit 1, expected function-entry declaration assertion. GREEN: same command after edit — exit 0. +- Regressions: `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all 27 passed. +- After-change forced-fresh probe: `mkdir -p build/cron-20261018-after-subtype-traverse/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-subtype-traverse/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-subtype-traverse/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; the former line-1235/1236 errors are gone. First remaining captured error is `typeobject.c(1359)` C2143, then line 1372 C2065 `type_needs_decref`; source family left untouched. Capture: `build/cron-20261018-after-subtype-traverse/probe.log`. +- `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- scripts/vc6-typeobject-subtype-traverse-err-c89.test.py` — exit 0. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-subtype-traverse-err-c89.test.py`, and this status entry. Next frontier: force-fresh confirm before isolating only the `typeobject.c(1359)` declaration family (`type_needs_decref`); do not claim a completed port. + +--- + +## Latest verified slice (`type_repr()` local declarations; frontier advances) + +Date: 2026-10-17 14:22 UTC + +Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; the requested `/home/ubuntu/projects/python-win9x` path does not exist. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before changes. Preserved all pre-existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, or publication. CPython baseline is tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `typeobject.c(1047)` frontier remained current under a forced-fresh VC6/Wine probe: `_blake2/blake2s_impl.c` compiled, then `type_repr()` failed on the late `PyObject *mod, *name, *rtn;` declaration. One focused Codex CLI lane (`codex-cli 0.153.4`, authenticated OpenAI, `--sandbox workspace-write --ephemeral`) followed TDD. It added the regression first, and observed the intended RED against unchanged production source. The only production change moves that declaration to the opening block before the `type->tp_name` guard; all assignments, evaluation order, and control flow remain unchanged. No other defect family was edited. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261018-before-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-before-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-before-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; first stable diagnostic group at `typeobject.c(1047)` was C2275 `PyObject` illegal use as expression, C2065 `mod`/`name`/`rtn` undeclared, and C2100 illegal indirection. `_blake2/blake2s_impl.c` compiled. Capture: `build/cron-20261018-before-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-type-repr-c89.test.py` before production edit — exit 1, expected assertion `type_repr: PyObject *mod, *name, *rtn; must be in the opening declaration block`. +- TDD GREEN: same focused test after edit — exit 0, `type_repr locals C89 declaration and unchanged assignment/evaluation/control flow: PASS`. Applicable regression command `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all 25 typeobject tests passed. +- After-change forced-fresh command: `mkdir -p build/cron-20261018-after-type-repr/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-type-repr/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-type-repr/probe.log 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. All former line-1047 diagnostics are gone. First remaining diagnostics: `typeobject.c(1090)` C2143 missing semicolon before `type`, then line 1092 C2065 `nargs` undeclared; left untouched. Capture: `build/cron-20261018-after-type-repr/probe.log`. +- `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- scripts/vc6-typeobject-type-repr-c89.test.py` — exit 0. Pre-existing changed/untracked path lists remained unchanged except the one intended new test; the already-modified `Objects/typeobject.c` retained its pre-existing status. +- Compiler-probe progress only. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. + +Files changed by this slice: `cpython/Objects/typeobject.c` (one declaration move); new `scripts/vc6-typeobject-type-repr-c89.test.py`; and this status entry. Next frontier: force-fresh confirm then isolate only the `type_call()` declaration at `typeobject.c(1090)`. Do not claim a completed port. + +--- + +## Latest verified slice (`type_set_annotations()` result declaration; frontier advances) + +Date: 2026-10-17 12:10 UTC + +Used existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read this status, `README.md`, and the profile reference `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `_PyType_Name()` frontier was stale. Forced-fresh VC6/Wine probing confirmed `_blake2/blake2s_impl.c` compiled, then the first stable diagnostic was `typeobject.c(972)` C2143, the late `int result;` declaration in `type_set_annotations()`. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, `workspace-write --ephemeral`) followed TDD. It added `scripts/vc6-typeobject-set-annotations-c89.test.py` and ran it before the production edit; RED exited 1 with the expected assertion that `result` must precede the immutable-type guard. The only production change moved `int result;` to the function's opening declaration block; executable statements, assignments, branches, and order were preserved. Its snapshot check confirmed existing changed/untracked paths were byte-identical other than this intended source edit. + +Exact verification: + +- Before-change forced-fresh probe: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First error at log line 1375: `cpython\\Objects\\typeobject.c(972) : error C2143: syntax error : missing ';' before 'type'`. Capture: `build/cron-20261018-current-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-annotations-c89.test.py` before production edit — exit 1, expected assertion `type_set_annotations: result must be declared before the immutable-type guard`. +- GREEN/regressions: focused test passed; all 24 `scripts/vc6-typeobject-*.test.py` scripts passed (overall exit 0). Outer `git diff --check -- PORT_STATUS.md scripts/vc6-typeobject-set-annotations-c89.test.py` and nested `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. +- After-change forced-fresh probe: `mkdir -p build/cron-20261018-after-set-annotations/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-set-annotations/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-set-annotations/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; the changed `typeobject.c` compiled through the former line-972 error. First remaining errors at line 1047 are C2275/C2065 for `PyObject`/`mod`/`name` and consequent C2100/C2065 for `rtn` in the next function; untouched. Capture: `build/cron-20261018-after-set-annotations/probe.log`. +- Compiler-probe progress only. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-set-annotations-c89.test.py`; and this status entry. Next frontier: force-fresh confirm, then isolate only the first `typeobject.c(1047)` declaration family. No completed port is claimed. + +--- + +## Previous verified slice (`type_get_annotations()` local declaration; frontier advances) + +Date: 2026-10-17 09:57 UTC + +Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, or publication. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused Codex CLI lane (`codex-cli 0.153.4`, authenticated OpenAI, `workspace-write --ephemeral`) followed TDD on the forced-fresh frontier. Before editing, the first stable diagnostics were `Objects/typeobject.c(937)` C2275 (`PyObject`) and C2065 (`annotations`) in `type_get_annotations()`. The source defect was a late local declaration after the heap-type guard. The only production edit moved `PyObject *annotations;` to the function's opening declaration position; all executable statements and their order remain unchanged. The focused regression checks the declaration placement and exact tokenized function body. An initial test implementation had a faulty whitespace assertion; its RED assertion failed for that test defect, was corrected, and the focused test was then rerun against unchanged production source to observe the expected RED. + +Exact verification: + +- Before-change forced-fresh probe: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: C2275/C2065 at `typeobject.c(937)` for `PyObject`/`annotations`. Capture: `build/cron-20261018-current-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-get-annotations-c89.test.py` against unchanged source — exit 1 with expected assertion `type_get_annotations: annotations must be declared before the heap-type guard`; `cmp cpython/Objects/typeobject.c /tmp/win9x-annotations-check/typeobject.before.c` — exit 0. +- GREEN and regressions: focused test — exit 0; all 23 `scripts/vc6-typeobject-*.test.py` scripts — exit 0. Preservation check verified 4,838 other baseline files byte-identical; prior entries in both repository statuses were retained. Scoped outer/nested `git diff --check` — exit 0. +- After-change forced-fresh probe: `mkdir -p build/cron-20261018-after-annotations/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-annotations/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-annotations/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Both former line-937 diagnostics are gone. Next first stable error is the distinct `typeobject.c(972)` C2143 missing-semicolon-before-type diagnostic, followed by C2065 `result` at line 975; untouched. Capture: `build/cron-20261018-after-annotations/probe.log`. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-get-annotations-c89.test.py`; and this status entry. Next frontier: force-fresh confirm, then isolate only the `type_set_annotations()` first diagnostic family. No completed port is claimed. + +--- + +## Latest verified slice (`type_set_bases()` rollback loop index; frontier advances) + +Date: 2026-10-18 UTC + +Used existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read `PORT_STATUS.md`, `README.md`, and the profile reference `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` first. Preserved all pre-existing outer and detached CPython work. No reset, clean, stash, discard, commit, push, or publication. The earlier recorded `res` frontier was stale: forced-fresh probing showed its fix was already present and advanced the first stable blocker to the rollback-loop C99 `Py_ssize_t i` declaration at `typeobject.c(847)`. Baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, OpenAI, workspace-write/ephemeral) followed TDD and preserved pre-existing changes. The new regression failed against unchanged production source, as expected. Since `type_set_bases()` already declares `Py_ssize_t i` at function scope, the sole production edit removes the redundant type from the rollback loop initializer, retaining reverse iteration, bounds, and restoration body. Regression covers rollback ordering and cleanup. A snapshot check confirmed all pre-existing file contents remain identical except the exact production line; only the requested regression test was added. + +Exact commands/results: + +- Before-change forced-fresh probe: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled; first error `typeobject.c(847)` C2143 on the C99 rollback-loop initializer. Capture: `build/cron-20261018-current-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-rollback-index-c89.test.py` — exit 1, expected `C99 rollback loop index declaration remains`; `cmp cpython/Objects/typeobject.c /tmp/typeobject-rollback-before.c` — exit 0 confirming production source unchanged for RED. +- TDD GREEN and all applicable tests: focused regression — exit 0; all 22 `scripts/vc6-typeobject-*.test.py` scripts — exit 0. Snapshot preservation check — exit 0. Scoped outer and nested `git diff --check` — exit 0. +- After-change forced-fresh probe: `mkdir -p build/cron-20261018-after-rollback-index/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-rollback-index/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-rollback-index/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The rollback-loop diagnostic at line 847 is gone. First remaining error is `typeobject.c(937)` C2275: `'PyObject' : illegal use of this type as an expression`; distinct later blocker untouched. Capture: `build/cron-20261018-after-rollback-index/probe.log`. +- No pythoncore/python.exe link, Wine interpreter execution, or Windows 98 SE execution occurred; this is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-set-bases-rollback-index-c89.test.py`; and this status entry. Next frontier: force-fresh confirm, then isolate the `typeobject.c(937)` defect family only. No completed port is claimed. + +--- + +## Previous verified slice (`type_set_bases()` `res` declaration; frontier advances) + +Date: 2026-10-18 UTC + +Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; the requested `/home/ubuntu/projects/python-win9x` path does not exist. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all prior outer and detached CPython changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A forced-fresh MSVC600/Wine probe confirmed the recorded `type_set_bases()` `res` blocker. One focused authenticated Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI, `--sandbox workspace-write --ephemeral`) followed TDD: added a focused regression and ran it against the unchanged source, observing the expected RED; then declared only `int res;` among the opening locals. Assignments, branches, and evaluation order were not changed. The child initially observed three existing declaration-fixture failures because they expected `if` immediately following the prior locals; narrowly updated those three directly affected expectations to account for `int res;`. No other production source changed. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled; first diagnostic `typeobject.c(821) C2065: 'res' : undeclared identifier`. Capture: `build/cron-20261018-current-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-res-c89.test.py` before production edit — exit 1, expected assertion `type_set_bases: res must be declared with the opening locals`. +- GREEN/regressions: focused test and all `scripts/vc6-typeobject-*.test.py` — exit 0; 21 scripts passed. Initial full-suite run caught three stale declaration expectations; they were narrowly updated, and the full suite then passed. Scoped `git diff --check` (status and four affected outer tests) and `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. +- After-change forced-fresh command: `mkdir -p build/cron-20261018-after-res/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-res/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-res/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`; prior `res` undeclared error is gone. First remaining diagnostic advances to `typeobject.c(847)` C2143/C2059 for the distinct C99 rollback-loop index `for (Py_ssize_t i = n - 1; ...)`; left untouched. Capture: `build/cron-20261018-after-res/probe.log`. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; this is compiler-probe progress only. + +Files changed in this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-set-bases-res-c89.test.py`; narrowly updated `scripts/vc6-typeobject-set-bases-index-c89.test.py`, `scripts/vc6-typeobject-set-bases-n-c89.test.py`, and `scripts/vc6-typeobject-set-bases-new-base-c89.test.py`; and this status entry. Next frontier: force-fresh confirm, then isolate only the rollback-loop C89 index declaration. No completed port is claimed. + +--- + +## Previous verified slice (`type_set_bases()` `temp` declaration; frontier advances) + +Date: 2026-10-17 UTC + +Used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; the requested `/home/ubuntu/projects/python-win9x` path does not exist. Read `PORT_STATUS.md`, `README.md`, and the applicable CPython Win9x/MSVC6 reference. Preserved the existing dirty/untracked outer and nested CPython work; no reset, clean, stash, discard, commit, push, or publication. The CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A forced-fresh compiler probe confirmed the previous typeobject declaration sequence had moved on: `temp` was the first undeclared identifier in `type_set_bases()`. One focused Hermes coding delegation was attempted but did not start because Anthropic credentials are unavailable. Implemented just the confirmed local declaration under TDD; the assignment remains at its original point, after the existing base updates. Adjusted only the directly affected expectations for the already-hoisted locals in the related `set_bases` tests. No `res` or later defect family was changed. + +Exact verification: + +- Before probe command: `mkdir -p build/cron-20261017-current-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261017-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261017-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; first diagnostic `typeobject.c(809) C2065: 'temp' : undeclared identifier`. `_blake2/blake2s_impl.c` compiled. Capture: `build/cron-20261017-current-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-temp-c89.test.py` before source edit — exit 1 with the intended assertion that `temp` must be in the opening declarations. +- GREEN/regressions: focused test plus every `scripts/vc6-typeobject-*.test.py` — exit 0; all 20 typeobject scripts passed. Scoped `git diff --check` for edited outer tests and nested `Objects/typeobject.c` — exit 0. +- After probe command: `mkdir -p build/cron-20261017-after-temp/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261017-after-temp/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261017-after-temp/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled, former `temp` error removed, and first diagnostic is now `typeobject.c(821) C2065: 'res' : undeclared identifier`. `res` and all later blockers remain unchanged. Capture: `build/cron-20261017-after-temp/probe.log`. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed in this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-set-bases-temp-c89.test.py`; narrowly updated expected declaration block in `scripts/vc6-typeobject-set-bases-index-c89.test.py`, `scripts/vc6-typeobject-set-bases-new-base-c89.test.py`, and `scripts/vc6-typeobject-set-bases-n-c89.test.py`; and this status entry. Next frontier: force-fresh confirm, then handle only `res` in `type_set_bases()` if still first. No completed port is claimed. + +--- + +## Latest verified slice (`type_set_bases()` `old_bases` declaration; frontier advances) + +Date: 2026-10-16 UTC + +Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; the requested `/home/ubuntu/projects/python-win9x` path does not exist. Read `PORT_STATUS.md`, `README.md`, and the profile legacy-toolchain reference. Preserved the extensive pre-existing dirty/untracked outer and detached CPython work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `new_base` frontier had advanced. A forced-fresh probe compiled `_blake2/blake2s_impl.c`; the first errors were `typeobject.c(800)` C2275/C2065 for the late `PyObject *old_bases = type->tp_bases;`, followed by separate `old_base` and `temp` declaration errors. A focused Hermes coding delegation was attempted but could not start because Anthropic credentials are unavailable. Implemented only the confirmed old_bases declaration/assignment split under TDD: new `scripts/vc6-typeobject-set-bases-old-bases-c89.test.py` failed first (exit 1, intended opening-declaration assertion); source now declares `PyObject *old_bases;` with function locals and assigns `old_bases = type->tp_bases;` at its previous point immediately before its assertion. Evaluation and assertion order are unchanged. Directly affected existing type_set_bases expectation tests were adjusted to account for the new local. No `old_base`, `temp`, `res`, or other defect family was changed. + +Exact verification: + +- Before probe: `mkdir -p "$TMPDIR/cp311-cron-typeobject-before/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-typeobject-before/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-typeobject-before/probe.log" 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled; first errors at `typeobject.c(800)` C2275/C2065 `old_bases`. Initial independent confirmation was captured at `build/cron-20261016-frontier-confirm/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-old-bases-c89.test.py` before production edit — exit 1 at expected missing declaration assertion. +- GREEN and applicable regressions: `python3 scripts/vc6-typeobject-set-bases-old-bases-c89.test.py` plus every `scripts/vc6-typeobject-*.test.py` — exit 0; 18 typeobject scripts passed. Scoped `git diff --check` in nested source and outer changed tests — exit 0. +- After probe: `mkdir -p build/cron-20261016-old-bases-after/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261016-old-bases-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261016-old-bases-after/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; former `old_bases` errors are gone. First current diagnostics are separate `old_base` undeclared at line 803 and `temp` undeclared at line 808, left untouched. Capture: `build/cron-20261016-old-bases-after/probe.log`. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-set-bases-old-bases-c89.test.py`; directly affected expectations in `scripts/vc6-typeobject-set-bases-index-c89.test.py`, `scripts/vc6-typeobject-set-bases-n-c89.test.py`, and `scripts/vc6-typeobject-set-bases-new-base-c89.test.py`; and this status entry. Next frontier: force-fresh confirm and handle only `old_base` if still first. No completed port is claimed. + +--- + + + +Date: 2026-10-16 16:21 UTC + +Used the existing checkout at `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; the requested `/home/ubuntu/projects/python-win9x` path does not exist. Read `README.md`, this status, and the CPython 3.11.16/MSVC6 reference under the active profile. Preserved all pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded frontier had advanced; before editing a forced-fresh VC6 probe confirmed `_blake2/blake2s_impl.c` compiled and the first diagnostic was `typeobject.c(769)` C2275/C2065 for the late `PyTypeObject *base` declaration in `type_set_bases()`. A focused Hermes coding-subagent could not start because the configured Anthropic provider has no credentials. The installed authenticated Codex CLI (`codex-cli 0.153.4`) performed one narrow implementation lane under TDD. New `scripts/vc6-typeobject-set-bases-base-c89.test.py` failed before the production edit on the intended missing loop-opening declaration. The sole production change declares `base` at the top of the loop body and assigns `(PyTypeObject*)ob` only after the existing `PyType_Check(ob)` validation; item retrieval, validation, cast timing, and subsequent checks remain ordered as before. No other production defect family changed. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-cron-current-frontier/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-current-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-current-frontier/probe.log" 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First compiler errors: `typeobject.c(769)` C2275/C2065 on `PyTypeObject *base`. Capture: `$TMPDIR/cp311-cron-current-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-base-c89.test.py` before source edit — exit 1 with the expected assertion that `base` is missing from the loop's opening declaration block. +- TDD GREEN and applicable regression suite: focused test plus all `scripts/vc6-typeobject-*.test.py` — exit 0; all 16 typeobject regression scripts passed. +- First after-change probe attempt used the requested scratch `XDG_RUNTIME_DIR` and exited 1 before compilation because Wine could not create its server lock under `/run/user/1000` (read-only filesystem). `wine cmd /c ver` with project-local `XDG_RUNTIME_DIR="$PWD/build/cronbase/runtime"` exited 0 (`Microsoft Windows 10.0.19043`). Retried forced-fresh with `mkdir -p build/cron-current-after/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-after/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-769 `base` diagnostics are gone. First current diagnostics advance to `typeobject.c(791)` C2275/C2065 on the distinct `PyTypeObject *new_base` declaration, left untouched. Capture: `build/cron-current-after/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped nested/outer `git diff --check` — exit 0. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-set-bases-base-c89.test.py`, and this status entry. Next frontier: force-fresh confirmation before handling only the late `new_base` declaration in `type_set_bases()`; keep subsequent declaration families separate. No completed port is claimed. + +--- + +## Latest verified slice (`type_set_bases()` loop-index C89 declaration; frontier advances) + +Date: 2026-10-16 UTC + +The requested `/home/ubuntu/projects/python-win9x` path did not exist; this existing checkout at `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x` was used. Read `PORT_STATUS.md` and `README.md` before acting. The named legacy reference `references/python-3-win9x-msvc6.md` was not found under this workspace or the searched legacy-ports tree; used the loaded legacy-toolchain skill guidance. Preserved all prior dirty and untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` sequence was no longer the active compiler frontier: a forced-fresh probe confirmed that file compiled, then first stopped at `typeobject.c(760)` in `type_set_bases()` on `for (Py_ssize_t i = 0; ...)`. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, OpenAI, workspace-write/ephemeral) implemented only this C89 loop-index slice under TDD. The test was run against the pre-edit source and failed on the expected missing declaration; the production change hoists `Py_ssize_t i;` adjacent to `n` and retains `i = 0` in the original loop initializer. It did not change the separate rollback loop. The existing `set-bases-n` regression was updated for the new declaration while keeping its earlier validation-order checks. Codex initially observed a test assertion failure because the first test version counted the separate rollback-loop `i`; the test was scoped to the requested validation loop and the complete applicable suite then passed. Snapshot/hash verification confirmed all pre-existing files except the two intentionally edited files remained unchanged. + +Exact verification: + +- Before-edit command: `mkdir -p "$TMPDIR/cp311-cron-blake-reprobe/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-blake-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-blake-reprobe/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics were at `typeobject.c(760)` C2143/C2065/C2059 for the C99 loop declaration. Capture: `$TMPDIR/cp311-cron-blake-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-index-c89.test.py` against saved pre-edit `typeobject.c` — exit 1 on the intended assertion that `Py_ssize_t i;` must follow `n` in the opening declaration block. +- Focused GREEN: `python3 scripts/vc6-typeobject-set-bases-index-c89.test.py` — exit 0, `type_set_bases loop index C89 declaration and unchanged evaluation order: PASS`. +- Applicable regression suite: `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" >/dev/null || { printf 'regression_failed=%s\\n' "$test"; exit 1; }; done` — exit 0; all 15 scripts passed. +- After-edit forced-fresh command: `mkdir -p "$TMPDIR/cp311-cron-blake-after/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-blake-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-blake-after/probe.log" 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The prior loop-declaration diagnostics at line 760 are gone. First current diagnostics advance to `typeobject.c(769)` C2275/C2065 for the separate late `PyTypeObject *base` declaration; subsequent errors remain untouched. Capture: `$TMPDIR/cp311-cron-blake-after/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Focused nested and outer `git diff --check` commands exited 0. +- No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-set-bases-index-c89.test.py`, updated `scripts/vc6-typeobject-set-bases-n-c89.test.py`, and this status entry. Next frontier: force-fresh re-probe before isolating the newly observed `type_set_bases()` late `PyTypeObject *base` declaration. Do not combine it with later declaration families or claim the port is complete. + +--- + +## Latest verified slice (`_PyType_Name()` C89 local declaration; frontier advances) + +Date: 2026-10-16 UTC + +Read `PORT_STATUS.md`, `README.md`, and the legacy-toolchain guidance before acting. The specific `python-3-win9x-msvc6.md` reference file was not present in the expected workspace/profile locations. The instructed `/home/ubuntu/projects/python-win9x` path does not exist; used the current checkout at `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Preserved existing dirty/untracked state in both repositories; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A fresh probe confirmed the recorded `_PyType_Name()` blocker. A Hermes coding delegation could not start because the configured Anthropic provider has no credentials; the installed authenticated Codex CLI (`codex-cli 0.153.4`, workspace-write/ephemeral) performed one focused implementation lane under strict TDD. The new test failed before source change at the expected missing opening declaration. Only `const char *s;` was hoisted; assignment to `strrchr()` stays after the assertion at its prior evaluation point. Codex hash checks confirmed pre-existing dirty/untracked files remained unchanged; the production file differed only by the requested declaration/assignment split. + +Exact verification: + +- Before-change command: `mkdir -p "$TMPDIR/cp311-cron-reprobe/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-reprobe/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(463)` C2143, then `(464)` C2065 for `s`. Capture: `$TMPDIR/cp311-cron-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-type-name-c89.test.py` before production change — exit 1, expected assertion that `const char *s;` must be in the opening declaration block. +- GREEN and applicable regressions: focused test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all nine typeobject test scripts passed. +- After-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-cron-after/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-after/probe.log" 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former lines 463-464 errors are gone. First current diagnostics advance to `typeobject.c(677)` C2275/C2065 for `new_mro`, then line 679 for `tuple`; these are separate and untouched. Capture: `$TMPDIR/cp311-cron-after/probe.log`. +- Baseline tag and commit verified unchanged. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-name-c89.test.py`, and `PORT_STATUS.md`. Next frontier: force-fresh re-probe before choosing the next isolated `typeobject.c` defect family; first observed is the late `new_mro` declaration at line 677. Do not conflate a compiler-probe advance with a linked or target-running interpreter. + +--- + +## Latest verified slice (`assign_version_tag()` C89 loop index; frontier advances) + +Date: 2026-10-16 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the pre-existing dirty outer checkout and detached CPython edits; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. A focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) implemented only the confirmed `assign_version_tag()` loop-index declaration using strict TDD. + +Exact verification: + +- Before-change forced-fresh probe: `mkdir -p "$TMPDIR/cp311-current-frontier/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-current-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-current-frontier/probe.log" 2>&1` — actual probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics were `typeobject.c(411)` C2143/C2065/C2059 cascading from `for (Py_ssize_t i = 0; ...)`. Capture: `$TMPDIR/cp311-current-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-assign-version-tag-index-c89.test.py` before production change — exit 1 on the expected assertion that function-scope `i` must precede statements. +- GREEN and applicable regressions: focused test plus `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test"; done` — exit 0; all nine typeobject tests pass. Two existing expectations (`vc6-typeobject-assign-version-tag-n-c89.test.py`, `vc6-typeobject-mro-bases-c89.test.py`) were narrowly adjusted for the hoisted declaration and assignment-form loop; their other behavior/order assertions remain. +- The only production change is `cpython/Objects/typeobject.c`: declare `Py_ssize_t i;` with `assign_version_tag()` locals and change the loop initializer to `i = 0`; bounds, body, and evaluation/control-flow order remain unchanged. +- After-change forced-fresh probe: `mkdir -p "$TMPDIR/cp311-after-assign-version-tag-index/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-after-assign-version-tag-index/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-after-assign-version-tag-index/probe.log" 2>&1` — actual probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former line-411 diagnostics are gone. New first stable blocker: `typeobject.c(463)` C2143 and `(464)` C2065 for the later `const char *s` declaration in `_PyType_Name()`; untouched. Capture: `$TMPDIR/cp311-after-assign-version-tag-index/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped source/test `git diff --check` commands exited 0. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-assign-version-tag-index-c89.test.py`, focused expectation updates in `scripts/vc6-typeobject-assign-version-tag-n-c89.test.py` and `scripts/vc6-typeobject-mro-bases-c89.test.py`, and this status entry. Next frontier: force-fresh re-probe before choosing a separate slice for `_PyType_Name()`'s `s` declaration if it remains first. Do not combine it with later `typeobject.c` blockers or claim a completed port. + +--- + +## Latest verified slice (`type_mro_modified()` `custom_mro` C89 declaration; frontier advances) + +Date: 2026-10-15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `type_mro_modified()` frontier was force-reprobed and confirmed: `_blake2/blake2s_impl.c` compiled, then VC6 reported C2143 at `typeobject.c(362)` for the late `int custom_mro` declaration; a later C2065 at line 365 was consequential. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) used strict TDD. New `scripts/vc6-typeobject-custom-mro-c89.test.py` failed before the production edit with the expected missing opening-block declaration assertion. The only production change declares `custom_mro` in the opening declaration block of `if (custom)` and assigns it after both successful lookups, at the original evaluation point before decrefs and the conditional. Lookup failure handling and evaluation order are unchanged. No later blocker was edited. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-current-frontier/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-current-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-current-frontier/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic: `typeobject.c(362)` C2143; later diagnostic: `typeobject.c(365)` C2065 for `custom_mro`. Capture: `$TMPDIR/cp311-current-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-custom-mro-c89.test.py` before production edit — exit 1, expected assertion `custom_mro must be declared in the opening declaration block`. +- GREEN and applicable regressions: focused test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all six typeobject scripts passed. +- After-change forced-fresh command with equivalent `XDG_RUNTIME_DIR="$TMPDIR/cp311-after-custom-mro/runtime"` environment — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-362/365 diagnostics are gone. Next first diagnostics are separate `typeobject.c(407)` C2275/C2065 for `bases`, followed by `n` and loop-index diagnostics at lines 408-409; these remain untouched. Capture: `$TMPDIR/cp311-after-custom-mro/probe.log`. +- Focused and all typeobject tests — exit 0. `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- scripts/vc6-typeobject-custom-mro-c89.test.py` — exit 0. Baseline tag/commit remain unchanged. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only, not a completed port. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only the `custom_mro` declaration/assignment split), new `scripts/vc6-typeobject-custom-mro-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then address only the first remaining `type_mro_modified()` `bases` declaration if still current; keep `n` and loop index as separate defect families. + +--- + +## Previous verified slice (`PyType_Modified()` `obj` declaration; frontier advances) + +Date: 2026-10-15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior recorded `PyType_Modified()` `obj` declaration frontier was force-reprobed and confirmed. `_blake2/blake2s_impl.c` compiled; the first diagnostics were `typeobject.c(318)` C2143 and `(319)` C2065 for the late initialized `PyObject *obj`. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD. It updated `scripts/vc6-typeobject-modified-ref-c89.test.py` first; the RED run exited 1 on the expected missing opening-block `obj` declaration. The minimal production edit hoists `PyObject *obj;` into `PyType_Modified()`'s opening declaration block and changes the old declaration to `obj = PyWeakref_GET_OBJECT(ref);` at the original evaluation point. The directly applicable subclasses test expectation was narrowly updated. No other production defect family was changed. No commit or publication occurred. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-frontier-refresh/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-frontier-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-frontier-refresh/probe.log" 2>&1` — compiler probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors: `typeobject.c(318)` C2143 and `(319)` C2065 on `obj`; later diagnostics were subsequent distinct blockers. Capture: `$TMPDIR/cp311-frontier-refresh/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-modified-ref-c89.test.py` after test-only update and before source edit — exit 1, expected assertion: `PyType_Modified: PyObject *obj; must be in the opening declaration block`. +- GREEN and applicable regressions: focused ref test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all five typeobject scripts passed. +- After-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-frontier-after-obj/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-frontier-after-obj/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-frontier-after-obj/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-318/319 `obj` diagnostics are gone. The next diagnostics advance to the separate `type_mro_modified()` C89 declaration at line 362 (C2143), followed by `custom_mro` at line 365; neither was changed. Capture: `$TMPDIR/cp311-frontier-after-obj/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped nested and outer diff checks exited 0. Before/after porcelain snapshots match in both repositories outside this intentional slice; extensive pre-existing changes remain present. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Compiler-probe progress only; no completed port is claimed. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only `PyType_Modified()`'s `obj` declaration/assignment split), `scripts/vc6-typeobject-modified-ref-c89.test.py`, `scripts/vc6-typeobject-modified-subclasses-c89.test.py`, and this status entry. Next frontier: force-fresh probe, then handle only the newly confirmed `type_mro_modified()` blocker if still first; keep the later `custom_mro` declaration separate. + +--- + +## Latest verified slice (`PyType_Modified()` C89 loop-index declaration; frontier advances) + +Date: 2026-10-15 09:17 UTC + +Read `PORT_STATUS.md` and `README.md` before acting. The requested CPython Win9x/MSVC6 reference file was not found in this checkout or active profile path; followed the loaded legacy-toolchain skill guidance. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier was force-reprobed before editing and confirmed: `_blake2/blake2s_impl.c` compiled, then the first diagnostic was `typeobject.c(313)` on `Py_ssize_t i = 0;`. A focused Hermes coding-subagent launch was unavailable because the configured Anthropic provider had no credentials. Authenticated `codex-cli 0.153.4` was used as one focused implementation lane, with strict TDD. New `scripts/vc6-typeobject-modified-index-c89.test.py` failed before the production edit (exit 1) on the intended assertion that `Py_ssize_t i;` belongs in the opening declaration block. The production change hoists only `i` and moves `i = 0;` to the exact original initialization point. Updated the directly applicable subclasses declaration expectation to permit the hoisted `i`. The distinct `ref` and `obj` declarations and all later blockers remain untouched. + +Exact verification: + +- Before-edit forced-fresh command: `XDG_RUNTIME_DIR="$TMPDIR/cp311-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(313)` C2143 for the late loop-index declaration. Capture: `$TMPDIR/cp311-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-modified-index-c89.test.py` before production edit — exit 1, expected assertion `PyType_Modified: Py_ssize_t i; must be declared at function entry`. +- GREEN and applicable regression: focused test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test"; done` — exit 0; all four typeobject tests passed. +- After-edit forced-fresh command with the same environment/command — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former `typeobject.c(313)` loop-index diagnostic is gone; first current diagnostic advances to `typeobject.c(315)` C2275/C2065 on the separate `PyObject *ref` declaration. `obj` at line 318 and other typeobject blockers are later and untouched. Capture: `$TMPDIR/cp311-frontier-after/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped nested and outer `git diff --check` on the three slice files — exit 0. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Compiler-probe progress only; no completed port is claimed. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only the `PyType_Modified()` index declaration/assignment split), new `scripts/vc6-typeobject-modified-index-c89.test.py`, narrow expectation update to `scripts/vc6-typeobject-modified-subclasses-c89.test.py`, and this status entry. Next frontier: force-fresh probe, then address only the `PyObject *ref` declaration in `PyType_Modified()` if still first. + +--- + +## Previous verified slice (`PyType_Modified()` C89 subclasses declaration; frontier advances) + +Date: 2026-10-15 07:05 UTC + +Read `PORT_STATUS.md` and `README.md` before acting. The requested legacy-toolchain reference file was not found in this checkout or active profile path; the loaded legacy-toolchain skill guidance was followed. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `_PyType_InitCache()` loop-index blocker was force-reprobed and its fix remains effective. `_blake2/blake2s_impl.c` compiled. The current first stable blocker was `PyType_Modified()`'s late `PyObject *subclasses = type->tp_subclasses;` at `typeobject.c(307)`. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI authenticated, workspace-write/ephemeral) followed strict TDD for only this declaration family. New `scripts/vc6-typeobject-modified-subclasses-c89.test.py` failed before the production edit with the intended assertion that `subclasses` must be declared at function entry. The sole production change hoists `PyObject *subclasses;` and leaves `subclasses = type->tp_subclasses;` immediately after the existing early-return guard. No other production defect family was changed. + +Exact verification: + +- Before-change forced-fresh probe: `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` with `XDG_RUNTIME_DIR="$TMPDIR/cron-reprobe/runtime"`, `WINEPREFIX=/home/ubuntu/.wine-win9xport`, and `WINEDEBUG=-all`; captured at `$TMPDIR/cron-reprobe/probe.log`. Probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics were `typeobject.c(307)` C2275/C2065 for `PyObject`/`subclasses`, followed by declaration errors at lines 311-316. No source edits occurred before this probe. +- TDD RED: `python3 scripts/vc6-typeobject-modified-subclasses-c89.test.py` before source edit — exit 1 at the expected missing function-entry declaration assertion. +- TDD GREEN: same focused test after source edit — exit 0. Applicable regression command `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all 3 typeobject tests passed. +- After-change forced-fresh probe using the same command/environment, captured at `$TMPDIR/cron-after-subsclasses/probe.log` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former line-307 diagnostics are gone. The first remaining diagnostics are at `typeobject.c(313)` C2143, then line 314 C2275/C2065 for the later `ref` declaration and line 315 for `i`; these are distinct next declaration families and remain untouched. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git -C cpython diff --check -- Objects/typeobject.c` and outer `git diff --check -- PORT_STATUS.md scripts/vc6-typeobject-modified-subclasses-c89.test.py` — exit 0. The complete nested diff also contains earlier pre-existing typeobject edits; this slice's addition is restricted to `PyType_Modified()`. +- No DLL/executable link, Wine interpreter execution, or real Windows 98 SE execution occurred. Compiler-probe progress only; no completed port is claimed. + +Files changed by this slice: `cpython/Objects/typeobject.c` (one declaration/assignment split in `PyType_Modified()`), new `scripts/vc6-typeobject-modified-subclasses-c89.test.py`, and this status entry. Next frontier: force-fresh re-probe, then isolate only the `ref`/loop-index declaration blockers in `PyType_Modified()`; do not combine them with later `type_mro_modified()` or other `typeobject.c` diagnostics. + +--- + +## Previous verified slice (`_PyType_InitCache()` C89 loop index declaration; frontier advances) + +Date: 2026-10-15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. A single delegated coding lane was attempted but could not start because no Anthropic credentials are configured; implementation proceeded directly under strict TDD. + +The stale recorded tupleobject frontier was replaced based on a forced-fresh probe. It compiled `_blake2/blake2s_impl.c` and stopped in `typeobject.c(228)` at the C89 loop-local `Py_ssize_t i`. The narrow TDD change hoists `i` into `_PyType_InitCache()`'s opening declarations and retains loop bounds, increment, and body. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command used `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` with project-local `XDG_RUNTIME_DIR` and `WINEPREFIX=/home/ubuntu/.wine-win9xport` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable error group was `typeobject.c(228)` C2143/C2065/C2059 for loop-local `i`. Capture: `$TMPDIR/cron-current-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-mro-loop-c89.test.py` before production edit — exit 1 on missing hoisted `Py_ssize_t i;`. +- GREEN/regressions: focused test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test"; done` — exit 0; both typeobject tests passed. +- After-change forced-fresh probe with the same command/environment — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Line-228 loop declaration errors are gone; first remaining group is `typeobject.c(307)` for a late `PyObject *subclasses` declaration. Full capture: `$TMPDIR/cron-current-after/probe.log`. +- `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- scripts/vc6-typeobject-mro-loop-c89.test.py` — exit 0. No DLL/executable link, Wine interpreter execution, or Windows 98 SE execution occurred. + +Files changed: `cpython/Objects/typeobject.c` (only `_PyType_InitCache()` loop index declaration split), new `scripts/vc6-typeobject-mro-loop-c89.test.py`, and this entry. Next frontier: freshly re-probe then handle only the `typeobject.c(307)` late `subclasses` declaration. Compiler-probe progress only; no completed port is claimed. + +--- + +## Previous verified slice (`maybe_freelist_push()` index C89 declaration; frontier advances) + +Date: 2026-10-14 UTC + +Read `PORT_STATUS.md`, `README.md`, and `legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded tupleobject frontier was rechecked with a forced-fresh MSVC6 probe before editing. `_blake2/blake2s_impl.c` had already compiled, and the `maybe_freelist_push()` late `Py_ssize_t index` declaration at line 1247 was indeed the first current diagnostic. One focused Codex CLI coding lane was used. It added a single C89 regression test, observed RED, then moved the declaration into the function's declaration block while preserving assignment after the empty-tuple return. The later C89 `for` loop blockers were deliberately left untouched. + +Exact verification: + +- Before-change probe: `mkdir -p build/cron-20261014-tuple-index-before/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-tuple-index-before/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-tuple-index-before/probe.log 2>&1` — probe exit 2; `total=108 compiled=107 cached=0 skipped=0`. First errors were at `tupleobject.c(1247)` (C2275, C2146, C2065); next independent errors were C89 loops at lines 1268 and 1287. `_blake2/blake2s_impl.c` compiled. Log: `build/cron-20261014-tuple-index-before/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-freelist-push-index-c89.test.py` before source edit — exit 1, expected assertion that `index` must be declared before debug assertion and empty-tuple check. +- TDD GREEN: same focused command after source edit — exit 0, `maybe_freelist_push index C89 declaration and evaluation order: PASS`. +- Applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; result=$?; printf '%s: exit %s\\n' "$test" "$result"; if [ "$result" -ne 0 ]; then exit "$result"; fi; done` — exit 0; all 14 tupleobject tests passed. +- After-change forced-fresh probe: `mkdir -p build/cron-20261014-tuple-index-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-tuple-index-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-tuple-index-after/probe.log 2>&1` — probe exit 2; `total=108 compiled=107 cached=0 skipped=0`. The line-1247 errors are gone. The first remaining diagnostics are now C89 `for` loop declarations at `tupleobject.c(1269)` and `(1288)` (C2143/C2146/C2065/C2059 cascades). Log: `build/cron-20261014-tuple-index-after/probe.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-tupleobject-freelist-push-index-c89.test.py` and `git -C cpython diff --check -- Objects/tupleobject.c` — both exit 0. Detached baseline HEAD remains unchanged. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only declaration and assignment in `maybe_freelist_push()`), new `scripts/vc6-tupleobject-freelist-push-index-c89.test.py`, and this status entry. Next compiler frontier: `maybe_freelist_clear()` loop declaration at line 1269; treat its defect family separately from the later loop in `_PyTuple_DebugMallocStats()` at line 1288. No linked `pythoncore.dll`/`python.exe`, Wine interpreter run, or real Windows 98 SE execution occurred: this is compiler-probe progress only, not a completed port. + +--- + +## Previous verified slice (`PyTuple_Type.tp_vectorcall` C89 initializer; frontier advances) + +Date: 2026-10-14 15:38 UTC + +Read `PORT_STATUS.md`, `README.md`, and the applicable CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The requested `_blake2/blake2s_impl.c` sequence was not the current compiler frontier: forced-fresh probe confirmed it compiles. The previously documented tupleobject designated-initializer blocker remained current. A single focused coding-agent delegation was attempted, but the configured Hermes provider could not start (Anthropic credentials unavailable). The installed authenticated Codex CLI was used as the focused implementation lane. It applied strict TDD to only `PyTuple_Type`'s `.tp_vectorcall` designated initializer at line 919. New `scripts/vc6-tupleobject-type-vectorcall-c89.test.py` failed before production edits (exit 1) because strict C89 rejected the designated initializer. The source change replaces that one designator with nine zero positional entries for `tp_is_gc` through `tp_finalize`, then `tuple_vectorcall` for `tp_vectorcall`. These entries follow the checkout's `PyTypeObject` field order. No `_blake2` file or other tupleobject defect family was changed. + +Exact verification: + +- Before-change forced-fresh probe: `mkdir -p build/cron-20261014-blake-frontier/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-blake-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-blake-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First current compiler errors: `tupleobject.c(919)` C2059 on `.`; later distinct errors at lines 1238, 1259, and 1278 were untouched. Capture: `build/cron-20261014-blake-frontier/probe.log`. +- Focused coding-agent delegation attempt: unavailable before child startup because Anthropic credentials are not configured. Authenticated `codex-cli 0.153.4` was used in a single `codex exec --sandbox workspace-write --ephemeral` lane. No commits or resets. +- TDD RED: `python3 scripts/vc6-tupleobject-type-vectorcall-c89.test.py cpython/Objects/tupleobject.c` before source edit — exit 1, expected strict C89 designated-initializer failure. GREEN: same command after edit — exit 0; compiles the exact extracted initializer under `cc -std=c89 -pedantic-errors -Wall -Wextra -Werror` and checks all 48 semantic fields. +- Applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" cpython/Objects/tupleobject.c; done` — exit 0 for all 13 scripts, including the new initializer regression. +- After-change forced-fresh probe: `mkdir -p build/cron-20261014-tuple-vectorcall-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-tuple-vectorcall-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-tuple-vectorcall-after/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-919 C2059 is gone. First remaining compiler diagnostics are now at `tupleobject.c(1247)` on `Py_ssize_t index` (C2275/C2146/C2065), followed by separate C89 loops at lines 1268 and 1287. Capture: `build/cron-20261014-tuple-vectorcall-after/probe.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-tupleobject-type-vectorcall-c89.test.py` and `git -C cpython diff --check -- Objects/tupleobject.c` — exit 0. Baseline tag/commit unchanged. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `PyTuple_Type` initializer tail), new `scripts/vc6-tupleobject-type-vectorcall-c89.test.py`, and this status entry. Next frontier: in a separate TDD slice, force-fresh confirm and address only the `tupleobject.c:1247` late `index` declaration. Do not conflate compiler-probe progress with a linked or target-running interpreter. No completed port is claimed. + +--- + +## Previous verified slice (`tuplerepeat()` `dest_end` declaration; frontier advances) + +Date: 2026-10-14 11:13 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior `tuplerepeat()` `dest_end` frontier was force-reprobed first and confirmed. A single focused coding-agent delegation was attempted, but the provider could not start because Anthropic credentials are unavailable. No child edits occurred. I proceeded with one narrow local TDD slice: added `scripts/vc6-tupleobject-repeat-dest-end-c89.test.py`; its pre-edit run failed with exit 1 on the intended missing opening-declaration assertion. The sole production change declares `PyObject **dest_end` in the opening block and changes the original initialized declaration to `dest_end = dest + size;` at the same point immediately after `dest = np->ob_item`. Updated the directly applicable existing `scripts/vc6-tupleobject-repeat-dest-c89.test.py` expectation to accept the new adjacent declaration and assignment while preserving its evaluation-order checks. Other tupleobject defect families were not edited. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p build/cron-20261014-frontier-refresh/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-frontier-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-frontier-refresh/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic family: `tupleobject.c(530)` C2275 (`PyObject`), C2065 (`dest_end`), C2100. Distinct later errors include `nargs` at 732, designated initializer at 916, `index` at 1235, and C89 loops at 1256/1275. Capture: `build/cron-20261014-frontier-refresh/probe.log`. +- Coding delegation: failed before startup due missing Anthropic credentials/provider; no child edits. +- TDD RED: `python3 scripts/vc6-tupleobject-repeat-dest-end-c89.test.py` before production edit — exit 1 on the intended assertion `dest_end must be declared in the opening declaration block`. +- GREEN/regressions: focused dest_end test and all `scripts/vc6-tupleobject-*.test.py` — exit 0; all 11 tupleobject regressions passed. The pre-existing `repeat-dest` check initially failed on its obsolete declaration-with-initializer expectation; that narrow assertion was aligned with the split declaration/assignment, and the complete suite then passed. +- After-change forced-fresh command: `mkdir -p build/cron-20261014-frontier-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-frontier-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-frontier-after/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-530 diagnostics are gone; next tupleobject blocker is line 733 (`Py_ssize_t nargs`) with C2275/C2146/C2065, followed by separate line 917 designated initializer and later declaration/loop errors. Wine also logged that the project-local Wayland socket path exceeds 108 bytes; compilation nevertheless ran to tupleobject.c and returned compiler exit 2. Capture: `build/cron-20261014-frontier-after/probe.log`. +- All tupleobject tests after updating the expectation: 11 passed; `git -C cpython diff --check -- Objects/tupleobject.c` and outer diff checks on the two focused tests and status — exit 0. Baseline tag/commit unchanged. +- No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c`, new `scripts/vc6-tupleobject-repeat-dest-end-c89.test.py`, updated `scripts/vc6-tupleobject-repeat-dest-c89.test.py`, and this status entry. Next frontier: in a separate TDD slice, force-fresh confirm and address only `tuplerepeat()`'s late `Py_ssize_t nargs` declaration at line 733. No completed port is claimed. + +--- + +## Latest run (fresh `tuplerepeat()` `dest_end` frontier; implementation lane unavailable) + +Date: 2026-10-14 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved the existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previous status-recorded `tuplerepeat()` `dest_end` blocker was force-reprobed before any implementation work and remains current. One focused coding-agent delegation was attempted for this single defect family, but failed before child startup because the configured Hermes delegation provider requires unavailable Anthropic credentials. No child edits occurred. Per delegation/TDD constraints, this run is diagnostics-only: no RED/GREEN cycle and no source or regression-test edit is claimed. The existing tupleobject tests were run as regression diagnostics only. + +Exact verification: + +- Forced-fresh command: `mkdir -p build/cron-20261014-destend-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-destend-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-destend-reprobe/probe.log 2>&1` — probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. First stable diagnostics: `tupleobject.c(530)` C2275 (`PyObject`), C2065 (`dest_end`), and C2100. Later distinct diagnostics include `nargs` at line 732, designated initializer at 916, `index` at 1235, and C89 loop declarations at 1256/1275. Full compiler capture: `build/cron-20261014-destend-reprobe/probe.log`. +- Focused coding-agent delegation for only the confirmed `dest_end` declaration — failed before startup: no Anthropic credentials/configured provider; no child edits. +- `set -e; for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; done` — exit 0; all ten tupleobject regression scripts passed. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- PORT_STATUS.md` — exit 0. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This remains compiler-probe progress only. + +Files changed this run: `PORT_STATUS.md` only; probe evidence is under `build/cron-20261014-destend-reprobe/`. Next frontier: retry one strictly TDD coding slice for only `tuplerepeat()`'s `dest_end` declaration when the delegated coding provider can start. Preserve the assignment at its original evaluation point; keep all later tupleobject diagnostics separate. No port completion is claimed. + +--- + +## Latest verified slice (`tuplerepeat()` destination declaration; frontier advances) + +Date: 2026-10-14 06:42 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded first blocker was force-reprobed before implementation and remains in `tuplerepeat()`: the late `PyObject **dest = np->ob_item` declaration. One focused Codex CLI coding lane (`codex-cli 0.153.4`, logged in, workspace-write/ephemeral; session `01a1392a-bdf0-7a73-948c-1dc78e92a676`) followed strict TDD. New `scripts/vc6-tupleobject-repeat-dest-c89.test.py` failed before production edit (exit 1) on the intended assertion that `dest` belongs to the opening declaration block. The sole production edit declares `dest` with the other function locals and assigns `dest = np->ob_item` immediately after successful tuple allocation at the original evaluation point. `dest_end` and all later declaration families remain untouched. A pre-edit hash snapshot covered 192 existing changed/untracked paths across both repositories; verification confirmed all 191 unrelated files unchanged and the CPython source differed only by this declaration/assignment split. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261014-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-reprobe/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. First stable diagnostics were in `tupleobject.c(528)` C2275/C2065/C2100 for late `PyObject **dest`; separate `dest_end` at line 529 and later tupleobject diagnostics followed. Capture: `build/cron-20261014-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-repeat-dest-c89.test.py` before source edit — exit 1, expected opening-declaration assertion. GREEN: same command after source edit — exit 0. +- Applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all ten tupleobject regression scripts pass. +- After-change forced-fresh command: `mkdir -p build/cron-20261014-after-tuplerepeat-dest/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-after-tuplerepeat-dest/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-after-tuplerepeat-dest/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. Former `tuplerepeat()` `dest` diagnostics are gone. The new first blocker is `tupleobject.c(530)` C2275/C2065/C2100 for the distinct late `PyObject **dest_end` declaration; later diagnostics include `nargs` at line 732, designated initializer at 916, `index` at 1235, and C89 loop declarations at 1256/1275, all untouched. The probe also logged non-fatal Wine errors that its project-local `XDG_RUNTIME_DIR` wayland socket path exceeds 108 bytes; compilation proceeded to `tupleobject.c` and returned the compiler's exit 2. Capture: `build/cron-20261014-after-tuplerepeat-dest/probe.log`. +- Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- scripts/vc6-tupleobject-repeat-dest-c89.test.py` — exit 0. Baseline tag/commit remain unchanged. +- No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compile-frontier progress only, not a completed port. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `tuplerepeat()` `dest` declaration/assignment split), new `scripts/vc6-tupleobject-repeat-dest-c89.test.py`, and this status entry. Next frontier: in a separate TDD slice, force-fresh confirm and address only `tuplerepeat()`'s `dest_end` declaration. Keep the later tupleobject diagnostics separate. + +--- + +## Latest verified slice (`tupleconcat()` b declaration; host frontier advances) + +Date: 2026-10-14 UTC + +Preserved pre-existing outer/nested work. No reset, clean, stash, commit, push, or compatibility-patch regeneration. Codex sandbox probe was blocked by Wine server-lock permissions; host tools completed the real forced-fresh probes. Production change only splits `tupleconcat()`'s late `PyTupleObject *b` declaration into an opening declaration and an assignment at its original point after type validation. Added `scripts/vc6-tupleobject-concat-b-c89.test.py`. + +Verification: +- Before forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/manual-20261014-host-before/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh`, stdout/stderr in `build/manual-20261014-host-before/probe.log`: exit 2; `total=108 compiled=107 cached=0 skipped=0`; first errors at tupleobject.c(471), C2275/C2065 for b. Earlier foreground attempt timed out at 180s, was confirmed stopped, then rerun as a tracked background process to completion. +- RED: focused new regression exit 1 on intended opening-declaration assertion. GREEN after minimal source edit: exit 0. +- All nine tupleobject regression scripts pass with explicit failure propagation. Scoped nested diff check passes. +- After forced-fresh probe: identical command using `build/manual-20261014-host-after/runtime`, captured in `build/manual-20261014-host-after/probe.log`: exit 2; `total=108 compiled=107 cached=0 skipped=0`. Former tupleconcat errors are gone. First remaining blocker advances to `tuplerepeat()` at tupleobject.c(528), C2275/C2065 on late `PyObject **dest`; separate dest_end at 529 remains untouched. + +Compile-frontier progress only; no linked DLL/interpreter, Wine interpreter execution, or Windows 98 runtime proof. Next slice: reproduce and isolate tuplerepeat's destination declaration. Nested source edits are not yet regenerated into the tracked compatibility patch. + +--- + +## Latest run (tupleconcat slice blocked before compilation) + +Date: 2026-10-14 UTC + +Read README.md, the top of PORT_STATUS.md, and the legacy-python-porting skill and references/cpython-msvc600-frontier.md. Nested baseline: `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549` (exit 0); `git -C cpython describe --tags --exact-match` → `v3.11.16` (exit 0). Nested HEAD is detached (`git -C cpython symbolic-ref -q --short HEAD`, exit 1); outer branch is `main`. Host: Linux 7.0.0-38-generic x86_64 GNU/Linux; `wine --version` → `wine-10.0 (Ubuntu 10.0~repack-12ubuntu1)` (exit 0). The MSVC6 compiler never started, so no fresh compiler banner was obtained. + +- Before edits: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0, all eight standalone regressions passed. +- Exact fresh-frontier command: `mkdir -p build/manual-20261014-tupleconcat-before/runtime && XDG_RUNTIME_DIR="$PWD/build/manual-20261014-tupleconcat-before/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/manual-20261014-tupleconcat-before/probe.log 2>&1` — exit 1, also saved in `build/manual-20261014-tupleconcat-before/exit-status.txt`. Summary: `total=1 compiled=0 cached=0 skipped=0`. +- The first attempted source was `cpython/Modules/getpath.c`. Wine reported `sock_init: ERROR in sock_check_pollhup()` and `wineserver: error creating /run/user/1000/wine/server-801-136fb0/lock: Read-only file system`. This is an environment blocker, not a verified C diagnostic. The previously recorded `tupleobject.c(471)` late `b` declaration remains unconfirmed in this run. +- No production or regression edits, no RED/GREEN cycle, and no after-frontier run: stopped at the sandbox/Wine blocker as requested, without bypassing it or reconstructing a harness. No linked DLL/interpreter or runtime evidence. +- Preservation snapshot: `build/manual-20261014-tupleconcat-before/hashes.json` records 190 existing dirty/untracked files plus both Git indexes, excluding ignored generated objects. Final comparison confirmed all 189 unrelated files and both indexes unchanged, tupleobject.c byte-identical, and the complete previous PORT_STATUS.md retained as the suffix after this prepend. Verification: `build/manual-20261014-tupleconcat-before/preservation.txt`. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- PORT_STATUS.md` — exit 0. + +Only PORT_STATUS.md was edited; local evidence is under `build/manual-20261014-tupleconcat-before/`. No reset, clean, stash, discard, commit, push, publication, broad patch regeneration, global configuration change, or backup-file operation. Next slice requires a working permitted Wine environment and a fresh frontier before choosing any source edit. + +--- + +## Latest run (`_PyTuple_FromArraySteal()` success-loop C89 index; frontier advances) + +Date: 2026-10-14 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a1383e-4af6-7733-9273-023e090009ed`) used strict TDD for the currently confirmed `_PyTuple_FromArraySteal()` success-path C99 loop index. The focused regression was updated and run before production edits; RED exit 1 on the intended assertion that the success loop must reuse the function-scope `i`. The only production change replaces `for (Py_ssize_t i = 0; ...)` with `for (i = 0; ...)`; loop condition/increment and item assignment/order are unchanged. The next late `PyObject *item` declaration remains untouched. Two directly applicable pre-existing declaration/order tests contained the old loop syntax in their expected full-function text; after the coding lane reported these stale expectations, they were narrowly aligned to the corrected loop. No unrelated paths were changed. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261014-run2/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-run2/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-run2/probe.log 2>&1` — exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics at `tupleobject.c(419)` were C2143/C2059 for the success-loop declaration. Capture: `build/cron-20261014-run2/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-from-array-steal-c89.test.py` before source edit — exit 1 with `AssertionError: _PyTuple_FromArraySteal: success loop must reuse function-scope i with assignment`. GREEN after source edit — exit 0. +- Applicable regressions: `python3 scripts/vc6-tupleobject-from-array-steal-c89.test.py` and `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; done` — exit 0; all eight tupleobject tests passed. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- scripts/vc6-tupleobject-from-array-steal-c89.test.py scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py` — exit 0. +- Post-change forced-fresh command: `mkdir -p build/cron-20261014-run2-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-run2-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-run2-after/probe.log 2>&1` — exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-419 diagnostics are gone; first remaining tupleobject blocker advances to `tupleobject.c(471)` in `tupleconcat()`, C2275/C2065 on late initialized `PyTupleObject *b = (PyTupleObject *)bb;`. Later independent errors at lines 527+ remain untouched. Capture: `build/cron-20261014-run2-after/probe.log`. +- The Codex hash comparison confirmed only the intended two files changed during its lane and both repository indexes plus unrelated file contents, including `PORT_STATUS.md`, were preserved. Exact source diff and subsequent narrow fixture updates were inspected. No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred; this is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (one loop initializer), `scripts/vc6-tupleobject-from-array-steal-c89.test.py`, and directly applicable expectation updates in `scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py` and `scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py`, plus this status entry. Next frontier: fresh probe before any edit; if unchanged, isolate only `tupleconcat()`'s late `b` declaration at line 471 with a single strict-TDD slice. No completed port is claimed. + +--- + +## Latest run (fresh tupleobject probe; coding-agent provider unavailable) + +Date: 2026-10-14 00:21 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine probe shows the status-recorded `_PyTuple_FromArraySteal()` `dst` declaration blocker is stale: the current source already hoists `tuple`, `i`, and `dst`. The actual first remaining blocker in this function is the distinct loop-local `for (Py_ssize_t i = 0; ...)` at line 419, followed by a separate `PyObject *item` declaration at line 420; neither was changed. A focused coding-agent delegation was attempted for the single recorded `dst` slice, but failed before child startup because the Hermes runtime requires the unavailable `anthropic` package and lazy installs are disabled. Therefore this run is diagnostics-only: no TDD RED/GREEN, source/test edit, or implementation claim. + +Exact verification: + +- Forced-fresh command: `mkdir -p build/cron-20261014-current/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-current/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable tupleobject diagnostics are C2143 at `tupleobject.c(419)` (missing semicolon before `type`, repeated) and C2059 at `(419)` (syntax error `)`), on the loop's late `Py_ssize_t i` declaration. The subsequent `PyObject *item` declaration and other tupleobject diagnostics remain distinct and untouched. Capture: `build/cron-20261014-current/probe.log`. +- Coding-agent prerequisite: `codex --version` → `codex-cli 0.153.4`; `codex login status` → logged in. The requested focused delegation could not start: Hermes delegation returned `anthropic` package required, venv not installed, lazy installs disabled. No child edits occurred. +- Existing regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all eight focused tupleobject scripts passed, including the existing `dst` and `tuple` checks. +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- PORT_STATUS.md` — exit 0. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is probe progress only, not a completed port. + +Files changed this run: `PORT_STATUS.md` only; diagnostic capture is under `build/cron-20261014-current/`. Next frontier: once a coding-agent provider can start, use one strict-TDD slice for only the currently confirmed loop index declaration at `_PyTuple_FromArraySteal()` line 419; leave the following `item` declaration separate. No port completion is claimed. + +--- + +## Latest run (`_PyTuple_FromArraySteal()` allocation-failure loop index; frontier advances) + +Date: 2026-10-13 20:03 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded tuple declaration frontier was stale. Forced-fresh MSVC600/Wine probe compiled `_blake2/blake2s_impl.c`; the recorded `_PyTuple_FromArraySteal()` tuple declaration is already hoisted in the present checkout, so the actual first blocker was its distinct NULL-path loop-index declaration at line 411 (`for (Py_ssize_t i = 0; ...)`). One focused Codex CLI coding lane (`codex-cli 0.153.4`, logged in, workspace-write/ephemeral; session `01a136d7-1fdc-7f83-aef9-dd39ed531458`) used strict TDD. The new focused test failed first on its intended assertion that function-scope `Py_ssize_t i` must precede statements. The sole production edit for this slice hoists `Py_ssize_t i;` into `_PyTuple_FromArraySteal()`'s declaration block and changes only the allocation-failure loop initializer to `i = 0`; the empty-tuple return, allocation, failure test, DECREF loop, and NULL return order are unchanged. The directly related pre-existing `vc6-tupleobject-from-array-steal-tuple-c89.test.py` expectation was updated to encode the new declaration placement and loop form. The later `dst`, success-path loop, and `item` declarations remain untouched. A hash snapshot covered 188 pre-existing dirty/untracked files in both repositories; 186 files outside the two intentionally involved test/source paths remained byte-identical, and the source diff was restricted to this function's index declaration/initializer. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261014-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-reprobe/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The first stable `tupleobject.c` diagnostics were line 411 C2143/C2065 (`i` undeclared), followed by separate `dst`/success-path diagnostics at lines 416-418. Capture: `build/cron-20261014-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-from-array-steal-c89.test.py` before the source edit — exit 1 on the intended assertion that function-scope `i` must precede statements. GREEN after edit — exit 0. +- Applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit $?; done` — exit 0; all seven tupleobject tests passed (`alloc`, `dealloc`, `from-array`, `from-array-steal`, `from-array-steal-tuple`, `new`, `pack`). Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and outer `git diff --check` for the two focused tests — exit 0. +- Post-change forced-fresh command: `mkdir -p build/cron-20261014-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-after/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former NULL-path loop-index diagnostics are gone. The first remaining errors are now in the same function at line 417 on the distinct late `PyObject **dst` declaration, followed by the independent second loop and item declaration diagnostics at lines 418-420; left untouched. Capture: `build/cron-20261014-after/probe.log`. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only, not port completion. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only the NULL-path loop index declaration split within `_PyTuple_FromArraySteal()`), new `scripts/vc6-tupleobject-from-array-steal-c89.test.py`, updated `scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py`, and this status entry. Next frontier: force-fresh probe before editing; if unchanged, isolate only `_PyTuple_FromArraySteal()`'s `dst` declaration at line 416/417 in its own TDD slice. Keep the second loop and item declaration separate. Do not claim port completion. + +--- + +## Latest run (forced-fresh frontier; coding lane unavailable) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh probe confirms the recorded tuple frontier had advanced: `_blake2/blake2s_impl.c` compiles, and the first blocker is now `Objects/tupleobject.c:_PyTuple_FromArraySteal()` at line 408 (`PyTupleObject *tuple = tuple_alloc(n)`). VC6 emits C2275/C2065 (`PyTupleObject`/`tuple`); subsequent errors at lines 410 and 415-418 are further declaration families, left untouched. One focused coding-agent delegation was attempted for only this declaration family with strict TDD, but failed before startup because the Anthropic package is unavailable and lazy installs are disabled. Accordingly, this run is diagnostics-only: no source/test edit or TDD cycle is claimed. + +Exact verification: + +- Forced-fresh command: `mkdir -p build/cron-20261013-current-frontier/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013-current-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013-current-frontier/probe.log 2>&1` — actual compiler/probe exit 2. Summary: `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` successfully compiled. First diagnostics: `tupleobject.c(408)` C2275/C2065 (`PyTupleObject`/`tuple`), then line 410 C2143/C2065 `i`; later distinct destination/item declarations follow. Capture: `build/cron-20261013-current-frontier/probe.log`. +- Focused coding-agent delegation — failed before child startup: required `anthropic` package unavailable; lazy installs disabled. No child edits occurred. +- Existing applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all five existing tupleobject tests passed. No new test for `_PyTuple_FromArraySteal()` was added. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- PORT_STATUS.md` — exit 0. +- No standalone compiler banner, linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is probe progress only, not port completion. + +Files changed this run: `PORT_STATUS.md` only; diagnostic capture is under `build/`. Next frontier: when a coding lane can start, TDD only the line-408 tuple declaration, preserving its evaluation after the `n == 0` return; then run focused VC6 probe and tupleobject regressions. Leave loop and destination declarations separate. + +--- + +## Latest run (`_PyTuple_FromArray()` loop-index declaration; frontier advances) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and the legacy-toolchain CPython reference before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Exact CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine probe confirmed the previous destination declaration fix and advanced to the next isolated defect: `_PyTuple_FromArray()`'s C99 loop index declaration at line 392. One focused Codex CLI lane (0.153.4, OpenAI provider, workspace-write/ephemeral; session `01a13575-b737-7212-918b-235d4922a919`) followed strict TDD. It updated the existing focused `scripts/vc6-tupleobject-from-array-c89.test.py`; the RED run failed at the intended assertion because `i` was absent from the declaration block. The only production change hoists `Py_ssize_t i` into that block and changes the loop initializer to `i = 0`. Loop condition/increment, item acquisition, INCREF/store, GC tracking, error/early-return behavior remain unchanged; no other function was changed. No existing changes were reset, cleaned, stashed, discarded, or overwritten. This status file was not touched by the coding lane. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh: `mkdir -p build/cron-20261013-index-frontier/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013-index-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013-index-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors at `tupleobject.c(392)` were C2143 and C2065 `i`; subsequent diagnostics were at distinct locations. Full capture: `build/cron-20261013-index-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-from-array-c89.test.py` before production edit — exit 1 on expected missing `i` declaration assertion. +- Focused GREEN and applicable regressions: `python3 scripts/vc6-tupleobject-from-array-c89.test.py`; `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all five tupleobject tests passed. +- Post-change forced-fresh: `mkdir -p build/cron-20261013-index-frontier-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013-index-frontier-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013-index-frontier-after/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled and the changed `_PyTuple_FromArray()` passes. Its previous line-392 diagnostics are gone. The first remaining errors advance into the distinct `_PyTuple_FromArraySteal()` function at line 408 (C2275/C2065 `tuple`), followed by its loop `i` declaration and `dst` declaration diagnostics; left untouched. Capture: `build/cron-20261013-index-frontier-after/probe.log`. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `_PyTuple_FromArray()` loop-index declaration split), `scripts/vc6-tupleobject-from-array-c89.test.py` (focused C89/order expectation), and this status entry. Next frontier: force-fresh probe before editing; if unchanged, isolate only the first `_PyTuple_FromArraySteal()` declaration defect family, leaving its later loop/destination declarations for separate slices. No completed port is claimed. + +--- + +## Latest run (`_PyTuple_FromArray()` destination declaration; frontier advances) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded `_PyTuple_FromArray()` destination declaration frontier was force-reprobed before editing and confirmed: `_blake2/blake2s_impl.c` compiled, then VC6 reported `tupleobject.c(390)` C2275 (`PyObject`), C2065 (`dst`), and C2100. A focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a134fc-f2d8-7d63-bbf7-7a7decfe9e6c`) used strict TDD. It first updated `scripts/vc6-tupleobject-from-array-c89.test.py`; the test failed before production change with the expected assertion that `dst` must be declared before the empty-tuple check. The sole new production change hoists `PyObject **dst` to `_PyTuple_FromArray()`'s declaration block and assigns `dst = tuple->ob_item` immediately after the successful allocation NULL check. The loop index and item declarations, evaluation/refcount/store/GC order, and error/early-return behavior remain untouched. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p build/cron-20261013-refresh/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013-refresh/probe.log 2>&1` — probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: `tupleobject.c(390)` C2275/C2065/C2100. Capture: `build/cron-20261013-refresh/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-from-array-c89.test.py` before production edit — exit 1 on the expected missing `dst` declaration assertion. GREEN: same command after edit — exit 0. +- Applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; done` — exit 0; all five tests (`alloc`, `dealloc`, `from-array`, `new`, `pack`) pass. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- scripts/vc6-tupleobject-from-array-c89.test.py` — exit 0. +- Post-change forced-fresh command: `mkdir -p build/cron-20261013-refresh-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013-refresh-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013-refresh-after/probe.log 2>&1` — probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `_PyTuple_FromArray()` line-390 `dst` diagnostics are gone. The first remaining diagnostics advance to line 392, C2143 and C2065 `i` on the loop's late declaration; later separate tupleobject blockers remain untouched. Capture: `build/cron-20261013-refresh-after/probe.log`. +- Exact CPython tag/commit remain unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This remains compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (the `dst` declaration/assignment split only), `scripts/vc6-tupleobject-from-array-c89.test.py` (focused expectation update), and this status entry. Next: force-fresh probe before editing; if unchanged, isolate only the next loop-index declaration in `_PyTuple_FromArray()` at line 392 in its own TDD slice. Do not claim port completion. + +--- + +## Previous run (fresh tuple frontier; coding-agent prerequisite unavailable) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyTuple_FromArray()` line-389 frontier was force-reprobed before any coding. It remains the first stable blocker: `_blake2/blake2s_impl.c` compiled, then VC6 reported `tupleobject.c(390)` C2275 (`PyObject`), C2065 (`dst`), and C2100; subsequent line-391 diagnostics are cascades from the same late initialized declaration family. One focused coding-agent delegation was attempted as required for implementation, but failed before child startup because the Hermes runtime has no `anthropic` package and lazy installs are disabled. Consequently this run is diagnostics-only: no TDD RED/GREEN cycle or source/test implementation is claimed. No source work was attempted without the requested coding lane. + +Exact verification: + +- Forced-fresh command: `mkdir -p build/cron-20261013-current/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013-current/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics at `cpython\\Objects\\tupleobject.c(390)`: C2275, C2065 `dst`, C2100; cascades follow at line 391. Full capture: `build/cron-20261013-current/probe.log`. +- Focused coding-agent delegation — failed before child startup: missing `anthropic`; lazy installs disabled. No child edits occurred. +- Applicable existing tupleobject regression suite: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all five tests pass (`alloc`, `dealloc`, `from-array`, `new`, `pack`). These are pre-existing tests; no new TDD cycle was performed. +- `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- PORT_STATUS.md` — exit 0. Baseline tag/commit verified unchanged. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This remains compiler-probe progress only. + +Files changed this run: `PORT_STATUS.md` only. `build/cron-20261013-current/probe.log` is a diagnostic artifact. Next frontier: resolve the coding-agent provider prerequisite, then use one strict-TDD slice for only `_PyTuple_FromArray()`'s `dst` declaration, preserving its evaluation point after successful tuple allocation; rerun the focused VC6 probe and applicable regression suite. Leave the subsequent loop declaration and other tupleobject blockers separate. + +--- + +## Latest run (`_PyTuple_FromArray()` first declaration hoisted; frontier advances) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded tupleobject frontier was force-reprobed before editing and confirmed: `_blake2/blake2s_impl.c` compiled, then `Objects/tupleobject.c(385)` failed on the late initialized `PyTupleObject *tuple` declaration (C2275/C2065). One focused Codex CLI lane (`codex-cli 0.153.4`, logged in, workspace-write/ephemeral) implemented only this declaration family using TDD. The new regression's RED failed with the expected assertion before the production change. The edit hoists `PyTupleObject *tuple;`, assigning `tuple = tuple_alloc(n);` at the original point after the `n == 0` early return. Distinct `dst`, `i`, and `item` declarations and all operation/refcount/error order remain unchanged. The coding lane's preservation snapshot covered 4,804 paths across both repositories; only the intended CPython source and new focused test differ. No unrelated existing modifications were changed. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-reprobe/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics: `tupleobject.c(385)` C2275 (`PyTupleObject`) and C2065 (`tuple`); later distinct declarations at lines 389-390 remain. Capture: `build/cron-current-reprobe/probe.log`. +- TDD RED/GREEN: `python3 scripts/vc6-tupleobject-from-array-c89.test.py` — exit 1 before the production edit at the intended declaration-order assertion, then exit 0 after it. +- Applicable regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit $?; done` — exit 0; all five tupleobject scripts pass, including `_PyTuple_FromArray()`. +- Initial post-change forced-fresh attempt in the coding lane exited 1 before compilation because Wine failed to create a lock under `/run/user/1000` (`Read-only file system`). Wine smoke check `XDG_RUNTIME_DIR="$PWD/build/cron-current-coder/retry-runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c ver` then exited 0 (`Microsoft Windows 10.0.19043`). Retried the forced-fresh command using that project-local runtime and captured `build/cron-current-coder/probe-retry.log`; actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled, and the former line-385 errors are gone. The next first blocker is `tupleobject.c(390)` C2275/C2065 (`PyObject`/`dst`); other separate tupleobject blockers remain untouched. +- `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- PORT_STATUS.md scripts/vc6-tupleobject-from-array-c89.test.py` — exit 0. Exact baseline tag/commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (one declaration/assignment split), new `scripts/vc6-tupleobject-from-array-c89.test.py`, and this status entry. Next: force-fresh probe before editing; if unchanged, address only the next first blocker in `_PyTuple_FromArray()` (`dst` at line 389), in a separate TDD slice. Do not claim a completed port. + +--- + +## Previous run (fresh tupleobject frontier re-probe; no coding agent available) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Exact CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine re-probe confirms the recorded `_PyTuple_FromArray()` frontier at line 385 remains the first stable blocker. A focused coding-agent lane was not started: `codex-cli 0.153.4` is installed, but the required delegation tool/provider is not available to this scheduled runtime. Per the workflow, this is diagnostics-only: no source or test edits and no TDD cycle are claimed. The subsequent declaration families at lines 389-390 and other tupleobject functions remain distinct and untouched. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261013T-run/reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013T-run/reprobe/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `Objects/tupleobject.c(385)` C2275 (`PyTupleObject`) and C2065 (`tuple`). Later same-function errors at lines 389-390 and separate tupleobject blockers follow. Capture: `build/cron-20261013T-run/reprobe/probe.log`. +- Baseline verified: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed this run: `PORT_STATUS.md` only. Next: delegate one isolated TDD slice for `_PyTuple_FromArray()`'s declaration at line 385 once the coding-agent lane is available; preserve evaluation timing and leave the distinct declarations at 389-390 untouched. No completed port is claimed. + +--- + +## Previous latest run (`tupledealloc()` C89 index declaration; frontier advances) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine source-list probe confirmed the recorded tupleobject frontier had advanced beyond `PyTuple_New()`: `_blake2/blake2s_impl.c` compiled, and the first stable blocker was the late initialized `Py_ssize_t i` in `tupledealloc()` after `Py_TRASHCAN_BEGIN`. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a13321-82e3-7b70-9085-e1247494109e`) used strict TDD. New `scripts/vc6-tupleobject-dealloc-c89.test.py` failed before the production edit with the expected assertion that `i` must be declared before the initial empty-tuple checks. The sole production change declares `i` at function entry and retains `i = Py_SIZE(op);` immediately after `Py_TRASHCAN_BEGIN`; decref, freelist/free, and trashcan ordering are unchanged. The lane captured hashes for all pre-existing dirty/untracked paths in both repositories and verified they remained byte-identical; only the intended CPython edit and new test were added. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261013T-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors: `tupleobject.c(209)` C2143 and `(210)` C2065 `i`; subsequent independent errors included `tuplerepr` line 221 and later tupleobject functions. Full capture: `build/cron-20261013T-current/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-dealloc-c89.test.py` before production edit — exit 1 on the intended declaration-placement assertion. GREEN: same command after edit — exit 0. +- Applicable regression loop: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all four scripts (`alloc`, `dealloc`, `new`, `pack`) pass. Scoped `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- scripts/vc6-tupleobject-dealloc-c89.test.py` — both exit 0. Diff/snapshot inspection confirms the only production changes are the intended declaration/assignment split and all pre-existing work was preserved. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261013T-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former `tupledealloc()` line-209/210 diagnostics are gone. First remaining errors advance to `Objects/tupleobject.c(385)` C2275/C2065 on the late initialized `PyTupleObject *tuple` in `_PyTuple_FromArray()`; separate later C89 declarations in that function and other tupleobject functions remain untouched. Full capture: `build/cron-20261013T-post-probe.log`. +- Exact baseline tag/commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `tupledealloc()` index declaration split), new `scripts/vc6-tupleobject-dealloc-c89.test.py`, and this status entry. Next frontier: force-fresh probe before editing; if unchanged, isolate the first `_PyTuple_FromArray()` blocker at line 385 in its own TDD slice. No completed port is claimed. + +--- + +## Latest run (`PyTuple_New()` C89 loop declaration; frontier advances) + +Date: 2026-10-12 17:58 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 skill reference before acting. Preserved pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded tupleobject frontier was force-reprobed. `_blake2/blake2s_impl.c` compiled, and the prior `PyTuple_New()` C99 loop declaration at line 80 is confirmed as the first blocker. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a13148-65d0-7250-a18e-5b4a768dcaa8`) followed TDD. New `scripts/vc6-tupleobject-new-c89.test.py` failed before the source edit (exit 1) on the intended declaration assertion. The sole source change hoists `Py_ssize_t i` into the declaration block and changes only the `for` initializer to assign `i = 0`; iteration and tuple initialization order remain unchanged. Both tupleobject-specific regression scripts pass. The child’s first probe attempt exited 1 before compilation due Wine server lock creation; Hermes independently reran the forced-fresh probe with a fresh project-local runtime directory. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T175809Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors were the recorded `tupleobject.c(80)` C2143/C2065/C2059 family. +- TDD RED: `python3 scripts/vc6-tupleobject-new-c89.test.py` — exit 1, intended assertion on missing function-scope `i` declaration. +- TDD GREEN and focused regressions: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; done` — both `vc6-tupleobject-alloc-c89.test.py` and `vc6-tupleobject-new-c89.test.py` exit 0. A snapshot diff confirmed no tupleobject changes outside this function; `PORT_STATUS.md` checksum was unchanged during coding. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T175809Z-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled and the `PyTuple_New()` line-80 diagnostics are gone. The next first errors are `Objects/tupleobject.c(168)` C2275/C2065 on late-initialized `PyTupleObject *result` in `PyTuple_Pack()`; later independent tupleobject errors remain untouched. Full before/after captures: `build/cron-20261012T175809Z/probe.log` and `build/cron-20261012T175809Z-after/probe.log`. +- The exact baseline tag/commit remains unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (the `PyTuple_New()` loop index declaration only), new `scripts/vc6-tupleobject-new-c89.test.py`, and this status entry. Next: force-fresh probe before edits, then consider only the newly confirmed `PyTuple_Pack()` declaration at line 168 in a separate TDD slice; keep later blockers separate. No completed port is claimed. + +--- + +## Latest run (tupleobject frontier reconfirmed; coding lane unavailable) + +Date: 2026-10-12 13:36 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved pre-existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `tuple_alloc()` frontier was force-reprobed before any edits and remains current. `_blake2/blake2s_impl.c` compiles. The first stable errors are `Objects/tupleobject.c(43)` C2275 (`PyTupleObject`) and C2065 (`op`) on `PyTupleObject *op = maybe_freelist_pop(size);`. Distinct later diagnostics include a C99 loop declaration at line 79 and further tupleobject issues; none were changed. One focused coding-agent delegation was attempted for only line 43, but failed before child startup because the Hermes runtime requires the unavailable `anthropic` Python package and lazy installs are disabled. Thus this was diagnostics-only: no TDD RED/GREEN cycle, source/test changes, or regression tests are claimed. + +Exact verification: + +- `mkdir -p build/cron-20261012T133609Z/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261012T133609Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T133609Z/probe.log 2>&1` — probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `tupleobject.c(43)` C2275/C2065; separate line-79 C2143/C2065/C2059 diagnostics follow. Full log: `build/cron-20261012T133609Z/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Focused coding delegation — failed before child startup: missing `anthropic`; lazy installs disabled. No child edits or test runs occurred. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. This is compiler-probe progress only; no port completion is claimed. Next: retry the single TDD slice for `tuple_alloc()` line 43 when a coding-agent provider can start, preserving the `maybe_freelist_pop(size)` evaluation point; keep line 79 and later tupleobject blockers separate. + +--- + +## Previous run (tupleobject frontier reconfirmed; coding lane unavailable) + +Date: 2026-10-12 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded structseq frontier was force-reprobed before editing. `_blake2/blake2s_impl.c` and `Objects/structseq.c` compile; the current first blocker is `Objects/tupleobject.c:tuple_alloc()` at line 43, on the late initialized declaration `PyTupleObject *op = maybe_freelist_pop(size);`. One focused coding-subagent delegation was attempted for this single declaration family using installed `codex-cli 0.153.4`, but failed before child startup because the Hermes runtime requires the unavailable `anthropic` Python package and lazy installs are disabled. No source/test change or TDD RED/GREEN cycle was made; this run is diagnostics-only. The existing changes and subsequent tupleobject diagnostics were left untouched. + +Exact verification: + +- `mkdir -p build/cron-20261012Tcurrent-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261012Tcurrent-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012Tcurrent-reprobe/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors: `tupleobject.c(43)` C2275 (`PyTupleObject`) and C2065 (`op`), with cascading warnings. The next distinct diagnostics include line 79; later errors in that file were not addressed. Full capture: `build/cron-20261012Tcurrent-reprobe/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Outer and detached repository pre-existing changes were present and preserved. +- Focused coding-agent delegation — failed before child startup: `anthropic` package unavailable; lazy installs disabled. No child edits or tests occurred. No focused tupleobject regression script exists in `scripts/` at this time. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next: retry one focused TDD coding lane for only the `tuple_alloc()` declaration at line 43 once the coding-agent provider can start; preserve the `maybe_freelist_pop(size)` evaluation point and leave the distinct line-79 and later tupleobject blockers separate. + +--- + +## Latest run (`_PyStructSequence_NewType()` C89 slot initialization; frontier advances) + +Date: 2026-10-12 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Exact CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded structseq designated-initializer frontier was first force-reprobed. Initial invocation failed before compilation because Wine could not create its server lock (`/run/user/1000/wine/server-801-136fb0/lock`); `wine cmd /c ver` then succeeded when run with a project-local `XDG_RUNTIME_DIR`. The exact forced-fresh probe was retried successfully. `_blake2/blake2s_impl.c` compiled; the prior `structseq.c` designated-initializer C2059 diagnostics at lines 590-597 were current. One focused Codex CLI implementation lane (codex-cli 0.153.4, session `01a12f6b-00a0-78a3-95e0-f1c894f09703`, workspace-write/ephemeral) followed test-first workflow. New `scripts/vc6-structseq-newtype-slots-c89.test.py` failed before the source change on the compound literals. The production change replaced only eight compound-literal assignments with `.slot` and `.pfunc` field assignments; slot values, order, casts, and zero sentinel are preserved. `PyStructSequence_NewType()` and all other source regions were left unchanged. Independent baseline hash check captured 4,799 tracked/untracked files across both repos before coding and verified all previously existing file contents remained unchanged except the intended `cpython/Objects/structseq.c` edit; `PORT_STATUS.md` was not edited by the coding lane. + +Exact verification: + +- Initial forced-fresh command at `build/cron-20261012T-current`: exit 2; `total=107 compiled=106 cached=0 skipped=0`, `_blake2/blake2s_impl.c` compiled. First stable errors were `Objects/structseq.c(590-597)` C2059 on the compound-literal braces; separate later errors were in `PyStructSequence_NewType()` at lines 624-626. Capture: `build/cron-20261012T-current/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-newtype-slots-c89.test.py` before production edit — exit 1 with the intended assertion rejecting compound literals. GREEN: same command after edit — exit 0; exact eight slot pairs and ordering verified. +- Focused regressions: `for test in scripts/vc6-structseq-*.test.py; do python3 "$test" cpython/Objects/structseq.c || exit; done` — all nine scripts exited 0. Host `python3 cpython/Lib/test/test_structseq.py` — 17 tests, exit 0; `python3 cpython/Lib/test/_test_embed_structseq.py` — 2 tests, exit 0. These host tests do not compile or execute the edited C source. +- Scoped whitespace checks: `git -C cpython diff --check -- Objects/structseq.c` and `git diff --check -- scripts/vc6-structseq-newtype-slots-c89.test.py` — both exit 0. Byte/hash comparison confirmed only the intended slot initialization changed among pre-existing paths. +- Post-change forced-fresh command: `mkdir -p build/cron-20261012T-current-post/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-current-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-current-post/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `structseq.c` designated-initializer diagnostics are gone; the first stable blocker advances to `Objects/tupleobject.c` beginning at line 43 (C2275/C2065 declaration diagnostics), with further C89 declaration/initializer diagnostics later in that file. Capture: `build/cron-20261012T-current-post/probe.log`. +- Exact CPython tag and commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/structseq.c` (only `_PyStructSequence_NewType()` slot assignments), new `scripts/vc6-structseq-newtype-slots-c89.test.py`, and this status entry. Next: force-fresh probe before editing, then address only the newly confirmed first `Objects/tupleobject.c` blocker in a separate TDD slice; leave subsequent tupleobject diagnostics separate. No port completion is claimed. + +--- + +## Previous run (`initialize_structseq_dict()` C89 declaration family; frontier advances) + +Date: 2026-10-12 07:15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the applicable CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all existing root and detached CPython modifications; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded frontier was force-reprobed before editing. `_blake2/blake2s_impl.c` compiled. The first stable MSVC600/Wine diagnostics were in `Objects/structseq.c:initialize_structseq_dict()` at line 408 (C2143), line 409 (C2275/C2065 for `keys`), and line 414 (undeclared `i`/`k`), with a separate late `new_member` declaration at line 418. One focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI, workspace-write/ephemeral; session `01a12ef1-6c60-78d2-bb6f-769f8a2e7a91`) followed TDD. New `scripts/vc6-structseq-initialize-structseq-dict-c89.test.py` failed before production edits as expected on the declaration placements. The lane hoisted only `i`, `k`, and uninitialized `keys` to the function declaration block and `new_member` to the loop's declaration block; tuple and Unicode allocation calls remain at their original execution points. Metadata writes, checks, `continue`, reference handling, resize, insertion, and cleanup order are preserved. Snapshot verification found all 179 pre-existing changed/untracked files unchanged, `PORT_STATUS.md` untouched during coding, and source outside this function unchanged. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p build/cron-20261012T-current/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-current/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors: `structseq.c(408)` C2143, `(409)` C2275/C2065 (`PyObject`/`keys`), `(414)` C2065 (`i`/`k`); independent later declaration errors at `(418-419)` and designated-initializer C2059 at `(588-595)`. Capture: `build/cron-20261012T-current/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-initialize-structseq-dict-c89.test.py` before source edit — exit 1, expected failure on late declarations. GREEN — exit 0. +- Focused and all `scripts/vc6-structseq-*.test.py`: exit 0 for all eight tests (dealloc, initialize-structseq-dict, new, repr, repr-name, repr-name-utf8, repr-value-repr, traverse). `git -C cpython diff --check -- Objects/structseq.c` and `git diff --check -- PORT_STATUS.md scripts/vc6-structseq-initialize-structseq-dict-c89.test.py` — exit 0. The new-file `git diff --no-index --check /dev/null ...` returns 1 because it signals differing content, with no diagnostics; not counted as a pass. +- Post-change forced-fresh command: `mkdir -p build/cron-20261012T-current-post/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-current-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-current-post/probe.log 2>&1` — actual probe exit 2; summary remains `total=107 compiled=106 cached=0 skipped=0`; `_blake2/blake2s_impl.c` and `structseq.c` compiled. The former line-408/409/414/418 declaration diagnostics are gone. The next first compiler diagnostics are C2059 designated-initializer errors at `structseq.c(590-597)`; later `PyStructSequence_NewType` diagnostics at `(624-627)` remain separate. Capture: `build/cron-20261012T-current-post/probe.log`. +- Exact CPython tag/commit verified unchanged. The MSVC environment invocation did not yield a standalone compiler banner. No `pythoncore.dll`/`python.exe` link, Wine interpreter run, or real Windows 98 SE execution was produced. This is compiler-probe progress only, not a completed port. + +Files changed by this slice: `cpython/Objects/structseq.c` (declaration placement only within `initialize_structseq_dict()`), new `scripts/vc6-structseq-initialize-structseq-dict-c89.test.py`, and this status entry. Next: force-fresh probe first, then isolate only the current `structseq.c` designated-initializer family at lines 590-597 in a separate TDD slice. Leave the later `PyStructSequence_NewType` blocker untouched. + +--- + +## Latest run (`structseq_repr()` value/repr C89 declarations; frontier advances) + +Date: 2026-10-12 05:02 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded frontier was force-reprobed before changes. `_blake2/blake2s_impl.c` compiled; the first blocker remained `Objects/structseq.c:structseq_repr()` at lines 296 and 298, where late `PyObject *value` and `PyObject *repr` declarations produce C2275/C2065. One focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a12e78-6932-7e01-bb77-3fb2d756177c`) followed TDD. New `scripts/vc6-structseq-repr-value-repr-c89.test.py` failed before production edits as expected because the declarations were not in the function declaration block. The lane hoisted only `value` and `repr`; assignments remain immediately after `=` output and after borrowed value lookup, respectively. Refcount, error, evaluation, and output order are unchanged. Updated the directly applicable existing `vc6-structseq-repr-name-c89.test.py` source expectation from declaration-with-initializer to the equivalent assignment. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-run/probe-before/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-run/probe-before.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors: C2275/C2065 at `structseq.c(296)` for `value` and `(298)` for `repr`, with cascading warnings. Capture: `build/cron-20261012T-run/probe-before.log`. +- TDD RED: `python3 scripts/vc6-structseq-repr-value-repr-c89.test.py` before production edit — exit 1, expected assertion that `value` and `repr` must be declared in the function entry declaration block. +- Focused GREEN and all applicable structseq regressions: `for test in scripts/vc6-structseq-*.test.py; do python3 "$test"; done` — all seven tests exit 0: dealloc, new, repr loop, repr name, repr name UTF-8, new value/repr regression, and traverse. Nested and outer scoped `git diff --check` — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-run/probe-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-run/probe-after.log 2>&1` — actual probe exit 2; summary remains `total=107 compiled=106 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The previous `structseq_repr()` diagnostics at 296/298 are gone. First remaining errors advance to `structseq.c(408)` C2143, then C2275/C2065 for `keys` at `(409)` and undeclared `i`/`k` at `(414)`; later independent `new_member` declaration errors at `(418-419)`, designated initializers `(588-595)`, and additional errors remain untouched. Capture: `build/cron-20261012T-run/probe-after.log`. +- Exact baseline tag/commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/structseq.c`, `scripts/vc6-structseq-repr-value-repr-c89.test.py` (new), `scripts/vc6-structseq-repr-name-c89.test.py` (updated), and this status entry. Compiler-probe progress only, not a completed port. Next: force-fresh probe before editing; if unchanged, isolate only the current `structseq.c` declaration family beginning at line 408. Do not combine the later `new_member` declaration or designated-initializer blockers. + +--- + +## Previous run (`structseq_repr()` loop-local name declaration; frontier advances) + +Date: 2026-10-12 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine reprobe confirmed the recorded frontier. `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2275/C2065 at `Objects/structseq.c(281)` on the late `PyObject *name`; later diagnostics in this file included `value` at `(295)`, `repr` at `(297)`, declaration families at `(405-416)`, designated initializers at `(585-592)`, and additional later errors. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a12dfe-caaa-71a2-a2d7-4885dc081db2`) used strict TDD. New `scripts/vc6-structseq-repr-name-c89.test.py` failed before production edits with the expected assertion that `name` must be declared at the start of the loop body. The sole production change hoists `PyObject *name;` alongside `name_utf8` and changes the original declaration-with-initializer into an assignment at its original point, preserving decoding, error handling, reference counts, and operation order. Updated the directly applicable existing `vc6-structseq-repr-name-utf8-c89.test.py` assertion to reflect the new legal declaration and unchanged assignment order. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-current/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors: C2275/C2065 at `structseq.c(281)`; later independent errors as listed above. An initial invocation exited 1 before probing because the output directory did not exist; the logged command succeeded after creating it. Capture: `build/cron-20261012T-current/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-repr-name-c89.test.py` before production edit — exit 1 at the intended assertion that `name` must be declared before loop-body statements. +- Focused and all applicable `structseq` regressions: `for test in scripts/vc6-structseq-*.test.py; do python3 "$test"; ...; done` — all six scripts exit 0: `dealloc`, `new`, `repr`, `repr-name`, `repr-name-utf8`, and `traverse`. The existing name-UTF8 test was updated because its prior assertion encoded the now-fixed declaration layout; it passes unchanged behavioral/order checks with the hoisted declaration. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-post/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. The former `name` diagnostics at line 281 are gone. First remaining `structseq.c` diagnostics advance to C2275/C2065 at `(296)` for `value` and `(298)` for `repr`; later errors include declaration families at `(406-417)`, designated initializers `(586-593)`, and additional blockers. Capture: `build/cron-20261012T-post/probe.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-structseq-repr-name-c89.test.py scripts/vc6-structseq-repr-name-utf8-c89.test.py` and `git -C cpython diff --check -- Objects/structseq.c` — exit 0. CPython tag and commit verified unchanged. The compiler output did not provide a standalone banner. No linked `pythoncore.dll`/`python.exe`, Wine interpreter run, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/structseq.c` (only the `name` declaration/assignment split), new `scripts/vc6-structseq-repr-name-c89.test.py`, updated `scripts/vc6-structseq-repr-name-utf8-c89.test.py`, and this status entry. Compiler-probe progress only, not a completed port. Next: force-fresh probe before edits; if unchanged, isolate only the first remaining `structseq_repr()` declaration family (`value` / `repr`) as a separate TDD slice. Do not combine the later `initialize_structseq_dict()` or static initializer blockers. + +--- + +## Previous run (`structseq_repr()` loop-local name declaration; frontier advances) + +Date: 2026-10-12 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2`/`structseq.c` frontier was force-reprobed before editing. `_blake2/blake2s_impl.c` compiled; the first stable diagnostics were C2143 at `Objects/structseq.c(273)` before `const`, then C2065 `name_utf8` at `(274)`. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a12d85-f68c-7213-9d0e-1443aa553b25`) used strict TDD. New `scripts/vc6-structseq-repr-name-utf8-c89.test.py` failed before production edits with expected assertion that `name_utf8` must be declared before loop-body statements. The sole production change declares `const char *name_utf8;` at the top of the `for` body and leaves `name_utf8 = typ->tp_members[i].name;` at its original point, after separator output. NULL checking, error handling, and decode order remain unchanged. The lane's byte-hash check confirmed all 175 other pre-existing dirty files, including this status file, remained unchanged during implementation. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T002656Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T002656Z/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `structseq.c(273)` and C2065 `name_utf8` at `(274)`. Capture: `build/cron-20261012T002656Z/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-repr-name-utf8-c89.test.py` before production edit — exit 1, expected assertion `VC6 requires name_utf8 declared before loop-body statements`. +- GREEN and all `scripts/vc6-structseq-*.test.py`: exit 0 for `dealloc`, `new`, `repr`, new `repr-name-utf8`, and `traverse`. Byte-preservation and exact-source-diff verification — exit 0 (175 other pre-existing dirty files unchanged; source contains only the intended declaration/assignment transformation). +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T002656Z-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T002656Z-post/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` still compiles; the former diagnostics at lines 273-274 are gone. First remaining diagnostics advance to `Objects/structseq.c(281)` C2275 `PyObject` / C2065 `name`; independent later diagnostics include `(295)` `value`, `(297)` `repr`, `(405-416)` declaration families, designated initializer C2059 at `(585-592)`, and later errors. Capture: `build/cron-20261012T002656Z-post/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only, not a completed port. + +Files changed this slice: `cpython/Objects/structseq.c` (one loop-local declaration split), new `scripts/vc6-structseq-repr-name-utf8-c89.test.py`, and this status entry. Next: force-fresh probe before edits; if unchanged, isolate only the first `structseq_repr()` late `PyObject *name` declaration at line 281 as a separate TDD slice. Do not combine the later `value`, `repr`, API, or initializer blockers. + +--- + +## Latest run (`structseq_dealloc()` C89 declaration; frontier advances) + +Date: 2026-10-11 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `_blake2` frontier was stale. A forced-fresh MSVC600/Wine probe compiled `_blake2/blake2s_impl.c`; the first blocker was `Objects/structseq.c:structseq_dealloc()` at line 109, a late initialized `PyTypeObject *tp = Py_TYPE(obj);` declaration. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a12c93-588b-7061-9f8d-45efe50670d9`, workspace-write/ephemeral) followed TDD. New `scripts/vc6-structseq-dealloc-c89.test.py` failed before source edits with the expected assertion that `tp` must be declared before GC untracking. The only production edit hoists `PyTypeObject *tp;` into the declaration block and changes the original declaration to `tp = Py_TYPE(obj);` immediately after `PyObject_GC_UnTrack(obj)`, preserving assignment timing and teardown order. No unrelated files were changed by the lane. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T200205Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T200205Z/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics were C2275/C2065 at `structseq.c(109)` (`PyTypeObject`/`tp`). Capture: `build/cron-20261011T200205Z/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-dealloc-c89.test.py` before the production edit — exit 1, expected assertion that `tp` must be declared before GC untracking. +- Focused GREEN and applicable regressions: `python3 scripts/vc6-structseq-dealloc-c89.test.py`, `python3 scripts/vc6-structseq-new-c89.test.py`, and `python3 scripts/vc6-structseq-traverse-c89.test.py` — all exit 0. `git -C cpython diff --check -- Objects/structseq.c` and `git diff --check -- scripts/vc6-structseq-dealloc-c89.test.py` — both exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T201000Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T201000Z/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. The prior `structseq_dealloc()` line-109 errors are gone; the first blocker advances to line 263 in `Objects/structseq.c` (`C2143` declaration/statement diagnostics and `C2065 i`), with other later independent diagnostics still present. Capture: `build/cron-20261011T201000Z/probe.log`. +- Exact CPython tag and commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/structseq.c` (only `structseq_dealloc()` declaration/assignment), new `scripts/vc6-structseq-dealloc-c89.test.py`, and this status entry. Compiler-probe progress only, not a completed port. Next: force-fresh probe before editing; if unchanged, isolate only the first `structseq.c` declaration family now at line 263. Do not conflate compilation progress with linked or target-running interpreter acceptance. + +--- + +## Latest run (`PySlice_New()` C89 declaration placement; frontier advances) + +Date: 2026-10-11 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded `_blake2`/`sliceobject.c` frontier was force-reprobed before editing using MSVC600 under Wine. `_blake2/blake2module.c`, `_blake2/blake2b_impl.c`, and `_blake2/blake2s_impl.c` compile. The first stable diagnostics remain the `PySlice_New()` late declarations: C2275/C2065 for `PyInterpreterState *interp` at line 126 and `PySliceObject *obj` at line 127, followed by cascading member-access errors. One focused Codex CLI coding lane (`codex-cli 0.153.4`, session `01a12a3d-7607-7211-96a7-1a0449318525`, workspace-write/ephemeral) followed strict TDD. New regression `scripts/vc6-sliceobject-py-slice-new-c89.test.py` failed before production edits at its expected assertion (`interp must be declared at function entry`). The only production change moved declarations of `interp` and `obj` to the start of `PySlice_New()` and changed the interpreter lookup to an assignment at its original point after the null-to-None normalization. Allocation, cache behavior, refcounts, and remaining function bodies were not changed. No unrelated existing work was changed. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T-slice-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T-slice-reprobe/probe-before.log 2>&1` — probe exit 2; summary `total=106 compiled=105 cached=0 skipped=0`. First errors in `sliceobject.c`: C2275/C2065 at line 126 (`PyInterpreterState`/`interp`), C2275/C2065 at line 127 (`PySliceObject`/`obj`), followed by C2223 cascades at lines 128-130. Later independent declaration diagnostics occurred at lines 600, 608, and 617. Capture: `build/cron-20261011T-slice-reprobe/probe-before.log`. +- TDD RED: `python3 scripts/vc6-sliceobject-py-slice-new-c89.test.py cpython/Objects/sliceobject.c` — exit 1, expected assertion `interp must be declared at function entry`. +- Focused GREEN: same command after edit — exit 0, `PySlice_New C89 declaration placement and lookup: PASS`. This is the only directly applicable focused regression found; no other `sliceobject` C89 scripts exist. +- Applicable CPython runtime suite attempt: `PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=cpython/Lib python3 -m unittest test.test_slice` — exit 1 during import, `AssertionError: SRE module mismatch` because host Python is 3.14.7 while checkout is CPython 3.11.16. `/usr/bin/python3` (3.14.4) was also tried and fails with the same mismatch. No built CPython interpreter is present, so runtime slice tests remain unverified. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T-slice-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T-slice-post/probe.log 2>&1` — probe exit 2; summary `total=106 compiled=105 cached=0 skipped=0`. The prior `PySlice_New()` diagnostics at lines 126-130 are gone. The first remaining diagnostics advance to lines 602, 610, and 619 (`PyObject` late declarations for `t1`, `t2`, and `res`); left untouched as a separate defect family. Capture: `build/cron-20261011T-slice-post/probe.log`. +- `git -C cpython diff --check -- Objects/sliceobject.c` and `git diff --check -- scripts/vc6-sliceobject-py-slice-new-c89.test.py` — exit 0. Baseline tag and commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/sliceobject.c` (only `PySlice_New()` declarations/assignment), new `scripts/vc6-sliceobject-py-slice-new-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed port. Next: force-fresh probe before editing and, if unchanged, isolate only the first remaining `sliceobject.c` late-declaration family (around line 602) with a new TDD test. Do not claim port completion. + +--- + +## Latest run (`PySet_Type`/`PyFrozenSet_Type` positional initializer; frontier advances) + +Date: 2026-10-11 05:00 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior recorded `setobject.c` declaration blocker was not current: a forced-fresh MSVC600/Wine probe compiled `_blake2/blake2s_impl.c` and `Objects/setobject.c`; the only reported errors in that file were C2059 on designated `.tp_vectorcall` initializers at lines 2188 and 2289. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a12951-3465-7492-b050-43f906e76593`, workspace-write/ephemeral) used strict TDD. The new regression's pre-edit RED failed as expected at both designators under strict C89. Only these two initializer entries changed: nine intervening `PyTypeObject` fields are explicitly zeroed in actual declaration order, and each original vectorcall function remains in `tp_vectorcall`. The new regression compiles both actual initializers as strict C89 and verifies all 48 field mappings against the checkout's `PyTypeObject` layout. Hash comparison confirms pre-existing files remained unchanged except the intended source edits; `PORT_STATUS.md` and compatibility patches were untouched during the coding lane. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-recheck/probe.log 2>&1` — probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The first/only errors in `setobject.c` were C2059 at lines 2188 and 2289. Capture: `build/cron-current-recheck/probe.log`. +- TDD RED: `python3 scripts/vc6-setobject-type-vectorcall-c89.test.py cpython/Objects/setobject.c` before the source edit — exit 1 with expected C90 designated-initializer errors at both vectorcall entries. +- Focused GREEN and applicable regressions: `python3 scripts/vc6-setobject-type-vectorcall-c89.test.py cpython/Objects/setobject.c` plus every `scripts/vc6-setobject-*.test.py` with `cpython/Objects/setobject.c` — all seven tests exit 0. Both type initializers pass all 48 semantic field mappings; `setiter_reduce` passes eight cases. `git diff --check` and `git -C cpython diff --check -- Objects/setobject.c` — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current-recheck-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-recheck-post/probe.log 2>&1` — probe exit 2; summary `total=106 compiled=105 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/setobject.c` compile; former setobject C2059 errors are gone. The first reported blocker advances to C2275/C2065 at `Objects/sliceobject.c(126-130)`, followed by independent late-declaration families at lines 141, 600, 608, and 617. Capture: `build/cron-current-recheck-post/probe.log`. An initial post-probe invocation lacked its output directory and exited 1 before starting; the recorded successful retry created the directory first. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. The compiler output did not provide a separate compiler banner. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/setobject.c` (only the two static type initializer tails), new `scripts/vc6-setobject-type-vectorcall-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed port. Next: force-fresh probe before editing; if the result is still current, isolate the first `Objects/sliceobject.c` declaration blocker at line 126 in its own TDD slice. Do not conflate compiler progress with a linked or target-running interpreter. + +--- + +## Latest run (`set_issuperset()` C89 declaration hoisted; frontier advances) + +Date: 2026-10-10 22:21 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded first blocker was force-reprobed before editing with MSVC600 under Wine. The prior status named `set_update_internal()`; current source/probe shows the exact function is `set_issuperset()` at line 1782. It failed on a late initialized declaration `PyObject *key, *it = PyObject_GetIter(other);` with C2275/C2065/C2100. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a127ec-3e7e-7ba3-9c34-172d872b5aa9`, workspace-write/ephemeral) performed strict TDD. The new test failed before production change with the expected missing-entry-declarations assertion. The only production change declares `key` and `it` in the function declaration block and moves `PyObject_GetIter(other)` assignment to the original evaluation point. The set fast path, loop, refcounts, errors, and returns are unchanged. An independent hash/status comparison confirmed exactly two paths changed; all pre-existing outer/nested content and status were preserved. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T222104Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T222104Z/probe.log 2>&1` — cl/probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics at `Objects/setobject.c(1782)`: C2275 `PyObject`, C2065 `key` and `it`, C2100 illegal indirection; cascades follow. Later distinct blockers: C2275/C2146/C2065 for `Py_ssize_t nargs` at line 2021, then C2059 at lines 2183 and 2284. Capture: `build/cron-20261010T222104Z/probe.log`. +- TDD RED: `python3 scripts/vc6-setobject-issuperset-c89.test.py cpython/Objects/setobject.c` before production change — exit 1, expected assertion that `key` and `it` must be declared in the initial block. +- Focused GREEN and applicable setobject regressions: `python3 scripts/vc6-setobject-issuperset-c89.test.py cpython/Objects/setobject.c`, `python3 scripts/vc6-setobject-make-new-set-c89.test.py cpython/Objects/setobject.c`, `python3 scripts/vc6-setobject-setiter-reduce-c89.test.py cpython/Objects/setobject.c`, `python3 scripts/vc6-setobject-table-resize-c89.test.py cpython/Objects/setobject.c`, and `python3 scripts/vc6-setobject-frozenset-vectorcall-c89.test.py cpython/Objects/setobject.c` — all exit 0. Output confirms the new C89 declaration/ownership check and four existing regressions pass (set iterator includes eight cases). Scoped nested and outer `git diff --check` — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T222104Z/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T222104Z/probe-post.log 2>&1` — cl/probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled and `setobject.c` now compiles past line 1782. The first remaining error family advances to `Py_ssize_t nargs` at line 2024: C2275/C2146/C2065. Further distinct designated-initializer errors are C2059 at lines 2186 and 2287. Capture: `build/cron-20261010T222104Z/probe-post.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/setobject.c` (only `set_issuperset()` declarations/assignment), new `scripts/vc6-setobject-issuperset-c89.test.py`, and this status entry. Compiler-probe progress only, not a completed port. Next: forced-fresh probe before editing; if unchanged, handle only the `Py_ssize_t nargs` declaration family at the current `setobject.c` line 2024 in its own TDD slice. Do not combine the later designated initializers. + +--- + +## Previous run (fresh `set_issuperset()` blocker confirmed; coding lane unavailable) + +Date: 2026-10-10 20:15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the applicable CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier was freshly force-reprobed. The first stable blocker remains in `Objects/setobject.c(1782)` within `set_update_internal()`: C2275 `PyObject`, C2065 `key`/`it`, and C2100 illegal indirection; subsequent independent errors occur at line 2021 (`Py_ssize_t nargs`) and designated initializers at 2183 and 2284. `_blake2/blake2s_impl.c` compiled. The one focused coding-subagent attempt for only the first blocker failed before startup because the Anthropic package is unavailable and lazy installs are disabled. Therefore this run is diagnostics-only: no production or test files were changed, and no TDD RED/GREEN implementation cycle is claimed. Existing directly applicable setobject tests pass. No pre-existing work was modified beyond this status entry. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T201500Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T201500Z/probe.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors: `setobject.c(1782)` C2275/C2065/C2100; distinct later errors at 2021, 2183, and 2284. Capture: `build/cron-20261010T201500Z/probe.log`. +- Focused coding delegation for the confirmed first `set_update_internal()` blocker — failed before child startup: missing `anthropic` package; lazy installs disabled. No child edits occurred. +- Existing regressions `scripts/vc6-setobject-make-new-set-c89.test.py`, `scripts/vc6-setobject-setiter-reduce-c89.test.py`, `scripts/vc6-setobject-table-resize-c89.test.py`, and `scripts/vc6-setobject-frozenset-vectorcall-c89.test.py` — all exit 0. +- `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/setobject.c` — exit 0. Exact baseline tag and commit verified unchanged. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next frontier: retry one focused TDD coding lane for the actual first declaration blocker in `set_update_internal()` at line 1782; leave the line-2021 and designated-initializer blockers separate. + +--- + +## Previous latest run (fresh frontier moved to `setobject.c`; coding lane unavailable) + +Date: 2026-10-10 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` success and `setobject.c` frontier were freshly checked using the forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` still compiles, but the previously logged `frozenset_vectorcall()` and later `setobject.c` diagnostics are stale: the actual first stable compiler errors now start at `Objects/setobject.c(1782)` inside `set_update_internal()` (C2275 `PyObject`, C2065 `key` and `it`, followed by C2100 illegal indirection). Further independent diagnostics are C2275/C2146/C2065 for `Py_ssize_t nargs` at line 2021, then designated-initializer C2059 at lines 2183 and 2284. The one required focused coding-subagent attempt failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. Therefore this run is diagnostics-only: no TDD RED/GREEN, implementation, or regression test is claimed, and no source/test files were changed. The current first blocker must be inspected and handled as its own TDD slice when the coding lane can start. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261010Tcurrent-next-check/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010Tcurrent-next-check/probe.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: `Objects/setobject.c(1782)` C2275 on `PyObject`, C2065 on `key` and `it`, then C2100; later distinct errors at lines 2021, 2183, and 2284. Capture: `build/cron-20261010Tcurrent-next-check/probe.log`. +- Focused coding delegation for only the confirmed first `setobject.c` blocker — failed before child startup: missing `anthropic` package; lazy installs disabled. No child edits or test runs occurred. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next frontier: use a focused TDD coding lane on the actual first declaration blocker in `Objects/setobject.c` at line 1782, after confirming the exact function-local semantics; keep later line-2021 and designated-initializer blockers separate. Do not claim a completed port. + +--- + +## Latest run (`make_new_set()` declaration hoisted; frontier advances) + +Date: 2026-10-10 UTC + +Read this status, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `make_new_set()` frontier was force-reprobed before editing using MSVC600 under Wine. `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2143 at `Objects/setobject.c(957)` and C2065 `so` at `(959)`; the `so->` errors at `(963-969)` cascade from that declaration. One focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a12614-9049-7873-a1f7-849f7702bc90`) followed strict TDD. It added a regression checking the declaration placement and preserving assertion/allocation/failure-check order; its pre-edit RED failed as expected because `so` was after the assertion. The only production edit moved `PySetObject *so;` before the assertion. Allocation, evaluation, error handling, and all other functions remain unchanged. Snapshot/hash checks confirmed all pre-existing outer/nested dirty and untracked contents plus both staged diffs were preserved. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010Tcurrent-next/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010Tcurrent-next/probe-before.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics C2143 at line 957 and C2065 `so` at line 959. Capture: `build/cron-20261010Tcurrent-next/probe-before.log`. +- TDD RED: `python3 scripts/vc6-setobject-make-new-set-c89.test.py cpython/Objects/setobject.c` before production edit — exit 1 with expected assertion `so must be declared without initializer before the assertion`. +- Focused GREEN/regressions: `python3 scripts/vc6-setobject-make-new-set-c89.test.py cpython/Objects/setobject.c`, `python3 scripts/vc6-setobject-setiter-reduce-c89.test.py cpython/Objects/setobject.c`, `python3 scripts/vc6-setobject-table-resize-c89.test.py cpython/Objects/setobject.c`, `git diff --check`, and `git -C cpython diff --check` — all exit 0. The new test checks declaration uniqueness and assertion/allocation/failure-check order; setiter regression passes eight cases. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010Tcurrent-next/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010Tcurrent-next/probe-after.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. No diagnostics remain at `make_new_set()` lines 957-969. The first blocker advances to the distinct `frozenset_vectorcall()` declaration family at lines 1034-1039 (C2275/C2146/C2065). Further untouched diagnostics occur at lines 1779, 2018, 2180, and 2281. Capture: `build/cron-20261010Tcurrent-next/probe-after.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed by this slice: `cpython/Objects/setobject.c` (one declaration hoist), new `scripts/vc6-setobject-make-new-set-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: force-fresh probe before editing; if unchanged, isolate only the first `frozenset_vectorcall()` C89 declaration blocker at `setobject.c(1034)` in its own TDD slice. Do not claim port completion. + +--- + +## Latest run (`setiter_reduce()` C89 declaration; frontier advances) + +Date: 2026-10-10 11:45 UTC + +Read `PORT_STATUS.md`, `README.md`, and the relevant CPython Win9x/MSVC6 reference before acting. Preserved pre-existing outer and detached CPython modifications. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Used one focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a1259c-aea6-7783-9904-89049dac951c`) for only the first confirmed `setobject.c` blocker and strict TDD. The new regression's pre-edit RED run failed as expected under strict C89 on the mixed declaration in `setiter_reduce()`. The only production change hoisted `PyObject *list` to the function declaration block; `list = PySequence_List((PyObject*)&tmp)` remains after the iterator-state copy and `Py_XINCREF(tmp.si_set)`, and cleanup/return paths are unchanged. Snapshot verification confirms all 162 pre-existing changed/untracked files' contents stayed byte-identical; only the intended `setobject.c` edit and new test were added. No other setobject blocker was changed. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010-current/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010-current/probe-current.log 2>&1` — actual probe exit 2; summary `total=104 compiled=103 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2275/C2065 at `Objects/setobject.c(779)` for the late `PyObject *list`; later distinct diagnostics included `make_new_set()` at line 956, `frozenset_vectorcall()` at 1033, `set_update_internal()` at 1778, and positional-initializer errors at 2179 and 2280. Capture: `build/cron-20261010-current/probe-current.log`. +- TDD RED: `python3 scripts/vc6-setobject-setiter-reduce-c89.test.py cpython/Objects/setobject.c` before production edit — exit 1, expected `ISO C90 forbids mixed declarations and code` at `PyObject *list = PySequence_List(...)`. +- Focused GREEN and applicable setobject regression tests: `python3 scripts/vc6-setobject-setiter-reduce-c89.test.py cpython/Objects/setobject.c` and `python3 scripts/vc6-setobject-table-resize-c89.test.py cpython/Objects/setobject.c` — both exit 0. New test compiles/runs exact extracted function with strict C89 and covers eight reference/evaluation/cleanup/return cases. Scoped nested and outer `git diff --check` — exit 0. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010-current/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010-current/probe-after.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The prior line-779 diagnostic is gone and `Objects/setobject.c` compiles past the changed function. First remaining blocker advances to C2143 at `Objects/setobject.c(957)` (`make_new_set()` declaration); further untouched diagnostics include lines 1034, 1039, 1779, 2018, 2180, and 2281. Capture: `build/cron-20261010-current/probe-after.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed by this slice: `cpython/Objects/setobject.c` (only `setiter_reduce()` declaration split), new `scripts/vc6-setobject-setiter-reduce-c89.test.py`, and this status entry. Compiler-probe progress only: the source-list probe still fails; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: freshly force-reprobe before editing, then isolate only the actual first `make_new_set()` C89 declaration blocker at line 956 using its own TDD test. Do not claim port completion. + +--- + +## Previous latest run (`PyRange_Type.tp_vectorcall` positional initializer; frontier advances) + +Date: 2026-10-10 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved the existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded rangeobject frontier was forced-fresh re-probed before editing. `_blake2/blake2s_impl.c` compiled; VC6's first diagnostic was C2059 at `Objects/rangeobject.c(791)` on the designated `.tp_vectorcall` entry. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a12439-49b6-7d73-b375-35a5c504fcbf`) followed TDD. It added a regression using the actual `PyTypeObject` header field order and asserting all 48 semantic fields. The test failed before production edit with the expected C90 designated-initializer error. Only the final `PyRange_Type` designated entry was replaced with ten explicit zero initializers for `tp_free` through `tp_finalize`, then positional `(vectorcallfunc)range_vectorcall`; no other range initializer or production code changed. Snapshot verification confirmed all pre-existing dirty/untracked files, including the pre-existing `PORT_STATUS.md` contents, remained unchanged aside from this intended production/test slice. + +Exact verification: + +- Before-change command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010-current/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010-current/probe-before.log 2>&1` — actual probe exit 2; `total=104 compiled=103 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic C2059 at `Objects/rangeobject.c(791)` on `.`. Capture: `build/cron-20261010-current/probe-before.log`. +- TDD RED: `python3 scripts/vc6-rangeobject-vectorcall-c89.test.py cpython/Objects/rangeobject.c` before source edit — exit 1, expected `ISO C90 forbids specifying subobject to initialize` for `.tp_vectorcall`. +- Focused GREEN and rangeobject regressions: `python3 scripts/vc6-rangeobject-vectorcall-c89.test.py cpython/Objects/rangeobject.c`, `python3 scripts/vc6-rangeobject-number-c89.test.py cpython/Objects/rangeobject.c`, and `python3 scripts/vc6-rangeobject-index-c89.test.py cpython/Objects/rangeobject.c` — all exit 0; all 48 type fields, all 36 number slots, and nine range-index cases pass. `git diff --check` and `git -C cpython diff --check -- Objects/rangeobject.c` — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010-current/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010-current/probe-after.log 2>&1` — actual probe exit 2; `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The changed `rangeobject.c` blocker is gone; first stable diagnostics advance to `Objects/setobject.c(244)` C2143 and `(245)` C2065 `newsize`, followed by further distinct blockers in `setobject.c`. Capture: `build/cron-20261010-current/probe-after.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. The coding lane's hash/status snapshot check and independent diff review passed: 158 previously dirty/untracked files retained byte-for-byte; only the intended CPython source modification and new test added. + +Files changed by this slice: `cpython/Objects/rangeobject.c` (only final `PyRange_Type` initializer entry), new `scripts/vc6-rangeobject-vectorcall-c89.test.py`, and this status entry. Compiler-probe progress only: the VC6 source-list probe still fails; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: freshly probe before editing; if unchanged, isolate only `Objects/setobject.c(244)`'s first C89 declaration blocker in its own TDD slice. Do not claim port completion. + +--- + +## Latest run (`range_as_number` positional initializer; frontier advances) + +Date: 2026-10-10 03:05 UTC + +Read `PORT_STATUS.md`, `README.md`, and the relevant CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded rangeobject frontier was freshly confirmed with forced-fresh MSVC600/Wine compilation before editing. `_blake2/blake2s_impl.c` compiled; the first stable diagnostic was C2059 at `Objects/rangeobject.c(686)` on `.nb_bool`; a separate C2059 remained later at line 756 on `.tp_vectorcall`. One focused Codex CLI coding lane (`codex-cli 0.153.4`, ephemeral, workspace-write) followed strict TDD. It added `scripts/vc6-rangeobject-number-c89.test.py`, which derives all 36 `PyNumberMethods` fields from the actual header and checks each slot semantically. The test failed before production edits as expected with `ISO C90 forbids specifying subobject to initialize`. Only `range_as_number` was converted to positional initialization, mapping `(inquiry)range_bool` to `nb_bool` and zeroing all other fields. The separate `.tp_vectorcall` initializer was not touched. A snapshot verification confirmed all pre-existing dirty/untracked bytes, both indexes, statuses, and HEADs were preserved except for this intended source edit and added test. + +Exact verification: + +- Pre-change command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010Tcurrent/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010Tcurrent/probe-before.log 2>&1` — actual probe exit 2; `total=104 compiled=103 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostic C2059 at `rangeobject.c(686)`; separate C2059 at `(756)`. Capture: `build/cron-20261010Tcurrent/probe-before.log`. +- TDD RED: `python3 scripts/vc6-rangeobject-number-c89.test.py cpython/Objects/rangeobject.c` — exit 1 before source edit, expected C89 rejection of designated initializer at `.nb_bool`. +- Focused GREEN and applicable rangeobject regressions: `python3 scripts/vc6-rangeobject-number-c89.test.py cpython/Objects/rangeobject.c` and `python3 scripts/vc6-rangeobject-index-c89.test.py cpython/Objects/rangeobject.c` — both exit 0. The new semantic test checked all 36 fields; range-index test passed 9 cases. +- Post-change forced-fresh probe using the same command with runtime `build/cron-20261010Tcurrent/runtime-post` — actual probe exit 2; `total=104 compiled=103 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The line-686 blocker is gone. First blocker advances to C2059 at `Objects/rangeobject.c(791)` on the distinct designated initializer. Capture: `build/cron-20261010Tcurrent/probe-after.log`. +- `git diff --check`, `git -C cpython diff --check -- Objects/rangeobject.c`, and independent rerun of both rangeobject tests — exit 0. Exact CPython tag/commit unchanged. Snapshot confirms outer/nested index and all pre-existing dirty/untracked content preserved. + +Files changed by this slice: `cpython/Objects/rangeobject.c` (only `range_as_number`), new `scripts/vc6-rangeobject-number-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: freshly probe before editing; if still confirmed, isolate only the `rangeobject.c(791)` designated initializer with its own TDD test. Do not claim port completion. + +--- + +## Previous latest run (range initializer frontier reconfirmed; coding lane unavailable) + +Date: 2026-10-10 00:48 UTC + +Read `PORT_STATUS.md`, `README.md`, and the relevant CPython Win9x/MSVC6 reference before acting. The reference at `/home/ubuntu/.hermes/profiles/maxwell/skills/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` was absent; read the available copy at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, or patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded rangeobject frontier remains current after a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; the first stable diagnostic is C2059 at `Objects/rangeobject.c(686)` on the designated `.nb_bool` initializer. A later separate C2059 remains at line 756 on `.tp_vectorcall`. One focused coding-subagent attempt was made for only the line-686 initializer and TDD regression, but failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. No implementation, test, or production source was changed in this run; this is diagnostics-only. The existing local `range_index()` declaration split was preserved. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261010Tcurrent/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010Tcurrent/probe-before.log 2>&1` — actual probe exit 2; summary `total=104 compiled=103 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic: C2059 at `rangeobject.c(686)`; separate later C2059 at `(756)`. Capture: `build/cron-20261010Tcurrent/probe-before.log`. +- Focused coding-agent lane — failed before child startup: `anthropic` package required; lazy installs disabled. No child edits occurred; no TDD RED/GREEN or regression run is claimed. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped nested and outer `git diff --check` commands exited 0. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next: retry one focused TDD coding lane for only `range_as_number` at line 685 when a coding provider can start, leaving the independent line-756 initializer untouched. + +--- + +## Previous latest run (`range_index()` C89 local declaration; frontier advances) + +Date: 2026-10-09 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved the existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded range frontier was freshly re-probed before editing using MSVC600 under Wine, forced-fresh. `_blake2/blake2s_impl.c` compiled; the first blocker was C2275/C2065 at `Objects/rangeobject.c(601)` for the late `PyObject *sidx` declaration. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a122d4-4e91-7f10-b7b8-713868d6b34c`) followed TDD. It added `scripts/vc6-rangeobject-index-c89.test.py`, observed the expected C89 mixed-declaration RED before production edits, then hoisted only the `sidx` declaration. The `PyNumber_FloorDivide` assignment remains at its original evaluation point; no other production function was changed. Snapshot/hash verification confirms the pre-existing 32 outer and 124 CPython dirty/untracked paths and both indexes were unchanged apart from the intended test addition and source edit. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-rerun" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/pre-change-probe-cron-rerun.log 2>&1` — actual probe exit 2; summary `total=104 compiled=103 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2275/C2065 at `rangeobject.c(601)` (`PyObject` / `sidx`); separate C2059 designated-initializer diagnostics at lines 685 and 755. Capture: `build/cron-20261009Tcurrent/pre-change-probe-cron-rerun.log`. +- TDD RED: `python3 scripts/vc6-rangeobject-index-c89.test.py cpython/Objects/rangeobject.c` before the source edit — exit 1, expected C90 mixed-declaration diagnostic at the late `sidx` declaration (recorded by the coding lane). +- Focused GREEN: same command after the edit — exit 0, `range_index C89 compile and evaluation/cleanup order: PASS (9 cases)`. The CPython `test_range` suite was also attempted under host Python 3.14.7 (not this CPython 3.11.16 checkout's built interpreter): 26 tests ran, six subtest failures in `test_iterator_pickling_overflowing_index` for protocols 0–5 (`None != 0`); thus this suite is not claimed as passing or as validation of the edited C source. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post-range-index" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/post-range-index.log 2>&1` — actual probe exit 2; summary `total=104 compiled=103 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/rangeobject.c` compiled; former line-601 C2275/C2065 diagnostics are gone. First blocker remains in `rangeobject.c` at line 686, C2059 on a designated initializer; another C2059 remains at line 756. Capture: `build/cron-20261009Tcurrent/post-range-index.log`. +- `/tmp/rangeobject-sidx-baseline/verify.py` — exit 0; confirms all 32 outer and 124 CPython pre-existing dirty/untracked paths and each index are unchanged, with only the intended new outer test and modified CPython `rangeobject.c`. `git diff --check` and `git -C cpython diff --check -- Objects/rangeobject.c` — exit 0. Exact baseline tag and commit verified unchanged. + +Files changed by this slice: `cpython/Objects/rangeobject.c` (only `sidx` declaration/assignment split), new `scripts/vc6-rangeobject-index-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: force-fresh probe before editing, then handle only the first `rangeobject.c` designated-initializer blocker at line 686 using its own TDD slice. Do not claim port completion. + +--- + +## Latest run (`PyPickleBuffer_Type` C89 positional initializer; frontier advances) + +Date: 2026-10-09 20:35 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved the existing dirty outer and detached CPython work; no reset, clean, stash, discard, commit, push, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded picklebuf frontier was freshly rechecked first with forced-fresh MSVC600/Wine compilation: `_blake2/blake2s_impl.c` and `Objects/picklebufobject.c` compiled; first stable blocker was C2059 at `Objects/picklebufobject.c(211)` on `.tp_name`. One focused Hermes coding-agent attempt failed before startup because the Anthropic package is unavailable and lazy installs are disabled. One Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a1225b-912d-7f93-8cdd-a48be9cae1e2`) followed TDD. It added `scripts/vc6-picklebuf-type-c89.test.py`, observed expected C89 designated-initializer RED before changing production code, then converted only `PyPickleBuffer_Type` to positional initialization. The regression checks all 48 `PyTypeObject` fields against the checkout's actual struct layout: all 11 original designated expressions are preserved semantically and the other 37 fields are explicitly zero. Its host C89 compile/runtime harness passed. Snapshot comparison confirmed all other 156 existing dirty/untracked files and indexes remained unchanged; source outside this initializer, including the already-dirty `picklebufobject.c`, is unchanged by the slice. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-rerun" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/probe-cron-recheck.log 2>&1` — actual probe exit 2; summary `total=103 compiled=102 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic C2059 at `picklebufobject.c(211)`. Capture: `build/cron-20261009Tcurrent/probe-cron-recheck.log`. +- TDD RED: `python3 scripts/vc6-picklebuf-type-c89.test.py cpython/Objects/picklebufobject.c` — exit 1 before production edit; expected `ISO C90 forbids specifying subobject to initialize` on all 11 designated entries. +- GREEN and all applicable picklebuf tests: `for test in scripts/vc6-picklebuf-*.test.py; do python3 "$test" cpython/Objects/picklebufobject.c; result=$?; echo "$test exit=$result"; if test "$result" -ne 0; then exit "$result"; fi; done` — exit 0. The new type test passed all 48 semantic field mappings; existing buffer-field and `picklebuf_raw()` validation/allocation-order tests passed (5 cases). Independently reran the new type test — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post-picklebuf-type" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/probe-post-picklebuf-type.log 2>&1` — actual probe exit 2; summary `total=104 compiled=103 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/picklebufobject.c` compiled; previous picklebuf designated-initializer blocker is gone. First blocker advances to `Objects/rangeobject.c(601)` with C2275 `PyObject` and C2065 `sidx`; later independent C2059 diagnostics are at lines 685 and 755. Capture: `build/cron-20261009Tcurrent/probe-post-picklebuf-type.log`. +- `git -C cpython diff --check`, `git diff --check`, and focused type test — exit 0. Nested CPython exact tag and commit verified unchanged. Codex's `diff --no-index --check /dev/null new-file` and whole-file comparison returned exit 1 because those commands signal differing content; no whitespace diagnostics were emitted. These are not counted as passing checks. + +Files changed by this slice: `cpython/Objects/picklebufobject.c` (only `PyPickleBuffer_Type`), new `scripts/vc6-picklebuf-type-c89.test.py`, and this status entry. Compiler-frontier progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: force-fresh probe before editing and address only the current first blocker in `Objects/rangeobject.c` at line 601. Do not claim port completion. + +--- + +## Latest run (`picklebuf_raw()` C89 declarations; frontier advances) + +Date: 2026-10-09 16:04 UTC + +Read `PORT_STATUS.md`, `README.md`, and the relevant legacy-toolchain reference before acting. The reference is at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`; the project-local copy is absent. Preserved all pre-existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `picklebuf_raw()` blocker was confirmed with a forced-fresh MSVC600/Wine probe before editing. `_blake2/blake2s_impl.c` compiled. VC6 reported C2059 at the independent designated initializer in `Objects/picklebufobject.c(142)`, then C2275/C2065 at `(162)` for `PyObject *m` and `(166)` for `PyMemoryViewObject *mv`, followed by cascades. One focused Hermes coding-subagent attempt failed before startup because the Anthropic package is unavailable and lazy installs are disabled. One Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a12169-8e26-79d1-971b-be4dac44ca93`) then followed strict TDD. It added a focused C89 compile/runtime regression covering released/non-contiguous validation, allocation failure, memoryview mutation, and event order; it observed the expected mixed-declaration RED before moving only `m` and `mv` to the function's declaration block. Their assignments remain at the original points after the guards and successful allocation. The C2059 designated initializers and all other files/blockers were left untouched. Independent diff review confirms only the two declaration forms changed in `picklebuf_raw()`. + +Exact verification: + +- Before-change command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/reprobe-before.log 2>&1` — actual probe exit 2; summary `total=103 compiled=102 cached=0 skipped=0`. First stable diagnostics: C2059 at line 142; C2275/C2065 at lines 162 and 166; independent C2059 at line 208. `_blake2/blake2s_impl.c` compiled. Log: `build/cron-20261009Tcurrent/reprobe-before.log`. +- TDD RED: `python3 scripts/vc6-picklebuf-raw-c89.test.py cpython/Objects/picklebufobject.c` before the production edit — expected C89 mixed-declaration failure, as recorded by the Codex lane. GREEN and focused C89 compile/runtime cases: same command after edit — exit 0, `picklebuf_raw C89 compile and validation/allocation order: PASS (5 cases)`. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/probe-post-picklebuf-raw.log 2>&1` — actual probe exit 2; summary `total=103 compiled=102 cached=0 skipped=0`. The former line-162/166 declaration diagnostics are gone; first blocker is now the designated initializer C2059 at line 142 (also line 211), untouched. `_blake2/blake2s_impl.c` compiled. No full build/link was attempted. +- `git -C cpython diff --check -- Objects/picklebufobject.c` and `git diff --check -- scripts/vc6-picklebuf-raw-c89.test.py` — exit 0. Exact baseline tag/commit verified unchanged. + +Files changed by this slice: `cpython/Objects/picklebufobject.c` (only declarations within `picklebuf_raw()`), new `scripts/vc6-picklebuf-raw-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: force-fresh probe before editing, then isolate only the first designated initializer blocker at `picklebuf_as_buffer` line 142 as its own test-first slice. Do not claim port completion. + +--- + +## Previous run (`mutablemapping_update()` len C89 declaration; frontier advances) + +Date: 2026-10-09 13:58 UTC + +Read this status and `README.md` before acting. The invoked skill reference `references/python-3-win9x-msvc6.md` was not found in the accessible project/skill files; prior status likewise records it unavailable. Preserved all pre-existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython exact baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` success and `mutablemapping_update()` late `Py_ssize_t len` blocker were reconfirmed with a forced-fresh MSVC600/Wine source-list probe before editing. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a120ef-d52c-7423-aebc-d991acb9f188`) followed strict TDD. It snapshotted and hashed all 151 pre-existing dirty/untracked paths across the outer and nested repositories. It added a C89 compile/runtime regression covering 10 argument/keyword/error/order cases, observed expected RED at the mixed declaration, then moved only `Py_ssize_t len` to the function declaration block and retained the assignment immediately after the existing assertion. Independent snapshot comparison confirmed all other 150 baseline paths and both indexes unchanged; `PORT_STATUS.md` remained untouched by the lane. No other defect family was edited. + +Exact verification: + +- Before-change command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-run" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/probe-current.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2143 at `Objects/odictobject.c(2299)` and C2065 `len` at `(2300)`. Log: `build/cron-20261009Tcurrent/probe-current.log`. +- TDD RED: `python3 scripts/vc6-odict-update-len-c89.test.py cpython/Objects/odictobject.c` — exit 1, expected C90 mixed-declaration diagnostic at the late `Py_ssize_t len` declaration. GREEN: same command after edit — exit 0, 10 C89 compile/runtime cases passed. +- Applicable regression loop: `for test in scripts/vc6-odict-*.test.py; do python3 "$test" cpython/Objects/odictobject.c; result=$?; echo "$test exit=$result"; if test "$result" -ne 0; then exit "$result"; fi; done` — exit 0; all six odict tests passed individually. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/probe-post-len.log 2>&1` — actual probe exit 2; summary `total=103 compiled=102 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/odictobject.c` compiled. Former `len` diagnostics are gone. First blocker advances to `Objects/picklebufobject.c`: C2059 at lines 142 and 208 on designated initializers; C2275/C2065 at line 162 (`PyObject *m`) and line 166 (`PyMemoryViewObject *mv`), with later pointer errors cascading. Log: `build/cron-20261009Tcurrent/probe-post-len.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-odict-update-len-c89.test.py` and `git -C cpython diff --check -- Objects/odictobject.c` — exit 0. Exact baseline tag and commit checked unchanged. + +Files changed by this slice: `cpython/Objects/odictobject.c` (one declaration/assignment split), new `scripts/vc6-odict-update-len-c89.test.py`, and `PORT_STATUS.md`. The applicable focused tests and compiler probe validate compiler-frontier progress only. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: freshly probe before editing, then isolate the first current `picklebufobject.c` defect family only. Do not claim port completion. + +--- + +## Previous run (mutablemapping_update `len` frontier reconfirmed; coding lane unavailable) + +Date: 2026-10-09 09:40 UTC + +Read `PORT_STATUS.md`, `README.md`, and attempted the required CPython Win9x/MSVC6 reference before acting. The reference file was not present at `/home/ubuntu/.hermes/skills/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`; no source changes were made in this diagnostics-only run. Preserved the pre-existing dirty outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `mutablemapping_update()` frontier remains current after a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; the first stable blocker remains the late `Py_ssize_t len` declaration in `Objects/odictobject.c`, followed by the undeclared `len` use. One focused coding-agent delegation was attempted for this exact slice, but failed before child startup because the runtime lacks the `anthropic` package and lazy installs are disabled. No test or production source was changed; no RED/GREEN cycle or regression suite was claimed. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-rerun" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/cron-reprobe.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `odictobject.c(2299)` and C2065 `len` at `(2300)`. Capture: `build/cron-20261009Tcurrent/cron-reprobe.log`. +- One focused coding-subagent delegation for the `len` declaration family failed before child startup: Anthropic package missing; lazy installs disabled. No child modifications occurred. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/odictobject.c` exited 0. +- No source/test regressions were run because no source or test changed. The MSVC environment emitted no standalone compiler banner. No link, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: retry the single focused TDD `len` declaration slice when a coding agent can start; keep assignment at its existing evaluation point. Do not claim port completion. + +--- + +## Latest run (confirmed `mutablemapping_update()` frontier; coding lane unavailable) + +Date: 2026-10-09 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded `mutablemapping_update()` first blocker was freshly confirmed by a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; first blocker remains C2143 at `Objects/odictobject.c(2299)` on the late `Py_ssize_t len` declaration, followed by C2065 `len` at 2300. A single focused coding-agent delegation was attempted as required, but failed before child startup because the Hermes runtime lacks the `anthropic` package and lazy installs are disabled. No source or test changes were made in this run; this is diagnostics-only. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261009-rerun/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009-rerun/pre-change-probe.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `odictobject.c(2299)` and C2065 `len` at `(2300)`. Capture: `build/cron-20261009-rerun/pre-change-probe.log`. +- One focused coding-subagent delegation for exactly the `mutablemapping_update()` declaration family failed before child startup: Anthropic package missing; lazy installs disabled. No child modifications occurred. +- No source or regression test was changed/run in this diagnostics-only run. The directly applicable odict test set was already recorded as passing in the immediately preceding run. +- Probe output showed the MSVC environment setup text but did not include a standalone compiler version banner. No compiler-link, Wine interpreter, or real Windows 98 SE result was produced. +- CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: retry one isolated TDD coding lane for only the confirmed `Py_ssize_t len` declaration in `mutablemapping_update()` when a coding-agent provider is available; retain the assignment at its existing post-assertion point. Do not claim port completion. + +--- + +## Latest run (`mutablemapping_update_arg` iterator/key declarations; frontier advances) + +Date: 2026-10-09 03:24 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython work. No reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact release tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `mutablemapping_update_arg()` frontier was freshly confirmed using the forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; summary `total=102 compiled=101 cached=0 skipped=0`. First blocker: C2275/C2065 at `Objects/odictobject.c(2252)` for late `PyObject *iterator`, followed by the same declaration-family issue at `(2257)` for `PyObject *key`. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write, ephemeral; session `01a11eab-b100-7c81-a014-403f0be55bc3`) followed strict TDD. It added a C89 compile/runtime regression for the exact keys branch, observed expected RED on only the targeted late declarations, then moved only `iterator` and `key` declarations to the start of the branch. `iterator = PyObject_GetIter(keys)` remains after the existing NULL check and at its original evaluation point; `key` initialization remains in the loop. No later `len` declaration was touched. The delegated lane's preservation hash check verified all 149 other pre-existing dirty files were unchanged. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/pre-change-probe.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: C2275/C2065 at `odictobject.c(2252)` and C2275/C2065 at `(2257)`. Capture: `build/cron-20261009Tcurrent/pre-change-probe.log`. +- TDD RED: `python3 scripts/vc6-odict-update-arg-iterator-c89.test.py cpython/Objects/odictobject.c` — exit 1, expected C90 mixed-declaration diagnostics exactly at the `iterator` and `key` declarations. GREEN: same command after edit — exit 0, eight runtime evaluation/cleanup cases passed. +- Applicable odict regressions, each exit 0: `vc6-odict-list-c89.test.py` (24 cases), `vc6-odict-number-c89.test.py` (36 field mappings), `vc6-odict-or-c89.test.py` (8 cases), and `vc6-odict-update-arg-func-c89.test.py` (6 cases). Aggregate loop exit 0. `git diff --check` for the new test and nested `git diff --check -- Objects/odictobject.c` — exit 0. +- Post-change forced-fresh probe with `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post"` and otherwise the same command — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The former diagnostics at 2252 and 2257 are gone; first blocker advances to `odictobject.c(2299)` C2143 / `(2300)` C2065 on `len`. Capture: `build/cron-20261009Tcurrent/post-change-probe.log`. +- Exact CPython tag and commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. + +Files changed by this slice: `cpython/Objects/odictobject.c` (only iterator/key declarations in `mutablemapping_update_arg()`), new `scripts/vc6-odict-update-arg-iterator-c89.test.py`, and this status entry. Compiler-probe progress only. Next frontier: force-fresh probe before editing, then address only the actual first blocker (currently the late `Py_ssize_t len` in `mutablemapping_update()`, line 2299). Do not claim port completion. + +--- + +## Previous run (`mutablemapping_update_arg` declaration family; frontier advances) + +Date: 2026-10-09 01:13 UTC + +Read the existing status, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `mutablemapping_update_arg()` frontier was freshly confirmed before editing with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; summary `total=102 compiled=101 cached=0 skipped=0`. First blocker: C2275/C2065 at `Objects/odictobject.c(2242)` on the late `PyObject *func` declaration. Native Hermes coding delegation was unavailable because the Anthropic package is not installed and lazy installs are disabled. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write, ephemeral) then followed TDD: added a prefix-only C89 compile/runtime regression, observed expected RED before changing production, and moved only `PyObject *func` to the function's initial declaration group. The change leaves lookup after the exact-dict path, preserving execution/cleanup/error order. Distinct later declarations at lines 2252/2257 and the `mutablemapping_update()` blocker at 2298-2299 were not touched. The lane reports all 148 pre-existing dirty/untracked files remained byte-identical; independent diff inspection confirms the only new source hunk in already-dirty `odictobject.c` is this declaration relocation. + +Exact verification: + +- Pre-change command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/pre-change-probe.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors: C2275/C2065 at `odictobject.c(2242)` (`PyObject`, `func`), followed by separate errors at 2252, 2257, 2298-2299. Capture: `build/cron-20261009Tcurrent/pre-change-probe.log`. +- TDD RED: `python3 scripts/vc6-odict-update-arg-func-c89.test.py cpython/Objects/odictobject.c` — exit 1, expected `ISO C90 forbids mixed declarations and code` at the late declaration. GREEN: same command after source change — exit 0, `mutablemapping_update_arg prefix C89 compile and dict/lookup ordering: PASS (6 cases)`. +- Applicable odict regressions, all exit 0: the new `vc6-odict-update-arg-func-c89.test.py` (6 cases), `vc6-odict-list-c89.test.py` (24 cases), `vc6-odict-number-c89.test.py` (36 mappings), and `vc6-odict-or-c89.test.py` (8 cases). Independently rerun together after the coding lane; aggregate exit 0. +- Post-change forced-fresh probe with `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post"` and otherwise the same command — actual probe exit 2; summary still `total=102 compiled=101 cached=0 skipped=0`. Former line-2242 errors are gone. First blocker advances to `odictobject.c(2252)` C2275/C2065 (`PyObject *iterator`); separate errors remain at 2257 (`key`) and 2298-2299 (`len`). Capture: `build/cron-20261009Tcurrent/post-change-probe.log`. +- `git diff --check -- scripts/vc6-odict-update-arg-func-c89.test.py` and `git -C cpython diff --check -- Objects/odictobject.c` — exit 0. Exact baseline tag/commit unchanged. + +Files changed by this slice: `cpython/Objects/odictobject.c` (only the `func` declaration relocation within `mutablemapping_update_arg()`), new `scripts/vc6-odict-update-arg-func-c89.test.py`, and this status entry. Probe logs are under ignored `build/cron-20261009Tcurrent/`. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution verified. Next frontier: forced-fresh probe first, then address only the first actual blocker, currently `PyObject *iterator` at `odictobject.c(2252)`. Do not claim port completion. + +--- + +## Previous run (`odictiter_reduce` C89 declaration; compiler frontier advances) + +Date: 2026-10-08 23:00 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved the existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` state and `odictiter_reduce()` first blocker were freshly checked with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; the first blocker was C2275/C2065 at `Objects/odictobject.c(1839)` on `PyObject *list`. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11db9-b3c7-7501-90a5-628fa8390bd5`) followed strict TDD. It added `scripts/vc6-odict-list-c89.test.py`, observed the expected C90 mixed-declaration RED before production edits, then hoisted only the `list` declaration into `odictiter_reduce()`'s declaration group. Its `PySequence_List((PyObject*)&tmp)` initializer remains at its original point after both increfs, preserving evaluation timing, refcounts, cleanup, and error flow. No later function or blocker was changed. Preservation snapshot comparison confirmed every pre-existing dirty/untracked file remained byte-identical except the intended production edit; `PORT_STATUS.md` was then updated for this run. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261008Tcurrent/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261008Tcurrent/reprobe.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors: C2275/C2065 at `odictobject.c(1839)` for `PyObject *list`; subsequent independent diagnostics included lines 2241, 2251, 2256, and 2297-2298. Wine startup initially failed before this capture because the server lock path under `/run/user/1000/wine` was read-only; `wine cmd /c ver` using the same project-local runtime then succeeded, and the fresh probe succeeded. Capture: `build/cron-20261008Tcurrent/reprobe.log`. +- TDD RED: `python3 scripts/vc6-odict-list-c89.test.py cpython/Objects/odictobject.c` before production edit — exit 1, expected `ISO C90 forbids mixed declarations and code` at the initialized `PyObject *list` declaration. GREEN: same command after edit — exit 0, `odictiter_reduce C89 compile and copy/incref/list/cleanup/ownership/failure order: PASS (24 cases)`. +- Applicable odict regressions: `for test in scripts/vc6-odict-list-c89.test.py scripts/vc6-odict-or-c89.test.py scripts/vc6-odict-number-c89.test.py; do python3 "$test" cpython/Objects/odictobject.c || exit "$?"; done` — exit 0. All three passed: list/order/ownership (24 cases), `odict_or` operation ordering (8 cases), and all 36 numeric-method mappings. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261008Tcurrent/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261008Tcurrent/reprobe-retry.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/odictobject.c` compiled; former diagnostics at line 1839 are gone. First stable blocker advances to `odictobject.c(2242)`: C2275 on `PyObject` and C2065 on `func`; further distinct diagnostics remain at 2252, 2257, and 2298-2299. Capture: `build/cron-20261008Tcurrent/reprobe-retry.log`. +- `git diff --check -- scripts/vc6-odict-list-c89.test.py` and `git -C cpython diff --check -- Objects/odictobject.c` — exit 0. `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` and `git -C cpython rev-parse 'v3.11.16^{commit}'` both → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed by this run: `cpython/Objects/odictobject.c` (only the `odictiter_reduce()` declaration split), new `scripts/vc6-odict-list-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: freshly probe before editing, then isolate only the first current blocker at `odictobject.c(2242)` (`PyObject *func`). Do not claim port completion. + +--- + +## Previous run (`odict_as_number` positional initializer; frontier advances) + +Date: 2026-10-08 20:48 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded compiler frontier was freshly checked with a forced-fresh MSVC600/Wine source-list probe before edits. `_blake2/blake2s_impl.c` compiled. The first blocker was the designated initializer in `Objects/odictobject.c`'s `odict_as_number` at line 900 (C2059). One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11d40-75d0-7623-8a3b-dc382dcca4fe`) followed TDD. It added `scripts/vc6-odict-number-c89.test.py`, which compiled the exact table as C89 and checks all 36 `PyNumberMethods` fields by semantic name. The test failed before the source edit as expected, then passed after replacing only `odict_as_number` with a positional initializer: `odict_or` remains in `nb_or`, `odict_inplace_or` remains in `nb_inplace_or`, and all 34 other fields are zero. No later `odictobject.c` functions were edited. All pre-existing changes remain preserved. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-20261008T203722Z" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The first stable blocker was C2059 at `odictobject.c(900)` on the `.nb_or` designated initializer. Capture: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791491842-1537598-7ce0.log`. +- TDD RED: the new `python3 scripts/vc6-odict-number-c89.test.py cpython/Objects/odictobject.c` failed before production change (expected C89 compile failure for designated initialization). GREEN: same test after the edit — exit 0, `odict_as_number C89 compile and all 36 semantic field mappings: PASS`. `python3 scripts/vc6-odict-or-c89.test.py cpython/Objects/odictobject.c` — exit 0, operation-order runtime regression passed (8 cases). +- Applicable frontier regression harness: `XDG_RUNTIME_DIR="$PWD/build/odict-number-slice/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/odict-number-slice/frontier-test.log 2>&1` — exit 1; 260 checks passed, with two known failures: console type detection/control-cleanup order (line 215) and numeric dispatch (`ValueError: substring not found`, line 239). No harness-wide pass claimed. `bash scripts/vc6-probe.test.sh` also exited 1 because its compiler-diagnostic-output check failed; other checks in that script passed. No broad pass claimed. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/odict-number-slice/runtime-retry" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/odictobject.c` compiled; the prior line-900 C2059 is gone. First remaining stable errors are C2275/C2065 at `odictobject.c(1839)` for `PyObject *list`, followed by independent blockers at 2241, 2251, 2256, and 2297-2298. These are untouched. Capture: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791492247-1537598-3a80.log`. +- Focused verification rerun after the coding lane: both odict regression tests exited 0; scoped outer/nested `git diff --check` exited 0. The exact CPython tag/commit remain unchanged. The changed production initializer is the only new modification within the already-dirty `cpython/Objects/odictobject.c`; `odict_or()` and the remainder of `odictobject.c` retain their pre-run bytes. + +Files changed by this run: `cpython/Objects/odictobject.c` (positional `odict_as_number` initializer), new `scripts/vc6-odict-number-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: freshly probe before editing; if confirmed, isolate only the current first blocker in `odictobject.c` at line 1839 (`PyObject *list`). Do not claim port completion. + +--- + +## Latest run (`odict_or` first C89 declaration family; frontier advances) + +Date: 2026-10-08 18:32 UTC + +Read this status, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing dirty outer and detached CPython state. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact baseline tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyObject_DebugMallocStats()` frontier was stale. A forced-fresh VC6/Wine source-list probe confirmed `_blake2/blake2s_impl.c` compiles and the first blocker is `Objects/odictobject.c`, at the late `PyObject *new` declaration inside `odict_or()` (C2275/C2065 at line 875). The first focused Hermes coding-agent dispatch did not start because the Anthropic package is unavailable and lazy installs are disabled. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11cc7-e355-7182-ba94-9a3530930344`) then performed strict TDD. It added an exact-function C89 compile/runtime regression, observed the expected RED before production edit, and moved only the declaration of `new` into the function's declaration group; its assignment remains at the original point after the `PyDict_Check()` rejection. The regression exercises operand selection, rejection, constructor failure, update failure/cleanup, and success in eight cases. The distinct designated-initializer and later function blockers remain untouched. The coding lane verified all 145 pre-existing dirty/untracked files byte-for-byte unchanged. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-20261008T182533Z" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2275/C2065 at `odictobject.c(875)` for `PyObject *new`; separate diagnostics at 899, 1804, 2206-2221, and 2262-2263 remained. Capture: `build/cron-current/cron-20261008T182533Z-current-reprobe.log`. +- TDD RED: `python3 scripts/vc6-odict-or-c89.test.py cpython/Objects/odictobject.c` — exit 1 before source edit; expected ISO C90 mixed-declaration diagnostic (`-Wdeclaration-after-statement`). GREEN: same command after edit — exit 0, `odict_or C89 compile and operand/rejection/construction/update/cleanup order: PASS (8 cases)`. +- Applicable broader regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > /tmp/odict-or-frontier-tests.log 2>&1` — exit 1. It reports two existing unrelated failures: console type detection/control-cleanup order (line 215) and numeric dispatch (`ValueError: substring not found`, line 239). All other logged checks passed; no full-harness pass claimed. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-20261008T183212Z" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and the edited `odictobject.c` compiled past the `odict_or()` declaration. The former line-875 diagnostics are gone. First remaining diagnostic is C2059 at `odictobject.c(900)` for the designated initializer; subsequent independent blockers remain at 1805, 2207, 2217, 2222, and 2263-2264. Capture: `build/cron-current/cron-20261008T183212Z-post-odict.log`. +- Independent focused test rerun and `git -C cpython diff --check -- Objects/odictobject.c` / `git diff --check -- scripts/vc6-odict-or-c89.test.py` — exit 0. Baseline exact tag/commit verified unchanged. + +Files changed by this run: `cpython/Objects/odictobject.c` (only the `odict_or()` declaration/assignment split), new `scripts/vc6-odict-or-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: re-probe forced-fresh before edits; address only the first current `odictobject.c` diagnostic, the separate designated initializer at line 900. Do not claim port completion. + +--- + +## Latest run (`_PyObject_DebugMallocStats` declaration family; frontier advances) + +Date: 2026-10-08 16:24 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyObject_DebugMallocStats()` frontier was confirmed by a forced-fresh probe before editing. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11c4e-a3a7-7b73-a20f-1f4c20e4a4f4`) used strict TDD for this function only. The new focused test failed before production changes with the expected declaration-order assertion. Then only local declarations were hoisted before the `_PyMem_PymallocEnabled()` early-return guard. All scalar initializers were converted to assignments after the guard at the original execution point and in original order. The guard still returns before those initializations, array zeroing is unchanged, and the rest of the function is asserted byte-semantically through normalized token order. No other function was edited by this slice. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-$(date -u +%Y%m%dT%H%M%SZ)" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; `_blake2/blake2s_impl.c` compiled; summary `total=101 compiled=100 cached=0 skipped=0`. First stable diagnostics were C2143 at `Objects/obmalloc.c(3035-3036)`, then C2275/C2146/C2065 at `(3038-3042)`. Capture: `build/cron-current/cron-20261008-current-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-debugmallocstats-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before source edit with the expected assertion that declarations must precede the guard. +- TDD GREEN and complete focused obmalloc regressions: `python3 scripts/vc6-obmalloc-debugmallocstats-c89.test.py cpython/Objects/obmalloc.c && for test in scripts/vc6-obmalloc-*.test.py; do python3 "$test" cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h || exit "$?"; done` — exit 0. All 16 discovered `vc6-obmalloc-*.test.py` scripts exited 0. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-$(date -u +%Y%m%dT%H%M%SZ)-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled, and the former `obmalloc.c(3035-3050)` diagnostics are gone. First stable blocker advanced to `Objects/odictobject.c`: C2275/C2065 at lines 875, 1804, 2206-2221 and C2059/C2143/C2065 around 899 and 2262-2263. Capture: `build/cron-current/cron-20261008-debugmallocstats-post.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-obmalloc-debugmallocstats-c89.test.py` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. CPython exact tag and commit unchanged. + +Files changed by this run: `cpython/Objects/obmalloc.c` (only `_PyObject_DebugMallocStats()` within the existing dirty source file), new `scripts/vc6-obmalloc-debugmallocstats-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. MSVC6 banner was not separately recorded in this run. Next frontier: fresh forced-fresh probe before edits, then isolate only the first current `Objects/odictobject.c` blocker using its own TDD slice. Do not claim port completion. + +--- + +## Latest run (fresh `_PyObject_DebugMallocStats` frontier; coding delegation unavailable) + +Date: 2026-10-08 14:12 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyObject_DebugMallocStats()` blocker was freshly reprobed with forced-fresh MSVC600/Wine compilation. `_blake2/blake2s_impl.c` compiled; the first stable blocker remains in `Objects/obmalloc.c` at `_PyObject_DebugMallocStats()`. VC6 reports C2143 at lines 3035-3036, where declarations follow the executable `_PyMem_PymallocEnabled()` guard/return, then C2275/C2146/C2065 for the `size_t` declarations at lines 3038-3042 and cascades. One focused coding-subagent delegation was attempted for only this function, with strict TDD and preservation constraints, but failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. No source or test changes were made. This run is diagnostics-only; declaration/evaluation handling still requires a test-first implementation. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-$(date -u +%Y%m%dT%H%M%SZ)" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; summary `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics: C2143 at `obmalloc.c(3035-3036)`, then C2275/C2146/C2065 at `(3038-3042)`. Full captured tool output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791468469-1438139-8770.log`. +- Focused coding delegation — failed before child startup: `anthropic` package required; lazy installs disabled. No child edits. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed this run: `PORT_STATUS.md` only. All pre-existing source/test modifications remain untouched. Compiler-probe progress only; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: retry a focused TDD coding lane for `_PyObject_DebugMallocStats()` when a coding agent can start; keep declarations needed before the early guard distinct from later locals where moving initialization could change timing. Do not claim port completion. + +--- + +## Previous latest run (fresh `_PyObject_DebugMallocStats` frontier; coding lane unavailable) + +Date: 2026-10-08 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved the existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded post-`_PyMem_DebugCheckAddress()` compiler state was freshly reprobed. The forced-fresh source-list probe compiled `_blake2/blake2s_impl.c`; the actual first stable blocker has advanced to `Objects/obmalloc.c` in `_PyObject_DebugMallocStats()`. VC6 first reports C2143 at lines 3035-3036, where declarations follow the executable `_PyMem_PymallocEnabled()` guard/return. It then reports C2275/C2146/C2065 for the subsequent `size_t` declarations at lines 3038-3042, followed by cascades through later locals. No source or test change was made: the required single focused coding-subagent attempt failed before startup because the Anthropic package is unavailable and lazy installs are disabled. This is diagnostic-only; the function’s exact declaration/evaluation requirements still need a TDD test before implementation. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-20261008-rerun" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-20261008-current-frontier.log 2>&1` — actual probe exit 2; summary `total=101 compiled=100 cached=0 skipped=0`. First stable diagnostics: C2143 at `obmalloc.c(3035-3036)`, then C2275/C2146/C2065 at `(3038-3042)`; `_blake2/blake2s_impl.c` compiled. Full capture: `build/cron-current/cron-20261008-current-frontier.log`. +- Focused coding delegation for only the confirmed `_PyObject_DebugMallocStats()` declaration family — failed before child startup: missing `anthropic` package; lazy installs disabled. No child edits were applied. +- Nested baseline checks: exact tag `v3.11.16` and commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. + +Files changed this run: `PORT_STATUS.md` only. All pre-existing source/test modifications remain untouched. This is compiler-probe progress only; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: a focused TDD lane for the declarations in `_PyObject_DebugMallocStats()` when a coding agent can start; preserve initialization/evaluation relative to the early return and do not touch later blockers. + +--- + +## Previous latest run (`_PyMem_DebugCheckAddress` C89 declarations hoisted; compiler confirmation blocked) + +Date: 2026-10-08 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyMem_DebugRawRealloc()` frontier was freshly confirmed before editing: `_blake2/blake2s_impl.c` compiled, with first stable diagnostics in `Objects/obmalloc.c(2798-2802)` inside `_PyMem_DebugCheckAddress()`. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11af1-dee3-7112-adbc-cc56f4423bb4`) followed TDD and changed only that function plus a new focused test. It moved the `q` declaration before `assert` and kept `q = (const uint8_t *)p` after the assertion, preserving the pointer-cast evaluation point and all validation/error order. Test observed expected RED before production edit, then GREEN. All 15 `scripts/vc6-obmalloc-*.test.py` scripts passed with the required `pycore_pymem.h` argument for tracemalloc. Codex's forced-fresh probe attempts could not start the compiler: Wine repeatedly attempted to create `/run/user/1000/wine/server-801-136fb0/lock` and failed with `Read-only file system`; both attempts ended at `Modules/getpath.c`, `total=1 compiled=0 cached=0`. Thus the compiler frontier after this source edit is unverified and no compiler advancement is claimed. + +Exact verification: + +- Before-edit fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-20261008-confirm" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-20261008-confirm.log 2>&1` — wrapper exit 0 while recording actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. First stable diagnostics: C2143 at `obmalloc.c(2798)`, C2275/C2146/C2065 on `size_t nbytes` at `(2799)`, followed by late declaration diagnostics at `(2800-2802)`. `_blake2/blake2s_impl.c` compiled. +- TDD RED: `python3 scripts/vc6-obmalloc-debugcheckaddress-c89.test.py cpython/Objects/obmalloc.c` — exit 1 with expected entry-declaration assertion before production edit. GREEN: same command after edit — exit 0. +- Applicable regressions: `for test in scripts/vc6-obmalloc-*.test.py; do python3 "$test" cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h || exit "$?"; done` — all 15 exited 0. +- Post-edit forced-fresh probe attempted twice, exact command prefix `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-codex-check" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh`; actual exit 1 both times before compilation, despite project-local runtime directory creation. Logs: `build/cron-current/vc6-debugcheckaddress-frontier.log` and `build/cron-current/vc6-debugcheckaddress-frontier-retry.log`. Both show `sock_init: ERROR in sock_check_pollhup()`, Wine lock creation failure on read-only `/run/user/1000`, and `total=1 compiled=0 cached=0 skipped=0`. This is a Wine startup failure, not a compiler diagnostic. +- Independent checks: focused regression rerun and scoped `git diff --check` for `cpython/Objects/obmalloc.c` and the new test — exit 0. CPython tag/commit unchanged. + +Files changed by this run: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-debugcheckaddress-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: restore/diagnose a writable Wine server runtime, then force a fresh probe before selecting any further edit. Do not infer the next frontier from stale diagnostics. + +--- + +## Previous latest run (fresh obmalloc frontier confirmed; coding agent unavailable) + +Date: 2026-10-08 07:51 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved the existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyMem_DebugRawRealloc()` blocker at `obmalloc.c(2650-2658)` was freshly re-probed with forced-fresh VC6/Wine compilation. `_blake2/blake2s_impl.c` compiled; the first stable blocker has advanced to `Objects/obmalloc.c(2798-2802)`, late declarations in a subsequent function. No implementation was attempted because the required focused coding-agent delegation failed before startup: Hermes reported the Anthropic package is unavailable and lazy installs are disabled. Per the delegated-lane requirement, no production or test files were changed. The current first blocker is diagnostic evidence only; its specific function and safe isolated TDD test have not yet been established in this run. + +Exact verification: + +- Forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-20261008-realloc-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-20261008-realloc-reprobe.log 2>&1` — actual probe exit 2; summary `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `obmalloc.c(2798)`; C2275/C2146/C2065 on `size_t nbytes` at `(2799)`, then C2143 late-declaration diagnostics at `(2800-2802)`. Capture: `build/cron-current/cron-20261008-realloc-reprobe.log`. +- One focused coding-agent delegation was attempted for the confirmed blocker. It failed before startup with `The 'anthropic' package is required ... venv: not installed and lazy installs are disabled: ['anthropic']`. No child edits were applied. +- CPython baseline checks: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git diff --check` and `git -C cpython diff --check -- Objects/obmalloc.c` exited 0 before the status update. + +Files changed by this run: `PORT_STATUS.md` only. The worktree's pre-existing modifications and untracked tests remain preserved. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: retry one focused TDD coding lane for the confirmed `obmalloc.c(2798)` function, first identify its exact declaration family and a focused regression safely; do not broaden edits or claim port completion. + +--- + +## Latest run (`_PyMem_DebugRawRealloc` C89 locals hoisted; frontier advances) + +Date: 2026-10-08 05:45 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyMem_DebugRawFree()` follow-on was re-probed forced-fresh before editing; its previous entry-declaration fix remains. The probe confirms `_blake2/blake2s_impl.c` compiled and the first stable blocker moved to `_PyMem_DebugRawRealloc()` at `obmalloc.c(2650-2658)`: C2275/C2065 for late `debug_alloc_api_t *api`, followed by the distinct late `uint8_t` pointer, `size_t`, and `save` declarations. One focused Hermes coding-agent delegation failed before startup because the `anthropic` package is unavailable and lazy installs are disabled. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11a06-0784-7842-8da5-c5896b6ee1a6`) followed strict TDD. It added `scripts/vc6-obmalloc-debugrawrealloc-c89.test.py`, observed the expected RED assertion before production edits, then hoisted only `_PyMem_DebugRawRealloc()` locals (including guarded `block_serialno`) to the function entry. `api` remains initialized after the NULL return; `block_serialno` retains its read after the overflow guard and tail calculation. Existing operation/control-flow order and both preprocessor paths are asserted by the test. No neighboring function was modified. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-20261008-blake2" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-20261008-blake2-reprobe.log 2>&1` — actual probe exit 2; summary `total=101 compiled=100 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics are C2275/C2065 at `obmalloc.c(2650)` on `debug_alloc_api_t` / `api`, then C2275/C2065 at lines 2651-2658 for subsequent locals. Capture: `build/cron-current/cron-20261008-blake2-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-debugrawrealloc-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before source edit with expected assertion that all locals, including `block_serialno`, must be entry declarations. +- Focused GREEN and applicable obmalloc regressions: `scripts/vc6-obmalloc-debugrawrealloc-c89.test.py` plus every existing `scripts/vc6-obmalloc-*.test.py` script — all 14 scripts exit 0. Tracemalloc test was given `cpython/Include/internal/pycore_pymem.h`. Individual reruns confirmed each result. An attempted combined shell-loop invocation was blocked by the cron security scanner before execution; it is not counted as test failure or pass evidence. +- Post-change forced-fresh probe with runtime `build/cron-current/runtime-cron-20261008-blake2-post` and same flags — actual probe exit 2; summary `total=101 compiled=100 cached=0 skipped=0`. The previous diagnostics at 2650-2658 are gone; the first remaining stable diagnostics advance to `obmalloc.c(2798-2805)` in a later function. Capture: `build/cron-current/cron-20261008-blake2-post.log`. +- `git diff --check`, `git -C cpython diff --check`, exact tag/commit checks — exit 0; baseline unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. + +Files changed by this run: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-debugrawrealloc-c89.test.py`, and this status entry. This is compiler-probe progress only. Next: fresh forced-fresh probe before edits; if confirmed, inspect only the first `obmalloc.c(2798)` declaration blocker. Preserve all existing work and do not claim port completion. + +--- + +## Previous latest run (`_PyMem_DebugRawFree` C89 locals hoisted; frontier advances) + +Date: 2026-10-08 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved the existing dirty outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A fresh forced-fresh VC6/Wine probe showed the logged `insert_to_freepool()` frontier was stale: `_blake2/blake2s_impl.c` compiled and the first stable diagnostics were C2275/C2065 at `Objects/obmalloc.c(2628-2630)`, late declarations inside `_PyMem_DebugRawFree()` following its NULL early return. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a1198d-bd77-7c01-95e3-788ab2904294`) performed strict TDD. It added `scripts/vc6-obmalloc-debugrawfree-c89.test.py`, observed expected RED before production edits, then hoisted only `debug_alloc_api_t *api`, `uint8_t *q`, and `size_t nbytes` to function entry. Assignments to `api` and `q` remain after the `p == NULL` return, retaining the original evaluation point and NULL safety. The test checks declarations, the guard, assignment positions, and full operation order. `_PyMem_DebugRawRealloc()` and every other compiler blocker remain untouched. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-20261008" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-20261008-reprobe.log 2>&1` — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors: C2275 `debug_alloc_api_t` and C2065 `api` at line 2628, then C2275 `uint8_t`/C2065 `q` at 2629 and C2143 before `size_t nbytes` at 2630. Capture: `build/cron-current/cron-20261008-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-debugrawfree-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before source edit, expected entry-declaration assertion. +- GREEN and applicable regressions: `python3 scripts/vc6-obmalloc-debugrawfree-c89.test.py cpython/Objects/obmalloc.c && for test in scripts/vc6-obmalloc-*.test.py; do python3 "$test" cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h || exit "$?"; done` — exit 0; focused test and all 13 obmalloc scripts passed. +- Post-change forced-fresh probe with runtime `build/cron-current/runtime-cron-20261008-post`, same flags — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former diagnostics at lines 2628-2630 are gone; first stable blocker advances to `_PyMem_DebugRawRealloc()` at `obmalloc.c(2650-2655)`, C2275/C2065 for late `api`, `head`, `data`, `r`, `tail`, and `total` declarations. Capture: `build/cron-current/cron-20261008-post.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. `git diff --check` and `git -C cpython diff --check -- Objects/obmalloc.c` exited 0. Baseline-hash check confirmed the 4,767 other tracked/untracked files and indexes were unchanged by the coding lane; CPython source bytes outside `_PyMem_DebugRawFree()` were unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-debugrawfree-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: fresh forced-fresh probe before edits; if confirmed, address only the first `_PyMem_DebugRawRealloc()` declaration family, with its own TDD slice. Do not claim port completion. + +--- + +## Previous latest run (`insert_to_freepool` C89 locals hoisted; frontier advances) + +Date: 2026-10-07 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Re-probed the recorded `insert_to_freepool()` frontier with forced-fresh VC6/Wine compilation before editing. `_blake2/blake2s_impl.c` compiled; the first stable diagnostic was C2143 at `obmalloc.c(2109)` for a declaration after executable statements, followed by undeclared `ao` at 2110 and more late declarations (`nf`, `lastnf`). Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11829-db82-70c1-87da-d70916c05d82`) for strict TDD. Added `scripts/vc6-obmalloc-insert-to-freepool-c89.test.py`; its RED run failed with the expected assertion requiring entry declarations. Then hoisted only six locals (`next`, `prev`, `ao`, `nf`, `lastnf`, `p`) to function entry; all initialized values remain assigned at their original evaluation points, including `p` inside its branch. Assertions, branch/control flow, and pointer update order are retained. No neighboring function was edited. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-rerun" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-insert-freepool-reprobe.log 2>&1` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics: C2143 at `obmalloc.c(2109)`, C2065 `ao` at `(2110)`, then C2143 at `(2112)` and `(2117)`. Log: `build/cron-current/cron-insert-freepool-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-insert-to-freepool-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before production edit; expected assertion `insert_to_freepool must declare all six locals without initializers at function entry`. +- TDD GREEN and all 11 `scripts/vc6-obmalloc-*.test.py` regressions — exit 0. This included insert-to-freepool, insert-to-usedpool, pool-extend/allocator, calloc, arena-map, allocator-name/default-allocator, RawWcsdup, setup-allocators, and tracemalloc initializer checks. Tracemalloc invocation included `cpython/Include/internal/pycore_pymem.h`. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-post-insert-freepool" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/post-insert-to-freepool.log 2>&1` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former diagnostics at lines 2109-2117 are gone. First remaining diagnostic is C2143 at `obmalloc.c(2286)` in the next function, `pymalloc_free()`; its late local declaration is untouched. Log: `build/cron-current/post-insert-to-freepool.log`. +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- scripts/vc6-obmalloc-insert-to-freepool-c89.test.py` — exit 0. Nested baseline tag/commit unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-insert-to-freepool-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: fresh forced-fresh probe before any edits; if confirmed, handle only the first `pymalloc_free()` declaration family at line 2286 with a separate TDD slice. Do not claim port completion. + +--- + +## Latest run (`insert_to_usedpool` C89 locals hoisted; frontier advances) + +Date: 2026-10-07 18:52 UTC + +Read this status, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Re-probed the prior `_PyObject_Calloc()`/`insert_to_usedpool()` state with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; `_PyObject_Calloc()` diagnostics were gone and the first stable blocker was `insert_to_usedpool()`'s late declarations at `obmalloc.c(2083-2085)`. Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a117af-724f-72c0-bb0a-17cc39fe3fb2`) for strict TDD. The lane added `scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py`, observed expected RED before changing production source, then hoisted only `uint size`, `poolp next`, and `poolp prev` to function entry and changed their initializers to assignments after the original assertion. The size calculation, lookup order, and four pointer-link writes are preserved. No neighboring function or later blocker was changed. The coding lane initially passed the wrong header to the broad obmalloc test loop; that invocation failed at tracemalloc header discovery. It corrected the header and the complete applicable obmalloc test set passed. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron-calloc-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-calloc-reprobe.log 2>&1` — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2143 at `obmalloc.c(2083)`, followed by C2275/C2146/C2065 for `poolp next` and `poolp prev` at `(2084-2085)`. Log: `build/cron-current/cron-calloc-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before source edit with expected assertion that `size`, `next`, and `prev` must be declared without initializers at function entry. +- TDD GREEN: same command after source edit — exit 0; `obmalloc insert_to_usedpool entry declarations and original operation order: PASS`. +- Applicable obmalloc regressions (new insert-to-usedpool test plus all existing `vc6-obmalloc-*.test.py` tests) — exit 0. The exact corrected chained command is recorded in the Codex output `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791398735-1124658-4e90.log`; every script passed, including the tracemalloc test with `cpython/Include/internal/pycore_pymem.h`. Independently reran the complete applicable set: all 10 `scripts/vc6-obmalloc-*.test.py` scripts passed (exit 0). +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-post-usedpool" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/post-insert-to-usedpool.log 2>&1` — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former `insert_to_usedpool()` diagnostics at `(2083-2085)` are gone. First remaining errors are in the next function `insert_to_freepool()`, beginning C2143 at `(2109)` and C2065 `ao` at `(2110)`; left untouched. `_blake2/blake2s_impl.c` compiled. Log: `build/cron-current/post-insert-to-usedpool.log`. +- Broader frontier regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/insert-to-usedpool-regression-suite.log 2>&1` — exit 1. It reports `_thread` and tracemalloc checks passed but retains the known `ValueError: substring not found` failure; no harness-wide pass claimed. +- `git diff --check -- PORT_STATUS.md scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. CPython exact tag/commit unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: perform a fresh forced-fresh probe before edits; if confirmed, address only the first `insert_to_freepool()` declaration family at line 2109 with a separate TDD slice. Do not claim port completion. + +--- + +## Latest run (`pymalloc_alloc` locals hoisted for VC6; frontier advances) + +Date: 2026-10-07 14:25 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `allocate_from_new_pool()` frontier was re-probed before edits. Forced-fresh VC6/Wine compilation confirmed `_blake2/blake2s_impl.c` compiled; the prior diagnostics at `obmalloc.c(2007-2009)` were stale and the actual first diagnostic group was late declarations in the subsequent `_PyObject_Calloc()` / `insert_to_usedpool()` code. Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a116bb-a28a-72e1-aa0e-2e149d4d582f`). It extended the existing pool-extend regression with a `pymalloc_alloc()` declaration/order assertion, observed expected RED before source edits, then hoisted only `uint size`, `poolp pool`, and `block *bp` to the function entry. Their initializations and all existing early-return, pool-read, and branch evaluation/control-flow order remain unchanged. No subsequent declarations or distinct functions were edited. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-reprobe-latest.log 2>&1` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostic C2143 at `obmalloc.c(2007)`, followed by C2275/C2146/C2065 at lines 2008-2009. The capture also included later cascades. +- TDD RED: `python3 scripts/vc6-obmalloc-pool-extend-c89.test.py cpython/Objects/obmalloc.c` — exit 1; expected assertion `pymalloc_alloc must declare size, pool, and bp without initializers at function entry`; preceding checks for `pymalloc_pool_extend` and `allocate_from_new_pool` passed. +- TDD GREEN: same focused command — exit 0; all three pool/allocator declaration-order checks passed. Seven other obmalloc regression scripts (allocator-name, arena-map-is-used, arena-map-mark-used, default allocator, RawWcsdup/allocated-blocks, setup-allocators, tracemalloc-init) each exited 0; tracemalloc used `cpython/Include/internal/pycore_pymem.h`. Codex lane's per-command output is in `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791382756-1050053-2fd0.log`. +- Applicable regression harness `bash scripts/vc6-probe-pythoncore-frontier.test.sh > /tmp/pymalloc-alloc-frontier.log 2>&1` — exit 1. Known unrelated console type-detection/order assertion failed; numeric-dispatch check raised `ValueError: substring not found`. Many other checks passed; no broad-suite pass claimed. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-post-pymalloc" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/post-pymalloc-alloc.log 2>&1` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. No diagnostics remain at `obmalloc.c(2007-2009)`. First remaining errors are C2143 at lines 2059 and 2061, followed by C2065 `ptr` / `nbytes` at lines 2062-2063 in `_PyObject_Calloc()`; subsequent C89 diagnostics at line 2080 onward are separate and untouched. This is compiler-probe progress only. +- `git diff --check` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. Nested baseline verified: exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, extended `scripts/vc6-obmalloc-pool-extend-c89.test.py`, and this status entry. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: freshly probe before edits; if confirmed, handle only the first current blocker in `_PyObject_Calloc()` at lines 2059-2063 with its own TDD slice. Do not claim a completed port. + +--- + +## Latest run (`allocate_from_new_pool` pool declaration hoisted; frontier advances) + +Date: 2026-10-07 09:56 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Re-probed the recorded `poolp next` frontier before editing. It had already been fixed locally: the current first blocker was the separate late initialized `poolp pool = usable_arenas->freepools` declaration in `allocate_from_new_pool()`. Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a115c5-019c-76d0-ba38-5934bc3d03d6`) after native delegation failed because the Anthropic package is unavailable and lazy installs are disabled. The lane extended the existing pool-extend test, ran the focused test RED before production edit, then hoisted only `poolp pool` to function entry. The assignment remains after the arena-list updates at its original execution point. Existing early returns, allocator list operations, and subsequent pool initialization remain unchanged. `pymalloc_pool_extend()` and the distinct subsequent blockers were not altered. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-confirm" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2275/C2146/C2065 at `obmalloc.c(1889)` on `poolp pool`; following pointer errors are cascades. Log: `build/cron-current/cron-reprobe-current.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-pool-extend-c89.test.py cpython/Objects/obmalloc.c` — exit 1; expected assertion that `allocate_from_new_pool` must declare `pool` without an initializer at function entry. The prior `pymalloc_pool_extend` assertion passed. +- Focused GREEN and eight applicable obmalloc tests: `python3 scripts/vc6-obmalloc-pool-extend-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-arena-map-is-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all checks passed. The RawWcsdup test includes C89 compile/runtime checks. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1; existing console type-detection/cleanup-order assertion and numeric-dispatch `ValueError: substring not found` remain. No harness-wide pass claimed. +- Post-change forced-fresh probe (same options, runtime `build/cron-current/runtime-post`) — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`; the former `poolp pool` diagnostics are gone. First remaining diagnostics now occur later in `obmalloc.c` at lines 1947-1952 (`block bp`, then `poolp next` in a separate function); further C89 declaration/type blockers follow. Log: `build/cron-current/post-pool-entry.log`. +- `git diff --check` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. Exact baseline tag/commit remain unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, extended `scripts/vc6-obmalloc-pool-extend-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: freshly probe before edits and address only the first current blocker in the next function in `obmalloc.c` (currently `block *bp` at line 1947), with its own TDD slice. Do not claim port completion. + +--- + +## Previous latest run (`pymalloc_pool_extend` next declaration hoisted; frontier advances) + +Date: 2026-10-07 07:34 UTC + +Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or broad patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `poolp next` frontier was confirmed by a fresh forced-fresh MSVC600/Wine probe: `total=101 compiled=100 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors were C2275/C2146/C2065 at `obmalloc.c(1838)` for late `poolp next`, then pointer-type cascades. Hermes coding-subagent dispatch failed before startup because the `anthropic` package is unavailable and lazy installs are disabled. Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11547-34ae-7a62-b889-a4ff244cc66a`) following strict TDD. It added `scripts/vc6-obmalloc-pool-extend-c89.test.py`, observed expected RED before modifying production source, then hoisted only `poolp next` to function entry. Its assignment remains at the original point after the full-pool branch. No behavior or evaluation order changed; the distinct later `poolp pool` blocker was not touched. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. First errors C2275/C2146/C2065 at `obmalloc.c(1838)` for `poolp next`. Log: `build/cron-current/cron-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-pool-extend-c89.test.py cpython/Objects/obmalloc.c` — exit 1, expected assertion that `next` must be declared at function entry. +- Focused GREEN/regressions: `for test in scripts/vc6-obmalloc-*.test.py; do python3 "$test" cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h || exit "$?"; done` — exit 0; all eight obmalloc tests passed, including pool-extend declaration/order, allocator and arena-map tests, RawWcsdup C89 compile/runtime checks, setup allocators, and tracemalloc initializer. +- First post-change forced-fresh attempt — exit 1 before compiler startup; Wine server failed to create a lock under read-only `/run/user/1000`. This is not compiler evidence. Retried with `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-retry"` and the same command — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `obmalloc.c` compiled through the changed function. Former line-1838 diagnostics are gone. First remaining blocker is the separate late `poolp pool` at `obmalloc.c(1889)` (C2275/C2146/C2065); following `->` errors cascade. Log: `build/cron-current/post-pool-next.log`. +- `git -C cpython describe --tags --exact-match HEAD` / `rev-parse HEAD` verified unchanged baseline. Codex preservation snapshot found only the intended pre-existing modified `cpython/Objects/obmalloc.c` plus the new test; the production diff is only the declaration move. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-pool-extend-c89.test.py`, and this status entry. Compiler-probe progress only. Next: fresh forced probe before any further change; if confirmed, address only the separate `poolp pool` declaration at line 1889 using TDD. Do not claim port completion. + +--- + +## Previous latest run (`arena_map_is_used` C89 locals hoisted; frontier advances) + +Date: 2026-10-07 03:21 UTC + +Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced-fresh probe confirmed the prior arena-map frontier had advanced: `_blake2/blake2s_impl.c` compiled and the first stable errors were the late `i3`, `hi`, `lo`, and `tail` declarations inside `arena_map_is_used()` (`obmalloc.c(1592,1594-1596)`). The Anthropic coding subagent failed before startup because the `anthropic` package is missing and lazy installs are disabled. Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a1145b-a4bc-7c90-8b48-2d26ea8bc7f9`) for strict TDD. It added `scripts/vc6-obmalloc-arena-map-is-used-c89.test.py`, observed expected RED before production edits, then hoisted only `int i3` and `int32_t hi`, `lo`, `tail` above the NULL guard. Their assignments remain after the successful lookup / NULL return at their original evaluation points. The lookup, null behavior, assignment order, and short-circuit predicate remain unchanged. Hash preservation check after the coding lane confirmed the other 134 pre-existing dirty/untracked files (including `PORT_STATUS.md` at that point) and source outside this function were byte-identical; this status entry was updated afterward for the current run. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostic C2143 at `obmalloc.c(1592)`, followed by C2275/C2146/C2065 on `int32_t hi`, `lo`, and `tail` at lines 1594-1596. Log: `build/cron-current/cron-reprobe.log`. +- TDD RED before source edit: `python3 scripts/vc6-obmalloc-arena-map-is-used-c89.test.py cpython/Objects/obmalloc.c` — exit 1, expected assertion that the function must declare its locals before the NULL guard. +- Focused regressions, independently rerun after edit: new arena-map-is-used test, arena-map-mark-used, allocator-name, default-allocator, RawWcsdup/allocated-blocks, setup-allocators, and tracemalloc-init tests — all exit 0. Exact chained command: `python3 scripts/vc6-obmalloc-arena-map-is-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h`. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/arena-map-is-used-regression-suite.log 2>&1` — exit 1. It reports the known console type-detection/order failure and numeric-dispatch `ValueError: substring not found`; no broad suite pass claimed. +- Post-change forced-fresh probe, same command as before-change: actual exit 2; `total=101 compiled=100 cached=0 skipped=0`. The `arena_map_is_used()` diagnostics are gone. First remaining errors are C2275/C2146/C2065 at `obmalloc.c(1838)` for a late `poolp next`, with a separate late `poolp pool` family at line 1888; left untouched. Log: `build/cron-current/post-arena-map-is-used.log`. +- `git -C cpython diff --check -- Objects/obmalloc.c`, `git diff --check -- PORT_STATUS.md scripts/vc6-obmalloc-arena-map-is-used-c89.test.py`, and CPython tag/commit checks — exit 0. No standalone compiler banner was recorded. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-arena-map-is-used-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: fresh forced-fresh probe before further changes; if the frontier remains, address only the first `poolp next` C89 declaration family at line 1838 using TDD. Do not claim port completion. + +--- + +## Previous run (`arena_map_mark_used` i3_next declaration hoisted; frontier advances) + +Date: 2026-10-07 01:09 UTC + +Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exactly at release tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +A fresh forced-fresh MSVC600/Wine probe confirmed the recorded `i3_next` blocker in `arena_map_mark_used()`. The Hermes coding-subagent API failed before startup because the Anthropic package is missing and lazy installs are disabled. Used one focused Codex CLI `codex exec` lane instead (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a113e3-575e-7512-89ed-0378245bfdd7`). It extended only the existing arena-map test, observed expected RED before production changes, then hoisted only `int i3_next` to function entry and changed its late initialized declaration to assignment at the original point after the `n_lo == NULL` return. Its expression, evaluation point, lookup and rollback/control flow remain unchanged. Other local changes were preserved. + +Exact verification: + +- Pre-change: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics C2143 at `obmalloc.c(1576)` and C2065 `i3_next` at `(1577)`. Capture: `build/cron-current/cron-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c` — exit 1, expected assertion that `i3_next` must be declared at function entry without initializer. +- Focused regressions: `python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all six pass. RawWcsdup includes C89 compile/runtime checks. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/i3-next-regression-suite.log 2>&1` — exit 1. Many checks pass; the known numeric-dispatch check raises `ValueError: substring not found`. No full-suite pass claimed. +- Post-change forced-fresh probe (same command, captured in `build/cron-current/post-i3-next.log`) — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former `i3_next` diagnostics are gone. First remaining blocker is `arena_map_is_used()` at line 1592 (C2143 on late `int i3`); subsequent C89/type diagnostics at 1594-1596 and pool diagnostics at 1833 onward are separate and untouched. The compile probe still does not link an interpreter. +- `git -C cpython describe --tags --exact-match HEAD` and `git -C cpython rev-parse HEAD` confirm baseline unchanged. Scoped `git diff --check` commands for the production and test files exited 0. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: fresh forced probe before further edits; if the frontier remains current, handle only the first `arena_map_is_used()` C89 declaration family using TDD. Do not claim port completion. + +--- + +## Previous run (fresh VC6 frontier probe; implementation lane unavailable) + +Date: 2026-10-06 22:57 UTC + +Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exactly at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. The recorded `n_lo` frontier is no longer the first blocker: a fresh forced-fresh VC6/Wine probe confirms `i3_next` at `Objects/obmalloc.c(1576-1577)` is now first. + +One focused Hermes coding-subagent attempt was made as required, but failed before startup: the Anthropic package is missing and lazy installs are disabled. No implementation or test change was made; this run is diagnostic-only rather than attempting an unreviewed direct edit. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-reprobe.log 2>&1; rc=$?; ...` — probe exit 2 (`total=101 compiled=100 cached=0 skipped=0`). `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `obmalloc.c(1576)` and C2065 `i3_next` at `(1577)`. Subsequent independent failures include declarations in `arena_map_is_used()` at 1591-1595 and pool-related errors at 1832 onward; left untouched. Full capture: `build/cron-current/cron-reprobe.log`. +- The terminal wrapper returned exit 0 because it printed and retained the actual probe return code (`PROBE_EXIT=2`); no compilation success is implied. +- Baseline verification: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Existing focused regression suite was not run because this diagnostics-only run changed no source/tests. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. + +Files changed this run: `PORT_STATUS.md` only. Next: use a focused coding lane when delegation is available to TDD only the `i3_next` declaration in `arena_map_mark_used()`, preserving its initialization/evaluation point; keep `arena_map_is_used()` and later pool blockers separate. Do not claim port completion. + +--- + +## Latest run (`arena_map_mark_used` n_lo declaration hoisted; frontier advances) + +Date: 2026-10-06 20:52 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before acting. Preserved the existing dirty outer and detached CPython changes; no reset, clean, stash, discard, commit, push, or patch regeneration. CPython remains at release tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `n_lo` frontier was freshly confirmed with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; the first blocker was C2275/C2065 at `Objects/obmalloc.c(1569)` on the late `arena_map_bot_t *n_lo`. Hermes coding-subagent dispatch could not start because the Anthropic package is missing and lazy installs are disabled. A focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write, ephemeral; session `01a112f7-89f4-7122-9f20-3c7d6c856113`) performed strict TDD. It extended only the existing arena-map test, observed expected RED before the source edit, then hoisted only `n_lo` to the function's declarations and changed its former initialized declaration to assignment at the original point after the overflow assertion. Existing null handling, rollback, and later `i3_next` declaration remain unchanged. The lane hash/inventory comparison confirmed every other pre-existing file remained byte-identical. + +Exact verification: + +- Pre-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2275/C2065 at `obmalloc.c(1569)` for `arena_map_bot_t *n_lo`. Capture: `build/cron-current/cron-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c` — exit 1 with expected assertion that `n_lo` must be declared without initializer at function entry. The test also locks assignment/evaluation and control-flow order. +- GREEN and focused obmalloc regressions: arena-map, allocator-name, default allocator, RawWcsdup/allocated-blocks, setup-allocators, and tracemalloc-init tests — all exit 0. Exact combined command: `python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h`. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/n-lo-regression-suite.log 2>&1` — exit 1. Many checks pass; the known unrelated numeric-dispatch check raises `ValueError: substring not found`. No suite-wide pass claimed. During the coding lane, an initial malformed batch invocation and a wrong header path also exited 1; the exact corrected combined command above passed all six scripts. +- Post-change forced-fresh probe (same command as pre-change) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The line-1569 `n_lo` diagnostics are gone. First remaining errors are C2143/C2065 at `obmalloc.c(1576-1577)` for the distinct late `i3_next` declaration; later errors at `arena_map_is_used()` and pool declarations are separate and untouched. Capture: `build/cron-current/post-n-lo.log`. +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py` — exit 0. Nested HEAD/tag remain exact. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py`, and this status entry. This is compiler-probe progress only. Next: perform a fresh forced-fresh probe before edits; if the frontier remains, address only `i3_next` in `arena_map_mark_used()` as a separate TDD slice. No commit or push. + +--- + +## Latest run (`arena_base_next` C89 declaration hoisted; frontier advances) + +Date: 2026-10-06 18:34 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, compatibility patch regeneration, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded next blocker after the prior `arena_map_mark_used()` declarations was freshly confirmed with a forced-fresh VC6/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; first diagnostics were C2275/C2146/C2065 at `Objects/obmalloc.c(1562)` for late `uintptr_t arena_base_next`. The required Hermes coding-subagent attempt failed before startup because the Anthropic package is missing and lazy installs are disabled. A focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a1127d-d96c-7162-b2b7-43f5313f1b89`) followed TDD. It extended the existing arena-map test to require the entry declaration and preserve initialization at the original assignment point, observed expected RED before production edits, then hoisted only this declaration. `arena_map_mark_used()` control flow and all later declarations/functions remain unchanged. + +Exact verification: + +- Baseline and working-tree check: outer branch `main`; nested CPython exact tag/commit `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Existing dirty and untracked state retained. +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First errors C2275/C2146/C2065 at `obmalloc.c(1562)` on `uintptr_t arena_base_next`. Capture: `build/cron-current/cron-reprobe.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c` — exit 1 after extending the test, expected assertion that `n_hi, i3, tail, arena_base_next` must be declared without initializers at entry. The unmodified existing test passed before extension. +- GREEN and focused obmalloc checks: arena-map, allocator-name, default allocator, RawWcsdup/allocated-blocks, setup-allocators, and tracemalloc-init scripts — all exit 0. The RawWcsdup test also compiled/exercised its C89 harness. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Numeric-dispatch check still raises `ValueError: substring not found`; captured in `build/cron-current/arena-base-next-regression.log` (line 238). Other logged checks passed; no suite-wide pass claimed. +- Post-change forced-fresh probe (same command) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The line-1562 diagnostics are gone. The first remaining blocker is C2275/C2065 at `obmalloc.c(1569)` for the separate late `arena_map_bot_t *n_lo`; later `i3_next`, `arena_map_is_used()`, and pool declarations remain untouched. Capture: `build/cron-current/post-arena-base-next.log`. +- Scoped nested `git diff --check -- Objects/obmalloc.c` and outer `git diff --check -- scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py` — exit 0. Exact CPython baseline unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py`, and this status log. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: fresh forced-fresh probe before edits; if the frontier remains, address only the separate late `arena_map_bot_t *n_lo` declaration in `arena_map_mark_used()` with its own TDD slice. No commit or push. + +--- + +## Previous latest run (arena_map_mark_used C89 declarations hoisted; frontier advances) + +Date: 2026-10-06 16:15 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, patch regeneration, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded radix-tree frontier was freshly confirmed before editing using forced-fresh MSVC600 through Wine. `_blake2/blake2s_impl.c` compiled; the first stable blocker was the late `n_hi`, `i3`, and `tail` declarations inside `arena_map_mark_used()` in `Objects/obmalloc.c`. Hermes coding-subagent delegation failed before startup because the Anthropic package is missing and lazy installs are disabled. Used one focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a11203-e64a-7843-943c-0fa3d62a875e`) for strict TDD. It added a focused order/declaration regression, observed expected RED before production edits, then hoisted only those three declarations to function entry. Their initializations remain after the original assertion, null check, and index evaluation at their original execution points. No neighboring `arena_map_is_used()` or later declaration families were changed. The coding lane's preservation check reported all 134 pre-existing changed/untracked files unchanged except for the intended source slice; it made no status-log edit. + +Exact verification: + +- Baseline check: outer branch `main` at `35caf1a558e6b2c5bf501894d8972f8b0dd828a6`; nested CPython exact tag/commit verified as `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Initial outer dirty state preserved. +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics C2143 at `obmalloc.c(1539)`, followed by C2143 at `(1544)` and C2275/C2146 for `int32_t tail` at `(1545)`. Capture: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791303333-689202-aea0.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before source edit; expected assertion that `n_hi`, `i3`, and `tail` must be declared at function entry. +- Focused GREEN and directly applicable obmalloc checks: the new arena-map test, `vc6-obmalloc-rawwcsdup-c89.test.py`, allocator-name, default-allocator, setup-allocators, and tracemalloc-init scripts — all exit 0. RawWcsdup script's C89 compile/runtime harness passed. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Many checks, including `_thread`, tracemalloc, and object regressions, pass. Existing numeric-dispatch check still raises `ValueError: substring not found`; no unrelated failures were changed. Capture: `build/cron-current/regression.log`. +- Post-change forced-fresh probe (same command as pre-change, captured in `build/cron-current/post-arena-mark-used.log`) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The errors at lines 1539-1545 are gone and compilation passes through the edited declarations. First remaining diagnostic is C2275 at `obmalloc.c(1562)` for the separate late `uintptr_t arena_base_next` declaration, followed by independent late `n_lo` and `i3_next` declarations and then `arena_map_is_used()` C89/type diagnostics. These are not addressed in this slice. +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py` — exit 0. Baseline tag/commit unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: fresh forced-fresh probe before any change; then address only the first current declaration blocker (`arena_base_next` in the `else` branch) with a separate TDD slice, preserving its original evaluation point. No commit or push. + +--- + +## Previous latest run (fresh radix-tree frontier confirmed; coding lane unavailable) + +Date: 2026-10-06 14:14 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference. Preserved all existing outer and detached CPython modifications; no reset, clean, stash, discard, commit, push, patch regeneration, or publication. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_Py_GetAllocatedBlocks()` fix remains present, but the recorded next-frontier summary was broad. A forced-fresh VC6/Wine source-list probe now confirms the actual first stable blocker is within `arena_map_mark_used()` in `Objects/obmalloc.c`: late declarations at lines 1539 (`arena_map_bot_t *n_hi`), 1544 (`int i3`), and 1545 (`int32_t tail`). Later declarations in the same function and the distinct `arena_map_is_used()` function remain separate; no source/test implementation was made. A focused Hermes coding-agent lane was attempted as required, but failed before startup because the Anthropic provider package is missing and lazy installs are disabled. No source edits were made. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-reprobe.log 2>&1` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First compiler diagnostics: C2143 at `obmalloc.c(1539)` and `(1544)`; then C2275/C2146 for `int32_t tail` at `(1545)`. Further errors at lines 1558 onward include distinct late declarations and cascades. Capture: `build/cron-current/cron-reprobe.log`. +- Focused existing regression: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c` — exit 0; allocated-block and RawWcsdup checks passed. +- `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/cron-regression.log 2>&1` — exit 1; existing unrelated numeric-dispatch assertion raised `ValueError: substring not found`. No broad-suite pass claimed. +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- PORT_STATUS.md` — exit 0. + +Files changed this run: `PORT_STATUS.md` only. This is diagnostics/compiler-probe evidence, not a linked `pythoncore.dll`/`python.exe`, Wine interpreter run, or Windows 98 SE result. Next: once a focused coding agent can start, TDD only the `arena_map_mark_used()` declaration-order family, preserving initializer evaluation points; do not change `arena_map_is_used()` or address separate type/API blockers. No commit or push. + +--- + +## Latest revision (`_Py_GetAllocatedBlocks` base declaration made C89-compatible; frontier advances) + +Date: 2026-10-06 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing dirty outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_Py_GetAllocatedBlocks()` frontier was freshly confirmed with forced-fresh MSVC600/Wine probing. `_blake2/blake2s_impl.c` compiled; the first blocker was C2143 at `Objects/obmalloc.c(1311)` on the late `uintptr_t base` declaration, followed by C2065 `base` at line 1314. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a11117-24ea-7ee0-bdcf-6a66cfbea801`) followed TDD. It extended the existing `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, observed RED before production edit, then hoisted only `uintptr_t base` into the function declaration group and converted the former initialized declaration to assignment at its original point after the arena skip. No other production statements or control flow were changed. A content-hash snapshot verified all 132 other pre-existing dirty/untracked files remained unchanged. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/reprobe.log 2>&1` — script exit 2 (compiler source-list failure); `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics C2143 at `obmalloc.c(1311)`, then C2065 `base` at 1314. Capture: `build/cron-current/reprobe.log`. +- TDD RED before production edit: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c` — exit 1 with the expected `_Py_GetAllocatedBlocks must declare uint i and uintptr_t base at entry and preserve loop operations` assertion. +- Focused GREEN: same command — exit 0; both allocated-block C89/order and RawWcsdup C89 runtime checks passed. +- Focused obmalloc regressions: allocator-name, default allocator, setup-allocators, and tracemalloc-init scripts (the latter with `cpython/Include/internal/pycore_pymem.h`) — all exit 0. One initial tracemalloc invocation used a nonexistent `pycore_tracemalloc.h` and exited 1; corrected invocation passed. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/regression.log 2>&1` — exit 1; existing `ValueError: substring not found` regression failure remains. No broad-suite pass claimed. +- Post-change forced-fresh probe (same command as pre-change, output `build/cron-current/postprobe.log`) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The line-1311/1314 diagnostics are gone; remaining obmalloc failures concern distinct radix-tree/C89/type issues, first visible at lines 1539 onward. `_blake2/blake2s_impl.c` compiled. No claim that `obmalloc.c` fully compiles. +- Scoped nested and outer `git diff --check` — exit 0. CPython exact tag/commit checks passed. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, and this status log. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: freshly re-probe before edits; inspect only the first stable current compiler diagnostic within the still-failing `obmalloc.c` translation unit. No commit or push. + +--- + +## Previous latest revision (`_Py_GetAllocatedBlocks` loop declaration made C89-compatible; frontier advances) + +Date: 2026-10-06 09:54 UTC + +Read this status, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved the pre-existing dirty outer worktree and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyMem_Strdup()` frontier was re-probed before editing. The forced-fresh MSVC600/Wine source-list probe passed `_blake2/blake2s_impl.c`; first blocker remained `Objects/obmalloc.c(1304)`, the C99 `for (uint i = ...)` declaration in `_Py_GetAllocatedBlocks()`. Hermes subagent delegation was unavailable because the runtime lacks the `anthropic` package and lazy installs are disabled. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write) performed the TDD slice: extended the existing untracked `scripts/vc6-obmalloc-rawwcsdup-c89.test.py` with a function-body/order assertion, observed RED before production edit, then hoisted only `uint i` into the function declaration group and changed the loop initializer to assignment. Loop bound, iteration, skip behavior, and accumulation are retained. All other local work was preserved. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First errors C2143 at `obmalloc.c(1304)` on the `for` declaration, followed by undeclared `i`; later C89 and arena-map/type errors were distinct. Capture: `build/cron-current/preprobe.log`. +- TDD RED: focused assertion in `scripts/vc6-obmalloc-rawwcsdup-c89.test.py` was reported by the coding lane as failing before the source edit because the entry declaration/C89 loop spelling was absent. (The lane's terminal transcript was truncated to its final diff in the returned output.) +- Focused GREEN/regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all five passed. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Existing unrelated console type detection/cleanup-order assertion and numeric-dispatch (`ValueError: substring not found`) failures persist; no broad-suite pass claimed. +- Post-change forced-fresh probe (same command) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled; prior line-1304 diagnostics are gone. First remaining errors are C2143 at `obmalloc.c(1311)` and C2065 `base` at 1314, followed by separate allocator arena-map/API/type issues. Capture: `build/cron-current/postprobe.log`. +- `git -C cpython diff --check -- Objects/obmalloc.c`, `git diff --check -- scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, CPython baseline tag/commit checks — exit 0. No commit or push. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, and this status log. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: fresh forced probe before any change; likely inspect the next declaration at `obmalloc.c(1311)` while keeping later arena-map/type/API diagnostics separate. + +--- + +## Previous latest revision (`_PyMem_Strdup` C89 declarations hoisted; probe advances) + +Date: 2026-10-06 07:27 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active CPython Win9x/MSVC6 reference before acting. Preserved the dirty outer worktree and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The previously recorded `_PyMem_Strdup()` frontier was revalidated with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled and the first failing translation unit was `Objects/obmalloc.c`; VC6 reported C2143 at lines 713-714 before the late `size_t size` / `char *copy` declarations, then undeclared-variable cascades. One focused Codex CLI lane (0.153.4, workspace-write; session `01a11020-6ea2-7702-91e3-42cfddc5ea95`) followed TDD: added an assertion for `_PyMem_Strdup()` to `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, observed the expected RED before production edits, then hoisted only those two declarations to function entry and retained initialization after `assert` plus allocation/null/copy/return order. A file-hash and inventory comparison confirmed every other dirty/untracked file was preserved. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. First errors C2143 at `obmalloc.c(713-714)`, then C2065 cascades for `copy` and `size`. `_blake2/blake2s_impl.c` compiled. +- TDD RED: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c` — exit 1 with expected `_PyMem_Strdup must use C89 entry declarations and preserve operation order` assertion. +- Focused GREEN/regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all five passed. An earlier tracemalloc invocation omitted its required header argument and exited 1; the corrected exact command above passed. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1; existing unrelated console type detection/cleanup ordering and numeric-dispatch (`ValueError: substring not found`) assertions persist. The obmalloc tests passed; no broad-suite pass claimed. +- Post-change forced-fresh probe (same as pre-change, redirected to `build/cron-current/strdup-post.log`) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The `_PyMem_Strdup()` diagnostics at lines 713-719 are gone. Next first compiler error is C2143 at `obmalloc.c(1304)` for a `for` loop declaration; subsequent failures include the distinct obmalloc C89/API issues (including missing `int32_t`-related type parsing) and remain untouched. Compiler probe only. +- `git -C cpython diff --check -- Objects/obmalloc.c`, `git diff --check -- scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, and exact CPython tag/commit checks — exit 0; baseline unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, and this status log. This is not a linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE verification. Next frontier: fresh forced probe before any further edits, then isolate the earliest remaining `obmalloc.c` C89 loop declaration at line 1304 as its own TDD slice. No commit or push. + +--- + +## Previous latest revision (fresh VC6 frontier confirmed; focused implementation delegation unavailable) + +Date: 2026-10-06 01:05 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyMem_RawStrdup()` frontier was freshly confirmed with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; the first failing translation unit remains `Objects/obmalloc.c`. First stable errors are C2143 at lines 697-698 on declarations after `assert`, with C2065 cascades for `copy` and `size`. The neighboring `_PyMem_Strdup()` errors at 710-711 and later obmalloc diagnostics are distinct and untouched. One focused coding-agent delegation for the single `_PyMem_RawStrdup()` slice was attempted, but did not start because the Hermes runtime lacks the `anthropic` package and lazy installs are disabled. No production or test edits were made; this run is diagnostics-only. + +Exact verification: + +- Forced-fresh VC6/Wine probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics C2143 at `obmalloc.c(697-698)`, followed by C2065 `copy` and `size` cascades. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791248452-462887-c640.log`. +- Focused obmalloc regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all four passed. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The relevant obmalloc checks passed; two known unrelated failures persist: console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`). No suite-wide pass claimed. +- Delegation attempt for only `_PyMem_RawStrdup()` — failed before agent startup: missing `anthropic` package; lazy installs disabled. No child edits were applied. +- `git -C cpython diff --check -- Objects/obmalloc.c`, `git diff --check -- PORT_STATUS.md`, and CPython exact tag/commit checks — exit 0; baseline unchanged. + +Files changed this run: `PORT_STATUS.md` only. This remains compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: retry one focused TDD coding lane when delegation is available, limited to `_PyMem_RawStrdup()`'s declaration family; keep `_PyMem_Strdup()` and later obmalloc blockers separate. + +--- + +Date: 2026-10-05 22:59 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference first. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyMem_RawStrdup()` frontier was forced-fresh re-probed and remains current. The source-list compile built `_blake2/blake2s_impl.c` and `Objects/object.c`; `Objects/obmalloc.c` is the first failing translation unit. First stable errors are C2143 at lines 697 and 698, before `size_t size` and `char *copy` declarations following `assert(str != NULL)`, then C2065 cascades for `copy` and `size`. This confirms the frontier but not a source fix. Per the required workflow, one focused coding-subagent delegation was attempted for this function only and failed before startup because Hermes lacks the `anthropic` package and lazy installs are disabled. No source or test edits were made; this run is diagnostics-only. + +Exact verification: + +- Forced-fresh VC6/Wine probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable compiler diagnostics are C2143 at `obmalloc.c(697-698)`, with C2065 cascades at 699/702. Later independent C89/API diagnostics remain in `obmalloc.c` and were not addressed. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791240907-436248-f100.log`. +- Focused obmalloc regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all four passed. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The relevant obmalloc checks pass; the two known unrelated failures persist: console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`). No broad-suite pass claimed. +- Focused implementation delegation for only `_PyMem_RawStrdup()` — failed before agent startup: missing `anthropic` package; lazy installs disabled. No source/test edits were applied. +- `git -C cpython diff --check -- Objects/obmalloc.c`, `git diff --check -- PORT_STATUS.md`, and CPython exact tag/commit checks — exit 0; baseline unchanged. + +Files changed this run: `PORT_STATUS.md` only. All pre-existing changes remain preserved. This is compiler-probe evidence only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: retry a focused TDD coding lane when delegation is available, limiting implementation to the declaration family in `_PyMem_RawStrdup()`; otherwise continue diagnostics only. Keep `_PyMem_Strdup()` and later obmalloc blockers separate. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains CPython `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The prior status recorded the post-`_PyMem_RawWcsdup()` next probe as blocked at Wine startup, so the compiler frontier was unverified. A forced-fresh probe now ran successfully through the source list. `_blake2/blake2s_impl.c` and `Objects/object.c` compiled. The first stable VC6 errors are in the separate `_PyMem_RawStrdup()` at `Objects/obmalloc.c(697-698)`: C2143 before `size_t size`, then before `char *copy`, followed by undeclared-variable cascades. The source confirms both declarations follow `assert(str != NULL)`. `_PyMem_Strdup()` has a similar later issue at 710-711, but it is a distinct later function and remains untouched. + +Attempted the required single focused coding-subagent delegation for only `_PyMem_RawStrdup()`; it failed before startup because Hermes lacks the `anthropic` package and lazy installs are disabled. Per the delegated-lane requirement, made no production or test edits. Ran current focused obmalloc regressions as diagnostics; all passed. The applicable broader harness still has its two known unrelated failures, so no broad-suite pass is claimed. + +Exact verification: + +- Forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First errors: C2143 at `obmalloc.c(697)` and `(698)`, followed by C2065 `copy` and `size` cascades. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791233276-411114-ad70.log`. +- Focused regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all four passed. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Known unrelated console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`) failures remain; relevant obmalloc checks passed. +- Delegation attempt for the one `_PyMem_RawStrdup()` TDD slice — failed before agent startup: missing `anthropic` package; lazy installs disabled. No source/test edits applied. +- `git -C cpython rev-parse HEAD`, `git -C cpython describe --tags --exact-match HEAD`, outer `git diff --check`, and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0; baseline unchanged and scoped diffs clean. + +Files changed this run: `PORT_STATUS.md` only. This remains compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: one test-first slice for `_PyMem_RawStrdup()` only after a focused coding lane is available; keep `_PyMem_Strdup()` and later obmalloc errors separate. + +--- + +## Previous latest revision (_PyMem_RawWcsdup C89 declarations hoisted; post-change VC6 probe blocked by Wine) + +Date: 2026-10-05 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference first. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyMem_SetupAllocators()` frontier was stale. A forced-fresh VC6/Wine source-list probe passed `_blake2/blake2s_impl.c`, `Objects/object.c`, and the allocator setup functions; the actual first diagnostics were C2143/C2065 at `Objects/obmalloc.c(674-675)` in `_PyMem_RawWcsdup()`, for `size_t len` declared after `assert`. One focused Codex CLI lane (0.153.4, workspace-write; session `01a10d62-5acc-7532-8e6a-64eee226a083`) hoisted only `len`, `size`, and `str2` to the function's declaration group and changed their original declarations to assignments at the same execution points. The overflow guard, allocation, failure return, copy size, and return order are unchanged. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics C2143 at `obmalloc.c(674)` before `type`, C2065 `len` at 675, with distinct C89 declarations later in adjacent helpers and other obmalloc code. Full capture: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791225631-384995-c8a0.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before the source edit; generated C harness failed under `-std=c89 -pedantic-errors` on the original mixed declarations at lines 33 and 38. The first harness invocation also exposed an unescaped regex-quote construction error, corrected before the expected RED; no production edit preceded the RED. +- GREEN after source edit: same focused command — exit 0; generated exact-function C89 harness passed copy, empty-string, allocation-failure, and overflow/order checks. +- Existing focused obmalloc allocator-name, default-allocator, setup-allocators, and tracemalloc-init regressions — exit 0. Applicable full regression harness was not run in this slice. +- Post-change forced-fresh probe (same command) — exit 1 before any compiler invocation; Wine reported `sock_init: ERROR in sock_check_pollhup()` and `wineserver: error creating /run/user/1000/wine/server-801-136fb0/lock: Read-only file system`, summary `total=1 compiled=0 cached=0 skipped=0`. This is a Wine startup failure, not compiler evidence; next compiler frontier is unverified. A retry was not made to avoid repeatedly invoking a broken shared Wine server. +- `git -C cpython diff --check -- Objects/obmalloc.c` and outer `git diff --check -- scripts/vc6-obmalloc-rawwcsdup-c89.test.py` — exit 0. Baseline commit unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, and this status entry. This is source-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: restore a writable Wine server runtime and run the forced-fresh probe before choosing any further edit; only then follow its first stable compiler blocker (expected adjacent helper declarations are not yet confirmed as frontier). + +--- + +## Previous latest revision (_PyMem_SetupAllocators pymalloc declaration moved before statements) + +Date: 2026-10-05 16:38 UTC + +Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before working. Preserved the existing dirty outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_blake2/blake2s_impl.c` sequence was verified with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` and `Objects/object.c` compiled. The first blocker was `Objects/obmalloc.c(349)`: C2275/C2146/C2065/C2059 on the late `PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC` declaration after the RAW allocator registration in `_PyMem_SetupAllocators()`. Native coding-subagent delegation failed because the Hermes runtime lacks the `anthropic` package; one focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a10ce7-820c-7ee3-9e1f-ecb1c0f5a7bd`) followed TDD. It added `scripts/vc6-obmalloc-setup-allocators-c89.test.py`, observed expected RED before the production edit, then moved only the `pymalloc` initialized declaration above the first statement. All initializer values and RAW/MEM/OBJ/debug-hook order are retained. No subsequent `obmalloc.c` diagnostics were changed. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled; first diagnostics were C2275/C2146/C2065/C2059 at line 349. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791217565-339027-c050.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c` — exit 1; expected assertion `both allocator initializers must precede the first statement for C89`. +- GREEN and focused regressions: setup-allocators, default-allocator, and tracemalloc-init scripts — all exit 0. The setup test confirms field values and RAW/MEM/OBJ/debug order. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > build/cron-current/regression-suite.log 2>&1` — exit 1. Two pre-existing unrelated failures remain: console type detection/cleanup ordering and numeric dispatch (`ValueError: substring not found`). No suite-wide pass claimed. +- Post-change forced-fresh probe (same exact command as before-change) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The line-349 diagnostics are gone; first remaining diagnostics are C2275/C2146/C2065/C2059 at `obmalloc.c(412-414)` for separate `dbg_raw`, `dbg_mem`, and `dbg_obj` initializers. Later errors untouched. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791218002-339027-ce90.log`. +- Scoped outer/nested `git diff --check` — exit 0. Baseline tag/commit unchanged. Preservation snapshot from the coding lane reports all other 130 pre-existing dirty/untracked files unchanged; this is consistent with the observed scoped diff/status. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-setup-allocators-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: fresh forced-fresh probe before edits, then address only the new first blocker at `obmalloc.c(412-414)` involving the three debug allocator declarations with TDD; retain all later diagnostics and the known unrelated regression failures separately. + +--- + +## Previous latest revision (default allocator switch assignments made VC6-compatible) + +Date: 2026-10-05 UTC + +Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a10c6e-4002-7c23-93c1-b9f41270f3ed`, workspace-write) was used for the one implementation slice; no commit or push. + +The recorded `_blake2/blake2s_impl.c` frontier was freshly rechecked before editing. The source compiled, and the actual first blocker was the three cast-to-braced-initializer assignments in `pymem_set_default_allocator()` (`obmalloc.c` lines 244, 247, 250), rejected by VC6 with C2059 on `{`. Strict TDD updated the focused default-allocator test first and observed RED. The minimal production change wraps each RAW/MEM/OBJ case in a C89 block, initializes a local `PyMemAllocatorEx` from the same allocator macro, then copies it into `new_alloc`. Branch selection, allocator fields (including context and all callbacks), setter/debug-hook ordering, and return behavior are retained. No subsequent `obmalloc.c` errors were changed. + +Exact commands and results: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic group: C2059 `{` at `obmalloc.c(244)`, `(247)`, `(250)`. Full captured output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791209613-304480-c2b0.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before production edit, expected failure that switch assignments/order did not match the VC6-compatible local-copy semantics. +- GREEN and focused regression: same default-allocator command — exit 0; `obmalloc default allocator C89 assignments, allocator semantics, and execution order: PASS`. +- Tracemalloc regression: `python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; positional initializer defaults match header field order. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > /tmp/obmalloc-slice-frontier-test.log 2>&1` — exit 1. Two known unrelated checks remain failing: console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`). No suite-wide pass claimed. +- Post-change forced-fresh probe (same command as pre-change) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former C2059 diagnostics at lines 244/247/250 are gone. The first remaining group is at `obmalloc.c(349)`: C2275/C2146/C2065/C2059 for `PyMemAllocatorEx pymalloc` and its braced initializer in a separate allocator setup function; leave this declaration/initializer family for the next slice. Further diagnostics in obmalloc.c are distinct and untouched. Full output: `build/cron-current/post-allocator-probe.log`. +- `git -C cpython diff --check -- Objects/obmalloc.c`, `git diff --check -- scripts/vc6-obmalloc-default-allocator-c89.test.py`, and baseline `git -C cpython rev-parse HEAD` — exit 0; baseline hash unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-default-allocator-c89.test.py`, and this status entry. A pre-edit snapshot confirmed no other pre-existing dirty/untracked file content changed by the focused coding lane. This remains compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: perform a fresh forced-fresh probe, then use TDD on only the new first blocker, `PyMemAllocatorEx pymalloc` in `_PyMem_SetupAllocators()`; keep later obmalloc declarations, designated initializers, allocator-map/platform compatibility errors, and the two unrelated regression failures separate. + +--- + +## Latest revision (tracemalloc configuration initializer converted for VC6) + +Date: 2026-10-05 09:57 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the pre-existing outer and nested dirty work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_blake2/blake2s_impl.c` state was verified with a forced-fresh MSVC600/Wine source-list probe before editing. `_blake2/blake2s_impl.c` and `Objects/object.c` compiled. First blocker remained `Objects/obmalloc.c(89)`, C2059 on `.` in `_PyTraceMalloc_Config_INIT`'s C99 designated initializer. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a10b79-c7ce-7ce2-b7bd-003a9d5ef9ac`) performed a strict TDD slice. It added `scripts/vc6-obmalloc-tracemalloc-init-c89.test.py`, first ran it RED against the original source, then replaced only the initializer in `cpython/Objects/obmalloc.c` with positional values `TRACEMALLOC_NOT_INITIALIZED, 0, 1`. Verified header field order is `initialized, tracing, max_nframe`; values preserve defaults. No later allocator/C89 errors were changed. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostic: `cpython\\Objects\\obmalloc.c(89) : error C2059: syntax error : '.'`. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791193614-235796-7820.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 1; expected assertion `_Py_tracemalloc_config must use a VC6-compatible positional initializer`. +- TDD GREEN and independent focused rerun: same command — exit 0; `obmalloc tracemalloc C89 positional initializer: PASS (initialized=TRACEMALLOC_NOT_INITIALIZED, tracing=0, max_nframe=1)`. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Tracemalloc and `_thread` regression checks passed. Two known unrelated failures remain: console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`). No suite-wide pass claimed. +- Post-change forced-fresh probe (same command as before-change): exit 2; `total=101 compiled=100 cached=0 skipped=0`. The C2059 at `obmalloc.c(89)` is gone; `obmalloc.c` first reports C2275/C2146/C2065 at line 239 for late `PyMemAllocatorEx new_alloc`, followed by related initializer/cascade errors. Separate C89/API/type blockers remain untouched. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791193985-235796-2b10.log`. +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- scripts/vc6-obmalloc-tracemalloc-init-c89.test.py` — exit 0. CPython baseline tag/commit unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-tracemalloc-init-c89.test.py`, and `PORT_STATUS.md`. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: perform a fresh forced probe, then address only the first current `obmalloc.c` declaration family (`PyMemAllocatorEx new_alloc` near line 239) with TDD; keep subsequent initializer/declaration errors separate. + +--- + +## Previous latest revision (fresh VC6 frontier recheck; implementation lane unavailable) + +Date: 2026-10-05 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_blake2/blake2s_impl.c` compiler state was rechecked using the forced-fresh source-list probe. `_blake2/blake2s_impl.c` and `Objects/object.c` compile; the actual first blocker has advanced to `Objects/obmalloc.c(89)`, C2059 on `.` in the `_PyTraceMalloc_Config_INIT` designated initializer. A single focused implementation delegation was attempted for only that initializer family. Delegation could not start because the Hermes delegation runtime lacks the `anthropic` package and lazy installs are disabled. In keeping with the delegated-lane requirement, made no production or test edits; this run is diagnostics-only. Later `obmalloc.c` declaration/initializer errors were left untouched. + +Exact verification: + +- Forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First compiler diagnostic: `cpython\\Objects\\obmalloc.c(89) : error C2059: syntax error : '.'`. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791186043-210799-43e0.log`. The invocation ran VC6 `cl.exe` through Wine; it did not emit a standalone compiler version banner. +- Focused delegation for the single line-89 initializer family — failed before agent startup: `The 'anthropic' package is required ... venv: not installed and lazy installs are disabled: ['anthropic']`. No delegated edits were applied. +- Applicable regression suite: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The suite's relevant existing checks run; two known unrelated failures remain: console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`). No obmalloc-specific regression exists yet; no code was changed in this diagnostics-only run. +- Worktree/baseline check: outer pre-existing dirty entries and detached CPython modifications were retained; `cpython` remains exactly at `v3.11.16`, `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only: no `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier remains the single designated initializer at `obmalloc.c(89)`; retry one focused TDD coding lane when delegation is available, preserving every other local change. + +--- + +## Previous latest revision (_PyTypes_FiniTypes loop counter made C89-compatible; frontier advances) + +Date: 2026-10-05 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The previously recorded frontier was freshly confirmed before editing. The forced-fresh MSVC600/Wine probe compiled `_blake2/blake2s_impl.c` and reached `Objects/object.c`; first diagnostics were C2143/C2065 at line 2093 for the C99 `for (Py_ssize_t i=...)` in `_PyTypes_FiniTypes()`. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a10a8c-b70d-7480-a8ec-5918918fecbd`) extended `scripts/vc6-object-notimplemented-c89.test.py`, ran the new assertion RED (expected missing function-entry `Py_ssize_t i`), then hoisted only that loop counter to the function declaration group and reused it in the loop. Reverse bounds/traversal, main-interpreter guard, per-item type lookup and deallocation order are preserved. `_PyTypes_FiniTypes()`'s existing inner `PyTypeObject *type` is the first declaration in its loop block, so no change there was needed. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics C2143/C2065 at `object.c(2093)` on the C99 loop declaration; dependent errors at 2095/2097. Log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791178068-168873-7820.log`. +- TDD RED: `python3 scripts/vc6-object-notimplemented-c89.test.py cpython/Objects/object.c cpython/Include/cpython/object.h` — exit 1; the new assertion failed as expected because `_PyTypes_FiniTypes` lacked entry `Py_ssize_t i`. +- GREEN plus directly applicable object regressions: the focused NotImplemented/object checks, object C89, FunctionStr, InitState, RichCompare, descrobject/classmethod/dispatch, and genericaliasobject scripts passed (exit 0). Independent rerun of NotImplemented, object C89, InitState, FunctionStr, RichCompare and descrobject checks — exit 0. RED/GREEN and focused-suite transcript: `/tmp/vc6-finitypes-tdd.log`, `/tmp/vc6-finitypes-checks.log`. +- Applicable suite: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The new object regression and most checks pass; two known unrelated failures persist: console type lookup/cleanup ordering and numeric dispatch (`ValueError: substring not found`). Captured rerun: `build/cron-current/regression-suite.log`. +- Post-change forced-fresh probe (same command) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `object.c` now compiles past `_PyTypes_FiniTypes`; first blocker advances to `Objects/obmalloc.c(89)`, C2059 on `.` in a designated initializer. Following diagnostics include distinct C89 declarations and related cascades; untouched. Log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791178483-168873-7360.log`. +- Scoped outer/nested `git diff --check` — exit 0. CPython tag and commit remain unchanged. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-notimplemented-c89.test.py`, and this log. This is compiler-probe progress only; no `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution is claimed. Next frontier: fresh forced probe before edits, then a single TDD slice addressing only the first stable `obmalloc.c(89)` designated-initializer error. Existing suite failures and all earlier local work remain preserved. + +--- + +## Previous latest revision (_PyTypes_InitTypes loop counter made C89-compatible; frontier advances) + +Date: 2026-10-05 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython work. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Existing dirty state was retained. + +Re-ran a forced-fresh MSVC600/Wine source-list probe before editing because the previous recorded frontier might be stale. `_blake2/blake2s_impl.c` compiled; the actual first blocker was no longer the recorded `PyStatus` declaration. `Objects/object.c` produced C2143/C2065 on the C99 loop declaration in `_PyTypes_InitTypes()` at line 2060, followed by a separate C99 loop declaration in `_PyTypes_FiniTypes()` at line 2091. Used one focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a10a11-ceb3-73f1-b38b-42541af4a989`) for a strict TDD slice. It first extended `scripts/vc6-object-notimplemented-c89.test.py` and verified RED against the original source. Then it hoisted only `size_t i;` to `_PyTypes_InitTypes()`'s entry declaration group and changed that loop to use `i`; loop bounds, body, and earlier legacy type initialization order are preserved. `_PyTypes_FiniTypes()` was not edited. + +The existing `scripts/vc6-descrobject-classmethod-c89.test.py` also asserted the old `_PyTypes_InitTypes()` loop spelling. Updated only that assertion to require the entry declaration and C89 loop spelling/order, so the directly applicable regression remains valid after this slice. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR=/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x/build/cron-current/runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable errors C2143/C2065 at `object.c(2060)` for `for (size_t i=...)`; a separate loop declaration produced C2143/C2065 at line 2091. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791170011-133815-15b0.log`. +- TDD RED: `python3 scripts/vc6-object-notimplemented-c89.test.py cpython/Objects/object.c cpython/Include/cpython/object.h` — exit 1 with the expected assertion `_PyTypes_InitTypes must declare size_t i before the interpreter guard`. +- GREEN: same command after source edit — exit 0; NotImplemented's 36 positional slots and the new init-loop declaration/order checks passed. +- Focused object regressions: NotImplemented, object C89, object FunctionStr, object initstate, object richcompare, classobject type initialization, descrobject classmethod/dispatch, and genericaliasobject scripts — all exit 0. In particular, the formerly stale descrobject test passes against the updated source. +- Applicable suite: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The descrobject type-initialization check now passes. Two known unrelated failures remain: console type lookup/cleanup-order check and numeric-dispatch check (`ValueError: substring not found`); other reported checks passed. +- Post-change forced-fresh probe (same command as before-change probe) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. The former line-2060 diagnostics are gone; `object.c` now reaches the distinct `_PyTypes_FiniTypes()` loop at line 2091, reported C2143/C2065 on `Py_ssize_t i`, with dependent diagnostics for `type`. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791170515-133815-d60.log`. +- `git -C cpython diff --check -- Objects/object.c` and outer `git diff --check -- scripts/vc6-object-notimplemented-c89.test.py scripts/vc6-descrobject-classmethod-c89.test.py` — exit 0. CPython baseline tag/commit unchanged. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-notimplemented-c89.test.py`, `scripts/vc6-descrobject-classmethod-c89.test.py`, and this status log. This is compiler-probe progress only. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is claimed. Next frontier: fresh forced probe before edits; then address only `_PyTypes_FiniTypes()`'s C99 loop declaration, preserving reverse deallocation order and the rest of the function. + +--- + +## Previous revision (NotImplemented number slot positional initializer; VC6 frontier advances) + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, or compatibility-patch regeneration. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Initial dirty state included `PORT_STATUS.md`, existing object regression scripts, extensive nested CPython edits, and existing untracked files; these were retained. The external coding-agent delegation API was unavailable (`anthropic` package missing; lazy installs disabled), so one focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a1091f-9e57-7953-8495-1504b1a42b03`) performed the narrow implementation slice. No commit or push. + +Fresh forced-fresh MSVC600/Wine source-list probe reconfirmed `_blake2/blake2s_impl.c` compiles, but the recorded `_PyObject_GetMethod` frontier was stale. The actual first blocker was C2059 syntax error `'.'` at `cpython/Objects/object.c(1815)`, the C99 designated initializer `.nb_bool = notimplemented_bool` in `notimplemented_as_number`. Verified `PyNumberMethods` field order from `cpython/Include/cpython/object.h`: 36 slots, `nb_bool` is slot 10. Added new focused regression `scripts/vc6-object-notimplemented-c89.test.py`, first ran it RED against the designated initializer, then replaced only that initializer with 36 explicit positional entries; `nb_bool` keeps `notimplemented_bool`, all other slots are zero. This test checks field order and every value against the CPython header. + +Exact verification: + +- Initial forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2, `total=100 compiled=99 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostic: C2059 at `object.c(1815)` on `.`. Log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791154112-60826-2b0.log`. +- TDD RED: `python3 scripts/vc6-object-notimplemented-c89.test.py cpython/Objects/object.c cpython/Include/cpython/object.h` — exit 1, expected assertion `notimplemented_as_number must use a VC6-compatible positional initializer`. +- TDD GREEN and focused object regressions: `python3 scripts/vc6-object-notimplemented-c89.test.py cpython/Objects/object.c cpython/Include/cpython/object.h && python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 0; all object checks passed, including validation of the 36 header-ordered slots. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1; the known unrelated console type-detection/cleanup-order assertion and numeric-dispatch check (`ValueError: substring not found`) remain failing. Numerous other checks passed; no suite-wide pass claimed. +- Post-change forced-fresh VC6 probe (same command as initial probe) — exit 2, `total=100 compiled=99 cached=0 skipped=0`. The former C2059 at line 1815 is gone and no designated-initializer diagnostic remains. The first remaining errors are C2275/C2146/C2065 at `object.c(1906)` for late `PyStatus status`; subsequent loop-declaration errors at lines 2058 and 2089 are separate and untouched. Log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791154525-60826-b00.log`. +- Codex lane preservation snapshot confirmed only the designated initializer changed within `object.c` and all 124 other pre-existing dirty/untracked files were unchanged during its edit. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is claimed. + +Files changed in this slice: `cpython/Objects/object.c`, new `scripts/vc6-object-notimplemented-c89.test.py`, and this status entry. This is compiler-probe progress only. Next frontier: perform a fresh forced-fresh probe before touching the late `PyStatus status` declaration around line 1906; use TDD for that single declaration family and preserve subsequent loop diagnostics separately. + +--- + +## Previous revision (_PyObject_GetMethod ordinary-dict attr declaration reused; VC6 retry blocked by Wine runtime) + +Date: 2026-10-04 20:46 UTC + +Read `PORT_STATUS.md`, `README.md`, and the invoked CPython Win9x/MSVC6 reference guidance before acting. The named reference file was not found in the repository. Preserved all existing outer and detached CPython edits; no reset, clean, stash, discard, commit, push, or compatibility-patch regeneration. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Initial dirty state included `PORT_STATUS.md`, object regression scripts, and extensive nested CPython source changes; these were retained. + +The recorded `_PyObject_GetMethod` ordinary-dict `PyObject *attr` frontier was confirmed by a successful forced-fresh VC6/Wine source-list probe immediately before implementation: 99/100 TUs compiled, including `_blake2/blake2s_impl.c`, and the first compiler diagnostic was C2275 at `Objects/object.c(1231)`. A focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write; session `01a108aa-4298-7190-ae47-64878df51251`) followed test-first procedure. Extended the existing untracked `scripts/vc6-object-richcompare-c89.test.py`; it failed RED against the current source because the ordinary-dict branch redeclared `PyObject *attr`. Then changed only that declaration to assignment reusing the function-entry `attr` local already used in the mutually exclusive managed-dict branch. The lookup remains after `Py_INCREF(dict)`; dictionary lookup, result assignment, decref/error cleanup, and branch order are unchanged. No other production source changed in this slice. + +Exact verification: + +- Before-edit forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2, `total=100 compiled=99 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled; first stable error C2275 at `object.c(1231)`. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791146440-32913-5a70.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1, expected assertion detecting duplicate ordinary-dict attr declaration. GREEN after source edit — exit 0; all object-richcompare script assertions passed. +- Focused regressions `python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c`, `python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c`, `python3 scripts/vc6-classobject-typeinit.test.py cpython/Objects/classobject.c cpython/Objects/object.c`, `python3 scripts/vc6-descrobject-classmethod-c89.test.py cpython/Objects/descrobject.c cpython/Objects/object.c`, and `python3 scripts/vc6-genericaliasobject-c89.test.py cpython/Objects/genericaliasobject.c cpython/Objects/object.c` — all exit 0. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > /tmp/vc6-ordinary-attr-suite.log 2>&1` — exit 1; 260 checks passed, two known unrelated failures remain (console type-detection order and numeric-dispatch helper `ValueError: substring not found`). +- Requested post-change forced-fresh probe (same exact command as the initial probe) — exit 1 before compiler startup: `sock_init: ERROR in sock_check_pollhup()` and `wineserver: error creating /run/user/1000/wine/server-801-136fb0/lock: Read-only file system`. The harness consequently reported `first compile blocker: cpython/Modules/getpath.c`, `total=1 compiled=0 cached=0 skipped=0`; this is a Wine startup failure, not a C diagnostic. No post-change compiler frontier is verified. Full attempt output is in the terminal capture `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791146737-32913-fc0.log`. +- No post-change VC6 probe success, linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is claimed. Next: resolve writable Wine server runtime placement and repeat a forced-fresh probe before advancing to any later `object.c` errors (1815, 1871+, 2023+). + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry. The compatibility patch was not regenerated. No commit or push. + +--- + +## Previous latest revision (_PyObject_GetMethod managed-dict attr declaration hoisted; frontier advances) + +Date: 2026-10-04 18:27 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing dirty outer and detached CPython changes; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +Re-probed the recorded frontier before editing. The status was current: forced-fresh VC6/Wine source-list compile reached `Objects/object.c`; `_blake2/blake2s_impl.c` compiled. The first errors were C2143/C2065 on the late managed-dict `PyObject *attr` at `object.c(1218-1219)`. Used one focused Codex CLI coding lane (`codex-cli 0.153.4`, workspace-write; session `01a10830-7a50-7612-b781-30c767c972df`) for a strict TDD slice. Extended only the already-untracked `scripts/vc6-object-richcompare-c89.test.py`; the focused test failed RED before touching production source. Then hoisted only the managed-dict `attr` declaration into `_PyObject_GetMethod()`'s opening local declarations, changing its late initialized declaration to an assignment at the same lookup point. The separate ordinary-dict branch's `attr` was not touched. Lookup, branch, result assignment, error handling, and cleanup order remain asserted unchanged. + +Exact verification: + +- Initial forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First blocker: C2143 at `object.c(1218)` before `type`, then C2065 `attr` at line 1219; following diagnostics were separate. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791138459-4193614-50.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1, expected assertion `_PyObject_GetMethod must declare attr exactly once without initializer at function entry`; all prior object assertions passed. +- TDD GREEN and independent focused regression rerun: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 0; all object richcompare/attribute/managed-dict checks, object C89 checks, and FunctionStr checks passed. +- Forced-fresh post-change probe: `XDG_RUNTIME_DIR="$PWD/build/cron-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. The former attr diagnostics at lines 1218-1219 are gone; `object.c` remains first failing translation unit, with its first remaining diagnostic C2275 at line 1231 for a separate late `PyObject` declaration in the ordinary-dict branch. Later C2059 at 1815, PyStatus/C89 failures at 1871+, and loop declaration failures at 2023+ remain distinct and untouched. Full output: `build/cron-recheck/post-attr-probe.log`. +- `git diff --check -- scripts/vc6-object-richcompare-c89.test.py` and `git -C cpython diff --check -- Objects/object.c` — exit 0. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry. Compile-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: freshly probe before any new edits; then TDD one declaration family only, beginning with the ordinary-dict late `PyObject *attr` at `object.c(1231)`. Keep the later independent blockers separate. + +--- + +## Previous latest revision (fresh VC6 frontier recheck; implementation delegated lane unavailable) + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the dirty outer worktree and detached CPython source; no reset, clean, stash, discard, commit, push, or publication. The CPython checkout remains exactly at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +Re-probed before editing because the recorded frontier might be stale. The recorded `_PyObject_GetMethod` state remains accurate: `_blake2/blake2s_impl.c` compiles, and the first stable blocker is the late `PyObject *attr` declaration at `Objects/object.c(1218)`. The preceding `PyDictValues *values` diagnostic is cleared. A focused coding subagent was requested for this single implementation slice, but delegation failed because the Anthropic Python package is unavailable and lazy installs are disabled. Per the safe-stop constraint for this run, made no production or test edits; this is diagnostics-only. + +Exact verification: + +- `git status --short --branch` (outer) — exit 0; pre-existing dirty state includes `PORT_STATUS.md`, `scripts/vc6-object-c89.test.py`, and untracked object regression scripts. No unrelated status entries were overwritten. +- `git status --short --branch && git describe --tags --exact-match HEAD && git rev-parse HEAD` (nested CPython) — exit 0; detached checkout at `v3.11.16`, `41388c9cb160d0886d5ca00d2e6c878260a8a4549`; numerous pre-existing nested modifications retained. +- Forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2, `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics: C2143 at `object.c(1218)` before type and C2065 `attr` at line 1219. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791130887-4170883-4b00.log`. +- Delegation attempt for exactly one `_PyObject_GetMethod` `attr` declaration slice — unavailable: `anthropic` package missing; lazy installs disabled. No child implementation was applied. + +No tests were changed or run, and no source change was made. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier remains the single late `PyObject *attr` declaration at `object.c(1218)`; retry a focused coding lane when available, then perform RED/GREEN, applicable regressions, and a fresh forced probe. Keep later diagnostics (including the separate declaration near line 1230) separate. + +--- + +## Latest revision (_PyObject_GetMethod values declaration hoisted; object.c frontier advances) + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. Baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Attempted the required focused coding-agent delegation, but it was unavailable because the Anthropic package is missing and lazy installs are disabled; Codex CLI 0.153.4 is installed, but no external CLI lane was started. Proceeded with one narrowly scoped direct TDD slice. + +A forced-fresh VC6/Wine re-probe confirmed the recorded object.c frontier. `_blake2/blake2s_impl.c` compiled; first blocker was the late `PyDictValues *values` declaration in `_PyObject_GetMethod()` at `object.c(1213)`. Extended the existing untracked `scripts/vc6-object-richcompare-c89.test.py` with a declaration/order assertion and observed RED (exit 1: missing function-entry `values`). Hoisted only `PyDictValues *values` beside the existing entry locals. The assignment remains in the original managed-dict condition; descriptor lookup, condition evaluation, and branch order are unchanged. No other production source was changed. + +Exact verification: + +- Initial forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2, `total=100 compiled=99 cached=0 skipped=0`. First diagnostics C2275/C2065 at `object.c(1213)` for late `PyDictValues *values`. Log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791122912-4136178-3100.log`. +- Focused TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1, expected assertion that `_PyObject_GetMethod` declares `values` at function entry. +- GREEN and focused object regressions: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 0; all checks passed, including declaration and managed-dict lookup order. +- Applicable harness: `MSVC600_ROOT=/dev/null bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1; live integration intentionally skipped. New object assertion passes. Known unrelated console lookup/cleanup assertion and numeric dispatch (`ValueError: substring not found`) still fail. +- Forced-fresh post-change VC6/Wine probe (same command as initial) — exit 2, `total=100 compiled=99 cached=0 skipped=0`. Former values diagnostics at line 1213 are gone; first errors now C2143/C2065 at lines 1218-1219 for the separate late `PyObject *attr`, followed by independent later diagnostics. Log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791123296-4136178-b950.log`. +- `git -C cpython diff --check -- Objects/object.c` and `git diff --check -- scripts/vc6-object-richcompare-c89.test.py` — exit 0. Baseline tag/commit unchanged. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry; all unrelated local changes preserved. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh probe, then test-first address only the first late `PyObject *attr` declaration at `object.c(1218)`; leave subsequent declaration families separate. + +--- + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. CPython remains detached at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. The referenced legacy-toolchain file was found at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. + +Re-probed the status-recorded frontier before editing. The stale `_blake2/blake2s_impl.c` entry point still compiles; the actual first blocker remained `cpython/Objects/object.c` in `_PyObject_GetMethod()`. A focused coding subagent could not be started because the Anthropic package is unavailable and lazy installs are disabled; `codex` CLI was present, but no external coding CLI was invoked. Proceeded with one focused test-first edit directly, preserving all unrelated dirty work. + +Added assertions to the already-untracked `scripts/vc6-object-richcompare-c89.test.py`, first observing expected RED for the absent function-entry `descr` and `f` declarations. In `cpython/Objects/object.c`, hoisted only `PyObject *descr` and `descrgetfunc f` into the function-entry declaration group; retained `_PyType_Lookup(tp, name)` and `f = NULL` assignments at their original execution points. No subsequent declarations or other source areas were changed. + +Exact verification: + +- Forced-fresh pre-change VC6/Wine command: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics: C2275/C2065 at `object.c(1196)` for late `PyObject *descr`; C2275/C2146/C2065 at `(1197)` for late `descrgetfunc f`. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791114989-4103247-f820.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1 with the intended missing function-entry `descr`/`f` assertion. A preliminary test-regex iteration failed to locate the function (also exit 1); corrected the test itself before the expected RED. No production source was changed before the expected RED. +- GREEN/focused regressions: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 0; all object C89/order assertions passed. +- Applicable full harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. New object assertions passed. Known unrelated console type lookup/cleanup-order assertion still fails, as does numeric dispatch (`ValueError: substring not found`). No unrelated fixes attempted. +- Forced-fresh post-change probe (same command) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. Former diagnostics at object.c(1196-1197) are gone. Next first errors are C2275/C2065 at `object.c(1213)` for late `PyDictValues *values`; later C2143/C2065 at lines 1218-1219 concern another late declaration. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791115333-4103247-3ce0.log`. +- Scoped nested `git diff --check -- Objects/object.c` and outer `git diff --check -- scripts/vc6-object-richcompare-c89.test.py` — exit 0. CPython baseline tag and commit verified unchanged. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and `PORT_STATUS.md`. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh re-probe, then test-first inspect only the late `PyDictValues *values` declaration at `object.c(1213)`; leave the later `attr` and other diagnostics for separate slices. + +--- + +## Latest revision (_PyObject_GetMethod C89 local hoisted; object.c frontier advances) + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and the invoked legacy-toolchain guidance before acting. The referenced on-disk `python-3-win9x-msvc6.md` was absent from both the active profile reference directory and repository search. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. Baseline remains tag `v3.11.16`, detached commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded object.c frontier remained current on a forced-fresh VC6/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; first stable diagnostic was C2143 at `Objects/object.c(1183)` on the late `PyTypeObject *tp = Py_TYPE(obj)` in `_PyObject_GetMethod`. Coding-agent subagent dispatch was attempted but unavailable because the runtime lacks the `anthropic` package and lazy installs are disabled. Proceeded with a single narrowly scoped test-first edit directly; no external coding CLI was run. + +Added an assertion to the existing untracked `scripts/vc6-object-richcompare-c89.test.py`, first ran it against the original source and observed expected RED (exit 1: `_PyObject_GetMethod must declare tp exactly once without initializer at entry`; all four existing object checks passed). Then moved only `PyTypeObject *tp` to the function-entry declaration group and changed its initializer to `tp = Py_TYPE(obj);` at the same original execution point. Assertion, type readiness check, subsequent dispatch, and cleanup order are unchanged. + +Exact verification: + +- Forced-fresh pre-change: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. First stable diagnostic C2143 at `object.c(1183)` before `type`, followed by dependent C2065 `tp` and later separate C89 diagnostics. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791107101-4071333-8770.log`. +- Focused regression RED before production edit: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1, expected missing function-entry `tp` declaration. +- Focused regression GREEN after edit: same command — exit 0; richcompare, exception-context, `PyObject_GetAttr`, `_PyObject_GetDictPtr`, and `_PyObject_GetMethod` ordering assertions all passed. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The object checks, including the new assertion, pass. Existing unrelated console type lookup/cleanup order assertion and numeric dispatch (`ValueError: substring not found`) remain failing; no unrelated changes attempted. +- Forced-fresh post-change probe (same command as above) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. The former line-1183 diagnostic is gone. First remaining diagnostics are C2275/C2065 at `object.c(1196)` for late `PyObject *descr`, followed by C2275/C2146/C2065 at line 1197 for `descrgetfunc f`; later diagnostics remain separate. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791107440-4071333-a520.log`. +- CPython baseline tag/commit checked before editing; no compatibility patch regeneration. No commit or push. + +Files changed this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: re-probe before editing, then test-first handle only the first late-local family at `object.c(1196)`; separate the `descrgetfunc f` declaration and subsequent issues. + +--- + +## Latest revision (_PyObject_GetDictPtr C89 locals hoisted; object.c frontier advances) + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and the legacy-toolchain reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. CPython remains detached at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyObject_GetDictPtr` frontier remained current on a forced-fresh VC6/Wine probe. One focused Codex CLI lane (0.153.4, workspace-write) extended the existing untracked `scripts/vc6-object-richcompare-c89.test.py`; the new check failed RED as expected before production changes. Hoisted only `PyObject **dict_ptr`, `PyDictValues **values_ptr`, and `PyObject *dict` to the function-entry declarations in `cpython/Objects/object.c`; assignments remain at their original points. The managed-dict branch, pointer initialization and NULL path, conversion/error-clear behavior, and values/dict store order are unchanged. No neighboring functions were modified in this slice. + +Exact verification: + +- Forced-fresh pre-change probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics were C2275/C2065 at `object.c(1124-1125)` for late `dict_ptr` and `values_ptr`, followed by dependent errors. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791099148-4038166-9d0.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1, expected missing function-entry declarations; preceding richcompare/exception/attribute checks passed. +- GREEN: same focused command — exit 0; all checks passed, including the new exact `_PyObject_GetDictPtr` statement-order assertion. `scripts/vc6-object-c89.test.py` and `scripts/vc6-object-functionstr-c89.test.py` also passed before the slice; the agent ran the focused richcompare script after the change. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The new object assertion and core object checks pass. Existing unrelated failures remain: console type lookup/cleanup order and numeric dispatch (`ValueError: substring not found`). No unrelated fixes attempted. +- Forced-fresh post-change probe (same command) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. Prior diagnostics at object.c(1124-1125) are gone; `_PyObject_GetDictPtr` now compiles through. The next first blocker is C2143 at `object.c(1183)` before `type` in a separate function, followed by dependent errors there. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791099505-4038166-22c0.log`. +- `git diff --check -- scripts/vc6-object-richcompare-c89.test.py` and `git -C cpython diff --check -- Objects/object.c` — exit 0. Baseline tag/commit verified unchanged. No compatibility patch regeneration. + +Files changed by this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry; prior local changes remain. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: re-probe before further edits, then test-first inspect only the C2143 declaration at `object.c(1183)`; keep subsequent diagnostics separate. + +--- + +## Previous revision (_PyObject_DictPointer size declaration hoisted; object.c frontier advances) + +Date: 2026-10-04 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all prior work; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. CPython remains detached at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +Re-probed the recorded object.c frontier with forced-fresh VC6/Wine source-list compile. `_blake2/blake2s_impl.c` compiled. First error family remained late `size_t size` in `_PyObject_DictPointer()` at line 1100. One focused Codex CLI lane (0.153.4, workspace-write) extended `scripts/vc6-object-c89.test.py`, observed expected RED, then hoisted only `size_t size;` to the start of the existing negative-offset block and changed the original declaration/initializer to `size = _PyObject_VAR_SIZE(tp, tsize);`. Expression, assertion, offset adjustment, and return order are preserved. No adjacent source errors were changed. + +Exact verification: + +- Forced-fresh pre-change probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. First diagnostics C2275/C2146/C2065 at `object.c(1100)` for late `size_t size`. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791091193-4004215-b950.log`. +- TDD RED: `python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c` — exit 1, expected `_PyObject_DictPointer` declaration/order assertion; the preceding three object checks passed. +- GREEN: same command — exit 0; all four object checks passed. `python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` and `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 0. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > /tmp/vc6-dictpointer-frontier-test.log 2>&1` — exit 1. The new assertion and object checks pass. Existing unrelated failures remain: console type lookup/cleanup order and numeric dispatch (`ValueError: substring not found`). Full log: `/tmp/vc6-dictpointer-frontier-test.log`. +- Forced-fresh post-change probe (same command) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. Former diagnostics at line 1100 are gone. First blocker advances to C2275/C2065 at line 1124 (`PyObject *dict_ptr`) in `_PyObject_GetDictPtr`; following diagnostics are separate. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791091612-4004215-640.log`. +- `git diff --check` and `git -C cpython diff --check` — exit 0. The source diff is limited to the one intended declaration/assignment conversion; CPython baseline unchanged. + +Files changed by this slice: `cpython/Objects/object.c`, `scripts/vc6-object-c89.test.py`, and this status entry. Compile-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or actual Windows 98 execution. Next frontier: test-first address only the late declarations at `object.c(1124)` in `_PyObject_GetDictPtr`; treat later diagnostics separately. + +--- + +## Previous latest revision (PyObject_GetAttr result declaration hoisted; object.c frontier advances) + +Date: 2026-10-04 03:18 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython/Win9x/MSVC6 reference before acting. Preserved all existing outer and nested changes; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. Verified CPython remains detached at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded object.c frontier was freshly confirmed with a forced VC6/Wine source-list probe. `_blake2/blake2s_impl.c` compiled, and `PyObject_GetAttr()` at `Objects/object.c(935)` was the first blocker. One focused coding CLI lane (Codex CLI 0.153.4, workspace-write) performed a TDD slice: extended the pre-existing untracked `scripts/vc6-object-richcompare-c89.test.py`, observed RED, then hoisted only `PyObject *result` to the function declarations and changed its former late initialized declaration to `result = NULL;` after name validation. Dispatch, validation, error-context, and return order are unchanged. No other production source was modified in this slice. + +Exact verification: + +- Forced-fresh pre-change probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. First errors: C2275/C2065 at `object.c(935)` for late `PyObject *result`; subsequent stable blocker was `size_t size` at line 1099. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791083254-3970565-ed70.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1; prior richcompare and `set_attribute_error_context` checks passed, new assertion failed because `result` was not declared at function entry. +- GREEN plus focused object regressions: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 0; all richcompare, error-context, `PyObject_GetAttr`, object C89, and FunctionStr assertions passed. +- Applicable harness: `MSVC600_ROOT=/dev/null bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Live compiler integration intentionally skipped. The new object checks passed; two known unrelated checks still fail: console type lookup/cleanup order, and numeric dispatch (`ValueError: substring not found`). No harness-wide pass claimed. +- Forced-fresh post-change probe (same command as pre-change) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. Former errors at `object.c(935)` are gone. First stable diagnostic is now C2275/C2146/C2065 at `object.c(1100)` for late `size_t size`; later object.c diagnostics are separate. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791083629-3970565-5220.log`. +- `git diff --check` and `git -C cpython diff --check` — exit 0. Baseline tag and commit verified unchanged. + +Files changed by this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry. Compiler-probe progress only; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: test-first inspect and address only the late `size_t size` declaration in the function at `object.c(1100)`, preserving original evaluation/order; re-probe before treating the frontier as current. + +--- + +## Previous latest revision (set_attribute_error_context C89 locals hoisted; object.c frontier advances) + +Date: 2026-10-04 01:06 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and nested changes; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. CPython remains detached at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +Forced-fresh MSVC600/Wine probe reconfirmed the recorded frontier: `_blake2/blake2s_impl.c` compiled, and the first blocker was `Objects/object.c(900)` in `set_attribute_error_context()`. Used one focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write) for this narrow TDD slice. Extended the pre-existing untracked `scripts/vc6-object-richcompare-c89.test.py` without removing its rich-compare check. Hoisted only `type`, `value`, `traceback`, and `PyAttributeErrorObject *the_exc` to the function entry; changed the late `the_exc` initialized declaration to assignment at its original point. Exception check/fetch/normalize/restore, augmentation, and early returns remain in original order. No other new production source change was made in this slice. + +Exact verification: + +- Initial forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. First stable diagnostics: C2275 and C2065 at `object.c(900)` for the late `PyObject *type, *value, *traceback`; C2275/C2065 at line 907 for late `PyAttributeErrorObject *the_exc`. `_blake2/blake2s_impl.c` compiled. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791075267-3936276-180.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1 before production edit; existing `PyObject_RichCompare` assertion passed, new assertion failed because the four locals were not at function entry. +- GREEN/focused regressions: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c && python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c` — exit 0; richcompare and `set_attribute_error_context` checks passed, as did three existing object C89 checks. +- Applicable harness: `MSVC600_ROOT=/dev/null bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. Live integration explicitly skipped; two known unrelated checks still fail: console type lookup/cleanup order, and numeric dispatch (`ValueError: substring not found`). All other emitted checks passed; no harness-wide pass claimed. +- Post-change forced-fresh probe (same command as initial probe) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. Prior errors at `set_attribute_error_context()` are gone. First stable diagnostic is now `object.c(935)` C2275/C2065 for late `PyObject *result` in `PyObject_GetAttr`; subsequent object.c diagnostics remain separate. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791075688-3936276-a060.log`. +- `git -C cpython diff --check -- Objects/object.c` and `git diff --check -- scripts/vc6-object-richcompare-c89.test.py` — exit 0. Baseline tag and commit verified unchanged. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-richcompare-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: test-first address only `PyObject_GetAttr()`'s late `result` declaration at line 935, preserving dispatch and error order; keep later object.c errors separate. + +--- + +## Latest revision (PyObject_RichCompare C89 local hoisted; object.c frontier advances) + +Date: 2026-10-03 22:52 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. CPython remains at detached tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Preserved all existing outer/nested changes; no reset, clean, stash, discard, commit, push, compatibility patch regeneration, or publication. + +The prior `PyObject_RichCompare` line-747 frontier was freshly reconfirmed by a forced-fresh source-list compile. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write) added a narrow regression and applied one C89 change: declared `PyObject *res` with the function-entry locals and changed the original late initialized declaration to `res = do_richcompare(...)`. Validation, recursive-call entry, leave, and return order are preserved. Independent review confirmed this function-only source diff; no other production source was changed in this slice. + +Exact verification: + +- Forced-fresh VC6 probe before implementation: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled; `object.c(747)` first errors C2275 (`PyObject` illegal use as expression) and C2065 (`res` undeclared). Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791067258-3892466-4770.log`. +- TDD RED: `python3 scripts/vc6-object-richcompare-c89.test.py cpython/Objects/object.c` — exit 1, expected assertion that `res` must be declared once without initializer at entry. +- GREEN and independent focused rerun: same command — exit 0, `object PyObject_RichCompare C89 res declaration and recursive-call/result order: PASS`. +- Applicable suite: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The test set ran; this slice's source check passed. Two known unrelated failures persist: console type lookup/cleanup ordering and numeric dispatch (`ValueError: substring not found`). +- Forced-fresh post-change probe (same command) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. Former line-747 errors are gone. First stable errors now occur at `object.c(900)` C2275/C2065 for late exception-object declarations in a different function; later `object.c` C89/initializer diagnostics remain distinct. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791067716-3892466-4fc0.log`. +- Scoped `git -C cpython diff --check -- Objects/object.c` and `git diff --check -- scripts/vc6-object-richcompare-c89.test.py` — exit 0. CPython remains at the exact baseline tag/commit above. + +Files changed by this slice: `cpython/Objects/object.c`, new `scripts/vc6-object-richcompare-c89.test.py`, and this log. Compile-frontier progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: test-first inspect and address only the late declarations at `object.c(900)`; keep subsequent diagnostics separate. + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. CPython remains at detached tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Preserved all existing outer and nested changes; no reset, clean, stash, discard, commit, push, patch regeneration, or publication. + +The `_blake2/blake2s_impl.c` recorded frontier remained stale as expected: forced-fresh VC6 probe compiled it and reached `Objects/object.c`. Addressed exactly the first error family in `_PyObject_FunctionStr`: removed the duplicate late `PyObject *module;` and changed the duplicate late `PyObject *result = NULL;` into `result = NULL;`. This keeps the original initialization point/order and uses the function-entry declarations. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write) followed TDD; native delegation was unavailable because the Anthropic package is absent. Independently reviewed its narrow diff. + +Exact results: + +- Forced-fresh pre-change probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`; first stable errors C2275 at `object.c(620-621)` for the duplicate `module` and `result` declarations. `_blake2/blake2s_impl.c` compiled. +- TDD RED: `python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 1, expected 2 `module` declarations found. +- GREEN: same test — exit 0, unique declarations and evaluation/statement order pass. Existing `python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c` — exit 0 (three existing checks pass). +- Applicable suite: `MSVC600_ROOT=/tmp/python-win9x-no-toolchain bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1; the active object checks passed; two known unrelated failures remain: console type lookup/cleanup ordering and numeric dispatch (`ValueError: substring not found`). Live compiler integration intentionally skipped in this suite invocation. +- Focused VC6 compile of `Objects/object.c` using the generated response-file include/define configuration — exit 2. Former diagnostics at lines 620-621 are gone. First remaining errors are C2275/C2065 at line 747 in a separate function, followed by distinct later C89 errors. This confirms progress at the compiler frontier; it does not clear the translation unit. + +Files changed this run: `cpython/Objects/object.c`, new `scripts/vc6-object-functionstr-c89.test.py`, and `PORT_STATUS.md`. No compatibility patch regeneration. Compile-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: test-first address only the line-747 C89 declaration in `object.c`, after confirming exact function context; retain later diagnostics as separate blockers. + +Read `PORT_STATUS.md`, `README.md`, and the CPython/Win9x/MSVC6 reference before acting. CPython remains at tag `v3.11.16`, detached baseline commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Preserved all pre-existing outer and nested work; no reset, clean, stash, discard, commit, push, patch regeneration, or publication. + +The previously mentioned `_blake2/blake2s_impl.c` frontier was stale. Forced-fresh MSVC600 source-list probe reached 99/100 translation units and compiled `_blake2/blake2s_impl.c`; the actual first blocker is `cpython/Objects/object.c`. First stable errors are C2275 for duplicate late `PyObject *module` and `PyObject *result = NULL` at lines 620–621 in `_PyObject_FunctionStr`; both names are already declared at function entry (lines 608–610). Later diagnostics in `object.c` are distinct and were not addressed. + +Focused implementation was not retained because Wine failed before invoking `cl.exe`. A test-first candidate reproduced the duplicate declaration (`RED`, expected assertion), and the minimal source edit passed that focused test and the existing object regression, but the actual compiler confirmation could not be obtained. Wine startup failed with `sock_init: ERROR in sock_check_pollhup()` and `wineserver: mkdir /run/user/1000/wine/server-21-59c6: Read-only file system`; retry with a temporary prefix/runtime directory failed identically. The temporary production edit was reverted byte-for-byte. The candidate test was removed rather than leaving an intentionally failing test artifact. + +Exact verification: + +- Forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`; first blocker `Objects/object.c`, C2275 at lines 620–621. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791051825-3857953-f590.log`. +- TDD candidate regression RED: `python3 scripts/vc6-object-functionstr-c89.test.py cpython/Objects/object.c` — exit 1, expected `module must be declared exactly once`. +- Candidate GREEN (while the temporary fix was present): same command — exit 0. Existing `python3 scripts/vc6-object-c89.test.py cpython/Objects/object.c` — exit 0. +- Focused VC6 compile using `build/vc6-probe-pythoncore-frontier/Objects_object.rsp` — exit 1 before compiler startup due to read-only `/run/user/1000/wine`; no compiler diagnostic beyond the full source-list probe was obtained. +- After reverting the candidate: `object.c` matches its entry snapshot; all 122 snapshotted pre-existing files, including `PORT_STATUS.md`, were verified unchanged before this log update. Nested scoped `git diff --check -- Objects/object.c` passed. + +Files changed for this run: `PORT_STATUS.md` only. No production compatibility change is retained. This remains compile-frontier evidence only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or actual Windows 98 SE execution. Next step: restore a Wine server runtime directory that is writable to the wineserver process, then repeat the forced-fresh frontier and address only the first current `object.c` diagnostic with RED/GREEN plus a successful focused VC6 compile. + +--- + +## Previous latest revision (generated compatibility patch refreshed; VC6 frontier in object.c) CPython baseline: `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. @@ -557,7 +3597,7 @@ One narrow C89 slice in `cpython/Modules/_tracemalloc.c`: hoisted `uintptr_t ptr Exact commands/results: -- `codex exec --sandbox workspace-write -C /home/ubuntu/projects/python-win9x --ephemeral ...` — exit 0. The child first added the test, then ran RED before editing production source: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1, expected assertion `AssertionError: _PyTraceMalloc_NewReference must hoist ptr/type/res/trace into the initial C89 declaration group`, followed by `FAILED`. +- `codex exec --sandbox workspace-write -C /home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x --ephemeral ...` — exit 0. The child first added the test, then ran RED before editing production source: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1, expected assertion `AssertionError: _PyTraceMalloc_NewReference must hoist ptr/type/res/trace into the initial C89 declaration group`, followed by `FAILED`. - Child GREEN: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 0, focused assertion passed and `ALL TESTS PASSED`. - Independent syntax + regression run: `bash -n scripts/vc6-probe-pythoncore-frontier.sh scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 0, all checks passed (`ALL TESTS PASSED`). - Fresh compiler probe: `XDG_RUNTIME_DIR="$PWD/build/tracemalloc-slice/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=51 compiled=50 cached=0 skipped=0`. `_tracemalloc.c` now compiles past the prior `_PyTraceMalloc_NewReference` C89 diagnostics. First blocker advanced to `cpython/Modules/timemodule.c`: C2275/C2146/C2065 at line 164 (`clock_t ticks`), line 171 (`_PyTime_t ns`), and line 507 (`time_module_state state`); further errors occur at lines 549, 773, 969, 1746–1759, 2097, and 2199–2294. These remain untouched for a separate slice. @@ -1818,7 +4858,7 @@ Exact commands and results: |---|---| | `git status --short --branch && git -C cpython status --short --branch && git -C cpython rev-parse HEAD && git -C cpython describe --tags --exact-match` | 0; pre-existing local modifications preserved; CPython remains detached at `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. | | `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` | 2; 39/40 sources compiled, including `_blake2/blake2s_impl.c`. First stable diagnostics: five C2065 loader-search constants at `posixmodule.c(15856)`–`(15860)`; distinct later errors start at 16173. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\home\\ubuntu\\projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\home\\ubuntu\\Organized\\Legacy-Ports\\Projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `bash -n scripts/vc6-probe-pythoncore-frontier.sh scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh` | 0; shell syntax and all applicable regression suites passed. | Compiler-probe progress only. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: determine and document intended Win9x behavior for these five loader-search constants, then add a focused failing test before any source edit. Keep the later C89 diagnostics separate. @@ -1841,7 +4881,7 @@ Exact commands and results: |---|---| | `git status --short --branch && git -C cpython status --short --branch && git -C cpython rev-parse HEAD && git -C cpython describe --tags --exact-match` | 0; pre-existing changes preserved; CPython detached at `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. | | `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` | 2; `_blake2/blake2s_impl.c` compiled; 39/40 sources compiled. First stable diagnostics are the five C2065 loader-search constants at `posixmodule.c(15856)`–`(15860)`; later C89 diagnostics follow. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; verified compiler banner as stated above. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\Organized\Legacy-Ports\Projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; verified compiler banner as stated above. | | `bash -n scripts/vc6-probe-pythoncore-frontier.sh scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh` | 0; syntax checks and all applicable regression suites passed. | | `git -C cpython diff --check && cmp -s <(git -C cpython diff) compat/msvc600/cpython-3.11.16-vc6-headers.patch && git diff --check -- . ':!compat/msvc600/cpython-3.11.16-vc6-headers.patch'` | 0; nested diff check passed, generated compatibility patch reproduces the full nested diff byte-for-byte, and non-generated outer diff check passed. | @@ -1979,7 +5019,7 @@ Exact commands and results: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; compiler banner recorded above. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\Organized\Legacy-Ports\Projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; compiler banner recorded above. | | `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before edit | 2; 39/40 compiled; first diagnostic family at `posixmodule.c(14905)` described above. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding assertion, before source edit | 1; expected RED: `VC6 os.add_dll_directory fallback missing`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`, including add/remove DLL-directory assertion. | @@ -2310,7 +5350,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first blocker `posixmodule.c(11238)` C2065 for `_MAX_ENV`; summary `total=40 compiled=39 cached=0`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before source edit | 1; expected RED: `VC6 _MAX_ENV fallback missing`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`. | @@ -2340,7 +5380,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first stable blocker `posixmodule.c(11217)` C2275/C2065 for `unicode`; summary `total=40 compiled=39 cached=0`. | | Focused `win32_putenv()` assertion before source edit | 1; expected RED, as reported by the delegated lane. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`. | @@ -2370,7 +5410,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | Focused `SYMBOLIC_LINK_FLAG_DIRECTORY` assertion before source edit | 1; expected RED, as reported by the delegated coding lane. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`, including the new fallback assertion. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` after source edit | 2; `_blake2/blake2s_impl.c` compiled and `posixmodule.c` compiled past line 9076. First stable blocker is `posixmodule.c(11217)` C2275/C2065 for later C89 declarations in `os_putenv_impl()`; summary `total=40 compiled=39 cached=0`. | @@ -2399,7 +5439,7 @@ This slice changed only: || Command | Exit/result | |---|---| -|| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +|| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | || `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; `_blake2/blake2s_impl.c` compiled, 39 sources compiled, first blocker `posixmodule.c(8885)` C2065 for `FSCTL_GET_REPARSE_POINT`; summary `total=40 compiled=39 cached=0`. | || `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the focused assertion, before source edit | 1; expected RED: `VC6 os_readlink fallback missing`. | || `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; GREEN, `ALL TESTS PASSED`. | @@ -2429,7 +5469,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | Focused waitpid assertion before source edit | 1; expected RED. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` after source edit | 2; `_blake2/blake2s_impl.c` compiled, 39 sources compiled, and `posixmodule.c` compiled past line 8741. The next first stable blocker is `posixmodule.c(8885)` C2065 for unavailable `FSCTL_GET_REPARSE_POINT`; summary `total=40 compiled=39 cached=0 skipped=0`. | @@ -2458,7 +5498,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; `_blake2/blake2s_impl.c` compiled, 39 sources compiled, first blocker `posixmodule.c(8741)` C2632/C2143/C2065 for `unsigned long long ustatus`; summary `total=40 compiled=39 cached=0 skipped=0`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the focused assertion, before source edit | 1; expected RED: `os_waitpid_impl must use the VC6-compatible PY_LONG_LONG status type`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; GREEN, `ALL TESTS PASSED`. | @@ -2488,7 +5528,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | Focused `os_kill_impl` assertion before source edit | 1; expected RED declaration/order assertion failure, as reported by the delegated lane. | | Focused `os_kill_impl` assertion after source edit | 0; GREEN. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` | 0; `ALL TESTS PASSED`. | @@ -2518,7 +5558,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; `_blake2/blake2s_impl.c` compiled, 39 sources compiled, and first blocker `posixmodule.c(6699)` C2143/C2065 for `saved_errno`; summary `total=40 compiled=39 cached=0`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the focused assertion, before source edit | 1; expected RED: `os_spawnv_impl saved_errno declaration missing from opening group`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; GREEN, `ALL TESTS PASSED`. | @@ -2549,7 +5589,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | Focused parse-envlist assertion before source edit | 1; expected RED assertion failure: `parse_envlist must hoist key and val into the C89 declaration group and preserve PyList_GetItem/evaluation/error/cleanup order`. | | Focused parse-envlist assertion after source edit | 0; GREEN, no output. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` | 0; `ALL TESTS PASSED`, including the new parse-envlist assertion. | @@ -2579,7 +5619,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first stable blocker `posixmodule.c(5130)` C2065 for `IO_REPARSE_TAG_SYMLINK`; summary `total=40 compiled=39 cached=0`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before source edit | 1; expected RED: `VC6 symlink reparse-tag fallback missing`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`. | @@ -2609,7 +5649,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first blocker `posixmodule.c(4614)` C2275/C2146/C2065 for `len`, `buffer`, `norm_len`, `norm_path`, and `result`; summary `total=40 compiled=39 cached=0`. | | Focused normpath structural assertion before source edit | 1 as reported by the delegated lane; expected RED. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after implementation | 0; `ALL TESTS PASSED`, including the normpath assertion. | @@ -2639,7 +5679,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first blocker `posixmodule.c(4569)` C2143/C2065 for the post-statement `wchar_t *p`; summary `total=40 compiled=39 cached=0`. | | Focused split-root structural assertion before source edit | 1; expected RED assertion failure. | | Focused split-root structural assertion after source edit | 0; expected GREEN result. | @@ -2670,7 +5710,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | Forced frontier probe before this slice | 2; first stable blocker `posixmodule.c(4473)` C2143/C2065 for `wchar_t *tmp`; `_blake2/blake2s_impl.c` compiled; summary `total=40 compiled=39 cached=0`. | | Focused `tmp` assertion before source edit | 1; expected RED assertion failure. | | Focused `tmp` assertion after source edit | 0; expected GREEN result. | @@ -2702,7 +5742,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first stable blocker `posixmodule.c(4402)` C2275/C2065 for `PyObject *str`; summary `total=40 compiled=39 cached=0`. `_blake2/blake2s_impl.c` compiled. | | Focused `os__getfullpathname_impl()` assertion before source edit | 1 as reported by the delegated lane; expected RED. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after implementation | 0; `ALL TESTS PASSED`, including the new `os__getfullpathname_impl` assertion. | @@ -2732,7 +5772,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first stable blocker `posixmodule.c(3874)` C2275/C2065 for `PyObject *resobj`; summary `total=40 compiled=39 cached=0`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the focused assertion, before the source edit | 1; expected RED: `posix_getcwd resobj declaration missing from opening group`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after the source edit | 0; `ALL TESTS PASSED`. | @@ -2762,7 +5802,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first stable blocker `posixmodule.c(2493)` C2143 for the post-statement nanosecond declaration; summary `total=40 compiled=39 cached=0`. | | Focused nanosecond assertion before source edit | 1; expected RED assertion failure, as reported by the delegated lane. | | Focused nanosecond assertion after source edit | 0; expected GREEN result. | @@ -2793,7 +5833,7 @@ This slice changed only: ||| Command | Exit/result | |||---|---| -||| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +||| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | ||| `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; first stable blockers `posixmodule.c(2472)` and `(2488)`, C2632 `long` followed by `long`; summary `total=40 compiled=39 cached=0`. | ||| `bash scripts/vc6-probe-pythoncore-frontier.test.sh` before source edit | 1; expected RED: `VC6 stat-size assertion must use PY_LONG_LONG`, followed by the focused assertion failure. | ||| `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`. | @@ -2823,7 +5863,7 @@ This slice changed only: || Command | Exit/result | ||---|---| -|| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +|| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | || `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; `posixmodule.c(2453)` first stable blocker, C2143/C2275/C2065 for post-statement `StatResultType`/`v`; summary `total=40 compiled=39 cached=0`. | || `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before source edit | 1; expected RED: `_pystat_fromstructstat declaration missing from opening group`. | || `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | 0; `ALL TESTS PASSED`. | @@ -2853,7 +5893,7 @@ This slice changed only: | Command | Exit/result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | 2; `_blake2/blake2s_impl.c` compiled and `posixmodule.c(2400)` was first; C2143/C2275/C2065 followed for `res`, `s_in_ns`, `ns_total`, and `float_s`; summary `total=40 compiled=39 cached=0 skipped=0`. | | focused `fill_time()` assertion before source edit | 1 as reported by the coding lane; expected RED declaration/order failure. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after implementation | 0; `ALL TESTS PASSED`, including the new `fill_time()` assertion. | @@ -2913,7 +5953,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; first blocker `posixmodule.c(1907)` C2065/C2146/C2059 for `FILE_ATTRIBUTE_TAG_INFO`; summary `total=40 compiled=39 cached=0`. | | focused TDD assertion before source edit | exit 1 as required by TDD. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after implementation | exit 0; `ALL TESTS PASSED`. | @@ -2943,7 +5983,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; `_blake2/blake2s_impl.c` compiled; first blocker `posixmodule.c(1826)` C2143/C2065 for the post-statement `is_unc_like_path` declaration; summary `total=40 compiled=39 cached=0`. | | delegated `codex exec -s workspace-write --skip-git-repo-check ...` | exit 0; added the focused assertion, reported the required RED test, applied only `win32_wchdir()`, and regenerated the compatibility patch; no commit/push/publication. | | focused TDD assertion before source edit | exit 1 as required by TDD. | @@ -2974,7 +6014,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; 39 sources compiled; first stable blocker `posixmodule.c(1582)` C2065, undeclared `FSCTL_GET_REPARSE_POINT`; later C89 declaration and legacy API diagnostics followed; summary `total=40 compiled=39 cached=0 skipped=0`. | | focused delegated RED assertion | exit 1 as reported by the coding lane; expected assertion that the VC6 path must return `FALSE` without the unavailable operation. | | focused delegated GREEN assertion | exit 0 as reported by the coding lane: `ok - VC6 reparse query returns FALSE and preserves the modern body`. | @@ -3004,7 +6044,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; 39 sources compiled; first blocker `posixmodule.c(1482)` C2632 for `long long`; later declarations/APIs also failed; summary `total=40 compiled=39 cached=0`. | | delegated focused TDD assertion before source edit | exit 1 as reported by the coding lane; expected failure `Windows Py_off_t must use PY_LONG_LONG`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after implementation | exit 0; `ALL TESTS PASSED`, including `Windows Py_off_t uses PY_LONG_LONG`. | @@ -3033,7 +6073,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; `_blake2/blake2s_impl.c` compiled, 39 sources compiled; first blocker `posixmodule.c(39)`, fatal C1083 for missing `sddl.h`; summary `total=40 compiled=39 cached=0 skipped=0`. | | focused delegated TDD assertion before source edit | exit 1 as reported by the coding lane; expected assertion failure for missing VC6 SDDL exclusion/fallback. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after implementation | exit 0; `ALL TESTS PASSED`, including `posix mkdir excludes SDDL on VC6 and uses null security attributes`. | @@ -3062,7 +6102,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; `_blake2/blake2s_impl.c` compiled, 39 sources compiled; first blocker `_operator.c(1814)` and `(1887)`, both C2059 syntax errors for designated fields; summary `total=39 compiled=38 cached=0`. | | delegated `codex exec -s workspace-write --skip-git-repo-check ...` | exit 0; added the two focused assertions, reported the expected RED failures, applied only the two `_operator.c` positional-initializer edits, regenerated the compatibility patch, and reported GREEN; no commit/push/publication. | | focused RED assertions | exit 1 as required by TDD; both new positional-initializer assertions failed before the source edit. | @@ -3092,7 +6132,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; `_blake2/blake2s_impl.c` compiled, 38 sources compiled; first blocker `_operator.c(1596)` C2275/C2065/C2223/C2198 for the post-statement `_operator_state *state`; later designated-initializer blockers at `(1813)` and `(1886)`; summary `total=39 compiled=38 cached=0`. | | delegated `codex exec -s workspace-write --skip-git-repo-check ...` | exit 0; added the focused assertion, reported the expected RED failure, applied only `methodcaller_new()`, regenerated the compatibility patch, and reported GREEN; no commit/push/publication. | | focused RED assertion | exit 1 as required by TDD; `AssertionError: methodcaller_new needs an opening C89 state declaration and original-point assignment`. | @@ -3123,7 +6163,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; `_blake2/blake2s_impl.c` compiled, 38 sources compiled; first blocker `_operator.c(1558)` C2059 for the designated initializer; later blockers at `(1596)`, `(1813)`, and `(1886)`; summary `total=39 compiled=38 cached=0`. | | delegated `codex exec --approve-for-me --skip-git-repo-check ...` | exit 0; added the focused assertion, reported the expected RED failure before the source edit, applied only `attrgetter_type_spec`, regenerated the compatibility patch, and reported GREEN; no commit/push/publication. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` | exit 0; `ALL TESTS PASSED`, including `attrgetter_type_spec uses a C89-compatible declared-order positional initializer`. | @@ -3153,7 +6193,7 @@ This slice changed only: | Command | Result | |---|---| -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\home\\ubuntu\\projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\\home\\ubuntu\\Organized\\Legacy-Ports\\Projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; `_blake2/blake2s_impl.c` compiled, 38 sources compiled; first blocker `_operator.c(1402)` C2275/C2146/C2065 for post-statement `Py_ssize_t nargs`; later blockers at `(1556)`, `(1594)`, `(1811)`, and `(1884)`; summary `total=39 compiled=38 cached=0 skipped=0`. | | focused Codex lane | exit 0; added the focused assertion, reported the expected RED failure, applied only the `attrgetter_vectorcall()` declaration-order edit, ran GREEN, regenerated the compatibility patch, and made no commit/push/publication. | | focused RED assertion | exit 1 as required by TDD; `AssertionError: attrgetter_vectorcall needs an opening C89 nargs declaration and original-point assignment`. | @@ -4572,7 +7612,7 @@ The recorded frontier was re-probed first and remained applicable: `cpython/Modu | Command | Result | |---|---| | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; 23 sources compiled through `_blake2/blake2s_impl.c` and `arraymodule.c`; first stable diagnostics were `atexitmodule.c(99)` C2143 and `(100)` C2275/C2065 for `the_func`/`res`; summary `total=24 compiled=23 cached=0 skipped=0`. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`; Wine emitted expected headless-display warnings. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`; Wine emitted expected headless-display warnings. | | focused coding-agent delegation | failed before launch: `The 'anthropic' package is required for the Anthropic provider`; no child changes were used. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before source edit | exit 1 as required by TDD; `atexit_callfuncs: the_func declaration missing`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | exit 0; `ALL TESTS PASSED`. | @@ -4689,7 +7729,7 @@ The recorded frontier was re-probed first and remained applicable: 22 sources co | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before source edit | exit 1 as required by TDD; `arrayiter_spec retains designated fields`. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | exit 0; `ALL TESTS PASSED`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` after source edit | exit 2; the `arrayiter_spec` C2059 blocker cleared. The next first stable diagnostics are `arraymodule.c(3114)`, `(3119)`, and `(3125)` for post-statement locals in `array_modexec()`, followed by the designated `arraymodule` initializer at `(3158)`; summary `total=23 compiled=22 cached=0 skipped=0`. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings. | | `bash -n scripts/vc6-probe-pythoncore-frontier.test.sh scripts/vc6-probe-pythoncore-frontier.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && git -C cpython diff --check` | exit 0; all applicable regression suites and source checks passed. | | `git -C cpython diff > compat/msvc600/cpython-3.11.16-vc6-headers.patch && git -C cpython diff --check` | exit 0; compatibility patch regenerated and nested source diff is clean. | | pristine detached `v3.11.16` temporary worktree plus `git apply --check` | exit 0; patch applies cleanly; temporary verification worktree removed. | @@ -4743,7 +7783,7 @@ The recorded frontier was re-probed first and remained applicable: `_blake2/blak | Command | Result | |---|---| | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` before this slice | exit 2; 22 sources compiled; first stable diagnostics were `arraymodule.c(2922)` C2143 and `(2923)` undeclared/cascade errors for `state`; later diagnostics included lines 2975, 2991, 3023, 3110, 3115, 3121, and 3154; summary `total=23 compiled=22 cached=0 skipped=0`. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings. | | focused coding-agent delegation | failed before launch: `The 'anthropic' package is required for the Anthropic provider`; no child changes were used. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before source edit | exit 1 as required by TDD; after correcting the assertion matcher, it failed with `arrayiter_next state declaration missing from opening group`. No production source was changed before the expected red result. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after source edit | exit 0; `ALL TESTS PASSED`. | @@ -4992,7 +8032,7 @@ The recorded `arraymodule.c` frontier was re-probed first and remained applicabl | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after the source edit | exit 0; `ALL TESTS PASSED`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` after the source edit | exit 2; the line-736 `PyObject *res` blocker cleared. The next first stable diagnostics are the separate C89 `Py_ssize_t vs/ws` declarations at lines 766–767, followed by later declaration, `long long`, string-size, and initializer families. Summary `total=23 compiled=22 cached=0 skipped=0`. | | `bash -n scripts/vc6-probe-pythoncore-frontier.test.sh scripts/vc6-probe-pythoncore-frontier.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh && git -C cpython diff --check` | exit 0; all applicable regression suites and source checks passed. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; compiler banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\\\home\\\\ubuntu\\\\Organized\\\\Legacy-Ports\\\\Projects\\\\python-win9x\\\\MSVC600\\\\VC98\\\\Bin\\\\VCVARS32.BAT && cl'` | exit 0; compiler banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings. | | `git -C cpython diff > compat/msvc600/cpython-3.11.16-vc6-headers.patch` | exit 0; compatibility patch regenerated. | | pristine detached `v3.11.16` temporary worktree plus `git apply --check` | exit 0; patch applies cleanly; temporary worktree removed. | @@ -5021,7 +8061,7 @@ The recorded `arraymodule.c` frontier was re-probed through the preceding `getar | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` after the source edit | exit 2; 22 sources compiled and `arraymodule.c` was reached. The `int cmp` blocker cleared. The next first stable diagnostics are `arraymodule.c(736) : error C2275: 'PyObject' : illegal use of this type as an expression` for `PyObject *res` after executable statements, followed by later declaration-order, string-size, and initializer diagnostics; summary `total=23 compiled=22 cached=0 skipped=0`. | | `bash -n scripts/vc6-probe-pythoncore-frontier.test.sh scripts/vc6-probe-pythoncore-frontier.sh` | exit 0. | | `bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && git -C cpython diff --check` | exit 0; all applicable regression suites and source checks passed. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\home\\ubuntu\\projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | exit 0; compiler banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings before the banner. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\home\\ubuntu\\Organized\\Legacy-Ports\\Projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | exit 0; compiler banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. Wine emitted expected headless-display warnings before the banner. | | `git -C cpython diff > compat/msvc600/cpython-3.11.16-vc6-headers.patch` | exit 0; compatibility patch regenerated. | | pristine detached `v3.11.16` temporary worktree plus `git apply --check` | exit 0; patch applies cleanly; temporary verification worktree removed. | @@ -5668,14 +8708,14 @@ The recorded `_pickle.c` state was re-probed before editing and remained true th | Command | Result | |---|---| -| `codex exec -s read-only --skip-git-repo-check "In /home/ubuntu/projects/python-win9x, inspect the current CPython v3.11.16 Windows 98/MSVC6 port state without modifying any files. Focus only on the recorded frontier in Modules/_randommodule.c at _random_exec(), especially the C89 mixed-declaration blocker around longval/longtype. Report the smallest evidence-backed edit, the exact focused test assertion that should be added first under strict TDD, and any semantic risks. Do not edit, commit, reset, stash, or push."` | exit 0; read-only focused analysis reported the minimal two-local hoist and no semantic risk beyond preserving initializer timing. No files changed. | +| `codex exec -s read-only --skip-git-repo-check "In /home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x, inspect the current CPython v3.11.16 Windows 98/MSVC6 port state without modifying any files. Focus only on the recorded frontier in Modules/_randommodule.c at _random_exec(), especially the C89 mixed-declaration blocker around longval/longtype. Report the smallest evidence-backed edit, the exact focused test assertion that should be added first under strict TDD, and any semantic risks. Do not edit, commit, reset, stash, or push."` | exit 0; read-only focused analysis reported the minimal two-local hoist and no semantic risk beyond preserving initializer timing. No files changed. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after adding the assertion, before the source edit | exit 1 as required by TDD; `_random_exec uses C89 locals and preserves initialization order` failed while prior assertions passed. | | `bash scripts/vc6-probe-pythoncore-frontier.test.sh` after the source edit | exit 0; `ALL TESTS PASSED`. | | `VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` after the source edit | exit 2; `_randommodule.c` compiled cleanly and the frontier advanced to `_sha3/sha3module.c(183)`, `error C2275: 'PyTypeObject' : illegal use of this type as an expression`, followed by designated-initializer `error C2059` diagnostics at lines 442, 445, 448, 451, 567, 570, and 649; `total=18 compiled=17 cached=0 skipped=0`. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\home\\ubuntu\\projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | exit 0; compiler banner: Microsoft 32-bit C/C++ Optimizing Compiler Version `12.00.8804` for 80x86. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport wine cmd /c 'call Z:\\home\\ubuntu\\Organized\\Legacy-Ports\\Projects\\python-win9x\\MSVC600\\VC98\\Bin\\VCVARS32.BAT && cl'` | exit 0; compiler banner: Microsoft 32-bit C/C++ Optimizing Compiler Version `12.00.8804` for 80x86. | | `bash -n scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && git -C cpython diff --check` | exit 0; all regression suites and nested source diff checks passed. | | `git -C cpython diff > compat/msvc600/cpython-3.11.16-vc6-headers.patch` | exit 0; compatibility patch regenerated. | -| `git -C cpython worktree add --detach /home/ubuntu/projects/python-win9x/build/verify-vc6-patch-worktree v3.11.16 && git -C /home/ubuntu/projects/python-win9x/build/verify-vc6-patch-worktree apply --check ../../compat/msvc600/cpython-3.11.16-vc6-headers.patch` | exit 0; patch applied cleanly to a pristine detached baseline, and the temporary worktree was removed. | +| `git -C cpython worktree add --detach /home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x/build/verify-vc6-patch-worktree v3.11.16 && git -C /home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x/build/verify-vc6-patch-worktree apply --check ../../compat/msvc600/cpython-3.11.16-vc6-headers.patch` | exit 0; patch applied cleanly to a pristine detached baseline, and the temporary worktree was removed. | **Current compile-frontier state:** `_randommodule.c` now compiles cleanly under MSVC 6.0 (`cl.exe` 12.00.8804) through Wine. The next blocker is `_sha3/sha3module.c`'s C89 declaration-order and C99 designated-initializer defects. This remains compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, no Wine execution of Python, and no real Windows 98 SE execution is claimed. @@ -7650,7 +10690,7 @@ Exact commands/results: |---|---| | `git status --short --branch && git -C cpython status --short --branch && git -C cpython rev-parse HEAD && git -C cpython describe --tags --exact-match` | 0; preserved pre-existing outer and nested modifications; baseline remains `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. | | `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` | 2; `_blake2/blake2s_impl.c` compiled; 39/40 sources compiled. First errors are the five C2065 loader-search constants at `posixmodule.c(15856)`–`(15860)`; later C89 diagnostics begin at 16173. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\Organized\Legacy-Ports\Projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; banner `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `bash -n scripts/vc6-probe-pythoncore-frontier.sh scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh` | 0; shell syntax and all applicable regression suites passed. | | `git -C cpython diff --check && cmp -s <(git -C cpython diff) compat/msvc600/cpython-3.11.16-vc6-headers.patch && git diff --check -- . ':!compat/msvc600/cpython-3.11.16-vc6-headers.patch'` | 0; nested whitespace check passed, generated patch reproduces full nested diff byte-for-byte, and non-generated outer diff check passed. | @@ -7787,7 +10827,7 @@ Exact commands/results: | Command | Exit/result | |---|---| | `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` | 2; 39/40 compiled. First stable diagnostics are the five C2065 errors above; distinct later C89 diagnostics follow. | -| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | +| `WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all wine cmd /c 'call Z:\home\ubuntu\Organized\Legacy-Ports\Projects\python-win9x\MSVC600\VC98\Bin\VCVARS32.BAT && cl'` | 0; `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`. | | `bash -n scripts/vc6-probe-pythoncore-frontier.sh scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe-pythoncore-frontier.test.sh && bash scripts/vc6-probe.test.sh && bash scripts/vc6-probe-core.test.sh && bash scripts/vc6-probe-pathcch.test.sh && bash scripts/generate-getpath-frozen.test.sh && bash scripts/vc6-probe-stdint.test.sh` | 0; all applicable regression suites passed (`ALL TESTS PASSED`). | | `git -C cpython diff --check && cmp -s <(git -C cpython diff) compat/msvc600/cpython-3.11.16-vc6-headers.patch; git diff --check -- . ':(exclude)compat/msvc600/cpython-3.11.16-vc6-headers.patch'` | 0; nested diff clean, compatibility patch matches complete nested diff byte-for-byte, outer non-generated diff clean. | | `git -C cpython rev-parse HEAD && git -C cpython describe --tags --exact-match` | 0; baseline remains `v3.11.16` / `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. | @@ -8024,4 +11064,1131 @@ Exact verification: Files changed by this slice: `cpython/Objects/longobject.c`, `scripts/vc6-longobject-c89.test.py`, and this status entry. This is compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: investigate the VC6 `long long` blocker at `PyLong_FromUnsignedLongLong` (including applicable compatibility typedef/macros and declarations) as its own evidence-backed slice; do not bundle later C89/CRT diagnostics. No commit or push. --- +## Latest revision (_PyTypes_InitState status declaration hoisted; object.c frontier advances) + +Date: 2026-10-05 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. The expected legacy reference path was absent; the active-profile copy was read at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, compatibility-patch regeneration, or publication. CPython remains detached at `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded frontier was freshly rechecked with forced-fresh VC6/Wine compile. `_blake2/blake2s_impl.c` compiled; actual first blocker was `_PyTypes_InitState()` in `cpython/Objects/object.c`, late `PyStatus status = _PyTypes_InitSlotDefs()` at line 1906. Used one focused Codex CLI coding lane (`codex-cli 0.153.4`, workspace-write). It added `scripts/vc6-object-initstate-c89.test.py`; the first run failed RED as intended on missing entry declaration. Then it hoisted only `PyStatus status;` to function entry and retained `status = _PyTypes_InitSlotDefs()` after the non-main-interpreter guard, preserving slot initialization and error handling. All prior dirty/untracked work was preserved. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=100 compiled=99 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2275/C2146/C2065/C2115 at `object.c(1906)` on the late `PyStatus status` declaration. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791162097-96506-7360.log`. +- TDD RED: `python3 scripts/vc6-object-initstate-c89.test.py cpython/Objects/object.c` — exit 1 with expected assertion that `_PyTypes_InitState` must declare status at entry. +- GREEN plus applicable focused object regressions (new initstate test, object C89, richcompare, FunctionStr, NotImplemented, descrobject/classmethod, genericaliasobject) — exit 0 for every command. The test asserts entry declaration, exact single declaration, guard, original slot-definitions call assignment point, exception propagation, and return order. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. New source assertion and numerous checks pass; known unrelated console type detection/cleanup assertion and numeric dispatch helper (`ValueError: substring not found`) still fail. +- Post-change forced-fresh probe (same command as pre-change) — exit 2; `total=100 compiled=99 cached=0 skipped=0`. The former PyStatus diagnostics at line 1906 are gone. First remaining errors are C2143/C2065 loop-declaration errors at `object.c(2060)` (`for (size_t i=...)`), followed by another loop declaration at line 2091 and dependent diagnostics. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791162455-96506-d5b0.log`. +- `git diff --check -- scripts/vc6-object-initstate-c89.test.py` and `git -C cpython diff --check -- Objects/object.c` — exit 0. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is claimed. + +Files changed in this slice: `cpython/Objects/object.c`, `scripts/vc6-object-initstate-c89.test.py`, and this status entry. Compiler-probe progress only. Next frontier: fresh forced-fresh probe before editing, then TDD only the first `for (size_t i=...)` declaration family at `object.c(2060)`; leave the separate line-2091 loop declaration untouched. No commit or push. + +## Latest revision (obmalloc default-allocator local hoisted; fresh VC6 frontier advances) + +Date: 2026-10-05 12:11 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the dirty outer worktree and extensive detached CPython edits; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +Fresh forced-fresh VC6/Wine re-probe confirmed the recorded state: `_blake2/blake2s_impl.c` compiled and the first stable blocker was `Objects/obmalloc.c(239)`, late `PyMemAllocatorEx new_alloc` in `pymem_set_default_allocator()`. One focused Codex CLI lane (`codex-cli 0.153.4`, authenticated, workspace-write; session `01a10bf3-21bf-7562-9c2e-2128573a0d08`) followed TDD. Added `scripts/vc6-obmalloc-default-allocator-c89.test.py`, observed expected RED, then hoisted only `new_alloc` to function entry; the previous `old_alloc` handling, domain switch/assignments, allocator call, debug hook, and return ordering remain unchanged. The agent's preservation comparison confirmed prior local changes remained byte-identical. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First errors C2275/C2146/C2065 at `obmalloc.c(239)` on `PyMemAllocatorEx new_alloc`. Full log: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791201545-269604-c8a0.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c` — exit 1; expected message `new_alloc must be declared once without initializer at function entry`. +- GREEN and independent focused rerun: same command — exit 0; `obmalloc default allocator C89 declaration and execution order: PASS`. Existing tracemalloc positional-initializer test also passes: `python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0. +- Applicable suite: `bash scripts/vc6-probe-pythoncore-frontier.test.sh > /tmp/obmalloc-lane-frontier.log 2>&1` — exit 1. Two existing unrelated failures remain: console type detection/cleanup order and numeric dispatch helpers. Live one-source integration test also ran and correctly reported a nonzero first-blocker status. Full 322-line output: `/tmp/obmalloc-lane-frontier.log`. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/obmalloc-default-allocator-post.log 2>&1` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `obmalloc.c(239)` declaration diagnostics are gone. Next diagnostics are C2059 on `{` at lines 244, 247, and 250 in the three `new_alloc = (PyMemAllocatorEx)PY*_ALLOC;` assignments; later separate declaration/type families remain untouched. Full log: `build/cron-current/obmalloc-default-allocator-post.log`. +- `git diff --check`, nested `git -C cpython diff --check -- Objects/obmalloc.c`, focused tests — exit 0. Baseline tag/commit unchanged. + +Files changed in this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-default-allocator-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh forced probe before editing, then address only the cast/initializer assignment family in `pymem_set_default_allocator()` with a distinct TDD test; preserve the verified declaration change and all subsequent blockers separately. + +--- +## Latest run (RawStrdup frontier reconfirmed; implementation lane unavailable) + +Date: 2026-10-06 UTC + +Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the existing dirty outer worktree and detached CPython modifications; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyMem_RawStrdup()` frontier was forced-fresh re-probed and remains accurate. `_blake2/blake2s_impl.c` compiled; `Objects/obmalloc.c` is the first failing translation unit. First stable diagnostics are C2143 at lines 697-698 on declarations following `assert` in `_PyMem_RawStrdup()`, followed by C2065 cascades for `copy` and `size`. The separate `_PyMem_Strdup()` declarations at lines 710-711 and subsequent obmalloc diagnostics remain untouched. + +One focused coding-subagent delegation was attempted for only `_PyMem_RawStrdup()` and failed before startup because the Hermes runtime lacks the `anthropic` package and lazy installs are disabled. `codex-cli 0.153.4` is installed, but no external CLI lane was started in the shared dirty checkout. No source or regression test was edited; this run is diagnostics-only. + +Exact verification: + +- Forced-fresh VC6/Wine probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `obmalloc.c(697-698)`, followed by C2065 for `copy` and `size`. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791256009-486631-f230.log`. The output invokes MSVC600 via Wine but has no standalone compiler-version banner. +- Focused regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all four passed. +- Applicable harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The obmalloc checks passed; two known unrelated failures remain: console type detection/cleanup order and numeric dispatch (`ValueError: substring not found`). +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- PORT_STATUS.md` — exit 0. CPython tag and commit checks passed; baseline unchanged. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next: retry one focused TDD coding lane for `_PyMem_RawStrdup()` when delegation is available; keep `_PyMem_Strdup()` and later obmalloc diagnostics as separate slices. + +--- +## Latest revision (_PyMem_RawStrdup C89 declarations hoisted; frontier advances) + +Date: 2026-10-06 05:26 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. + +The recorded `_PyMem_RawStrdup()` frontier was forced-fresh re-probed and remains current. `_blake2/blake2s_impl.c` compiled, followed by 95 other source files; `Objects/obmalloc.c` remained the first failing translation unit. Before the edit, VC6's first stable diagnostics were C2143 at lines 697-698, before the declarations following `assert(str != NULL)`, followed by C2065 cascades for `copy` and `size`. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a10fa7-a787-7c40-a8ce-88b6fc719855`, workspace-write) performed the one-slice TDD change. It added a focused assertion to the existing RawWcsdup regression script, observed the intended RED, then hoisted only `size_t size` and `char *copy` in `_PyMem_RawStrdup()`; initialization remains after the assert. Assert, `strlen`, allocation, NULL handling, `memcpy`, and return order are unchanged. `_PyMem_Strdup()` and all later obmalloc diagnostics were left untouched. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `obmalloc.c(697-698)`, then C2065 cascades for `copy` and `size`. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791263672-508466-3950.log`. +- TDD baseline focused test: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c` — exit 0 before strengthening the test; the existing RawWcsdup C89 copy/empty/allocation-failure/overflow checks passed. +- TDD RED: same focused test after adding the RawStrdup assertion and before the production edit — exit 1, expected assertion `_PyMem_RawStrdup must use C89 declarations and preserve operation order`. +- TDD GREEN and focused regressions: `python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all four passed. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1. The new and other obmalloc checks passed. Two known unrelated failures remain: console type detection/cleanup order, and numeric dispatch (`ValueError: substring not found`). No suite-wide pass claimed. +- Post-change forced-fresh probe (same command as pre-change) — exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former RawStrdup diagnostics at lines 697-699 are gone. First remaining diagnostics are C2143 at `obmalloc.c(713-714)`, followed by undeclared `copy`/`size` cascades in the separate `_PyMem_Strdup()` helper; distinct later obmalloc diagnostics remain untouched. Full output: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791264091-508466-5e00.log`. +- Scoped `git diff --check -- scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, `git -C cpython diff --check -- Objects/obmalloc.c`, and CPython exact tag/commit checks — exit 0. + +Files changed in this slice: `cpython/Objects/obmalloc.c`, `scripts/vc6-obmalloc-rawwcsdup-c89.test.py`, and this status entry. The outer worktree and detached CPython checkout retain their prior dirty/untracked state. This remains compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next frontier: freshly re-probe before edits, then use one TDD slice on only `_PyMem_Strdup()`'s C89 declaration family at `obmalloc.c(713-714)`; leave the later allocator-map/API diagnostics separate. + +--- +## Latest run (`allocate_from_new_pool` pool declaration hoisted; frontier advances) + +Date: 2026-10-07 09:56 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Re-probed the recorded `poolp next` frontier before editing. It had already been fixed locally: the current first blocker was the separate late initialized `poolp pool = usable_arenas->freepools` declaration in `allocate_from_new_pool()`. Used one focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a115c5-019c-76d0-ba38-5934bc3d03d6`) after native delegation failed because the Anthropic package is unavailable and lazy installs are disabled. The lane extended the existing pool-extend test, ran the focused test RED before production edit, then hoisted only `poolp pool` to function entry. The assignment remains after the arena-list updates at its original execution point. Existing early returns, allocator list operations, and subsequent pool initialization remain unchanged. `pymalloc_pool_extend()` and the distinct subsequent blockers were not altered. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-confirm" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2275/C2146/C2065 at `obmalloc.c(1889)` on `poolp pool`; following pointer errors are cascades. Log: `build/cron-current/cron-reprobe-current.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-pool-extend-c89.test.py cpython/Objects/obmalloc.c` — exit 1; expected assertion that `allocate_from_new_pool` must declare `pool` without an initializer at function entry. The prior `pymalloc_pool_extend` assertion passed. +- Focused GREEN and eight applicable obmalloc tests: `python3 scripts/vc6-obmalloc-pool-extend-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-arena-map-is-used-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-allocator-name-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-default-allocator-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-rawwcsdup-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-setup-allocators-c89.test.py cpython/Objects/obmalloc.c && python3 scripts/vc6-obmalloc-tracemalloc-init-c89.test.py cpython/Objects/obmalloc.c cpython/Include/internal/pycore_pymem.h` — exit 0; all checks passed. The RawWcsdup test includes C89 compile/runtime checks. +- Applicable regression harness: `bash scripts/vc6-probe-pythoncore-frontier.test.sh` — exit 1; existing console type-detection/cleanup-order assertion and numeric-dispatch `ValueError: substring not found` remain. No harness-wide pass claimed. +- Post-change forced-fresh probe (same options, runtime `build/cron-current/runtime-post`) — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`; the former `poolp pool` diagnostics are gone. First remaining diagnostics now occur later in `obmalloc.c` at lines 1947-1952 (`block bp`, then `poolp next` in a separate function); further C89 declaration/type blockers follow. Log: `build/cron-current/post-pool-entry.log`. +- `git diff --check` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. Exact baseline tag/commit remain unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, extended `scripts/vc6-obmalloc-pool-extend-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: freshly probe before edits and address only the first current blocker in the next function in `obmalloc.c` (currently `block *bp` at line 1947), with its own TDD slice. Do not claim port completion. + +--- +## Latest run (`_PyObject_Calloc` locals hoisted for VC6; frontier advances) + +Date: 2026-10-07 UTC + +Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains exactly at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyObject_Calloc()` frontier was freshly confirmed before edits with a forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled; first stable diagnostics were C2143 at `obmalloc.c(2059)` and `(2061)` on the late initialized `nbytes` and `ptr`, followed by C2065 cascades at `(2062-2063)`. Hermes coding-subagent dispatch failed before startup because the Anthropic package is unavailable and lazy installs are disabled. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11735-95ee-78b1-ac52-9aef9b07138e`) followed TDD: it added `scripts/vc6-obmalloc-calloc-c89.test.py`, verified the expected RED before changing production code, then hoisted only `size_t nbytes` and `void* ptr` to function entry and retained both assignments after the original assertion/calculation points. The assertion, allocation and zeroing behavior, fallback, accounting and return order are preserved. No neighboring function or later blocker was changed. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-recheck" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-reprobe-current.log 2>&1` — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics C2143 at `obmalloc.c(2059)` and `(2061)`; C2065 `ptr` and `nbytes` at `(2062-2063)`. Capture: `build/cron-current/cron-reprobe-current.log`. +- TDD RED: `python3 scripts/vc6-obmalloc-calloc-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before production edit with expected assertion `_PyObject_Calloc must declare nbytes and ptr without initializers at function entry`. +- TDD GREEN and focused test: same command — exit 0, `_PyObject_Calloc nbytes/ptr entry declarations and original operation order: PASS`. +- Applicable obmalloc regression suite: the new calloc test plus allocator-name, arena-map-is-used, arena-map-mark-used, default-allocator, pool-extend, RawWcsdup/allocated-blocks, setup-allocators, and tracemalloc-init tests — all exit 0. Exact commands and output were independently rerun; tracemalloc used the required header `cpython/Include/internal/pycore_pymem.h`. The Codex lane's first broad-loop invocation exited 1 because it omitted that required header; corrected invocations passed. Two erroneous header-path attempts also failed with FileNotFoundError and are not test passes. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-post-calloc" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/post-calloc.log 2>&1` — actual probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former `_PyObject_Calloc()` diagnostics are gone. The first remaining diagnostic is C2143 at `obmalloc.c(2083)` for the late `uint size` in `insert_to_usedpool()`, followed by related late `poolp next`/`prev` errors at `(2084-2085)`; later errors are cascades or distinct functions and untouched. +- `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- scripts/vc6-obmalloc-calloc-c89.test.py` — exit 0. Exact CPython tag/commit unchanged. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-calloc-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: fresh forced-fresh probe before any edits; if the first blocker remains `insert_to_usedpool()` at line 2083, handle only that declaration family in a separate TDD slice. Do not claim port completion. + +--- +## Latest run (fresh probe confirms `pymalloc_free`; coding lane unavailable) + +Date: 2026-10-07 23:10 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `insert_to_freepool()` state was freshly re-probed. `_blake2/blake2s_impl.c` compiled, as did 99 source-list entries total; the first stable blocker has advanced to `pymalloc_free()` at `cpython/Objects/obmalloc.c(2286)`, C2143 before the late `pool` declaration and C2065 `pool` at 2287. Later diagnostics include `lastfree` and downstream allocator functions; they are distinct and untouched. One focused coding-subagent attempt was required but failed before startup because the Anthropic package is unavailable and lazy installs are disabled. Therefore this was diagnostics-only; no code or regression test changed. + +Exact verification: + +- Read-only discovery: `git status --short --branch` — exit 0; existing dirty/untracked files retained. +- Forced-fresh MSVC600/Wine probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-this-run" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `obmalloc.c(2286)`, C2065 `pool` at `(2287)`. Full capture: `/home/ubuntu/.hermes/profiles/maxwell/cache/terminal-output/out-1791414381-1200760-2b10.log`. +- Coding delegation for the one focused `pymalloc_free()` TDD slice — failed before child startup: Anthropic package missing; lazy installs disabled. No edits made by child. +- Applicable obmalloc regressions: chained all 11 `scripts/vc6-obmalloc-*.test.py` currently present, supplying `cpython/Objects/obmalloc.c` and `cpython/Include/internal/pycore_pymem.h` where required — exit 0; all 13 individual checks printed PASS (the pool-extend test covers three functions). +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git -C cpython diff --check -- Objects/obmalloc.c` and `git diff --check -- PORT_STATUS.md` — exit 0. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: retry a single focused TDD coding lane for only the confirmed `pymalloc_free()` declaration family when delegation is available. Do not claim port completion. + +--- +## Latest run (`pymalloc_free` C89 declarations hoisted; next blocker confirmed) + +Date: 2026-10-08 01:22 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `pymalloc_free()` frontier was freshly confirmed with forced-fresh MSVC600/Wine compilation: `obmalloc.c(2286)` C2143 before the late `pool` declaration, then C2065 `pool` at 2287. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a11915-6dd9-7242-b525-60e23eef616f`) followed strict TDD. It added `scripts/vc6-obmalloc-pymalloc-free-c89.test.py`, observed expected RED before production edits, then hoisted only `poolp pool` and `block *lastfree` into the function-entry declaration block. Assignments remain at their original evaluation points after the Valgrind early-return and address-range/refcount checks. No control flow or pointer updates were changed. All pre-existing local changes were preserved; the coding lane did not edit this status file. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-cron" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/cron-frontier-reprobe.log 2>&1` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics were C2143 at `obmalloc.c(2286)` and C2065 `pool` at `(2287)`. +- TDD RED: `python3 scripts/vc6-obmalloc-pymalloc-free-c89.test.py cpython/Objects/obmalloc.c` — exit 1 before production edits; expected assertion that `pool` and `lastfree` must be declared at function entry. +- TDD GREEN: same command after edit — exit 0; entry declarations and the function's full relevant evaluation/control-flow sequence passed. +- Focused obmalloc regression batch (all 12 `scripts/vc6-obmalloc-*.test.py`, with `cpython/Include/internal/pycore_pymem.h` supplied to the tracemalloc test) — exit 0; independently rerun by Hermes. All 12 test scripts exited 0; the pool-extend test validates three functions. RawWcsdup additionally passed its C89 compile/runtime checks. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-current/runtime-post-pymalloc-free" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current/post-pymalloc-free.log 2>&1` — probe exit 2; `total=101 compiled=100 cached=0 skipped=0`. The former `pymalloc_free()` diagnostics at 2286-2299 are gone. First remaining stable diagnostics are in later allocator/debug functions: C2275/C2065 at `obmalloc.c(2628-2630)` around `debug_alloc_api_t api`, `uint8_t q`, and `size_t nbytes`; subsequent diagnostics include other distinct debug allocator functions and allocator-statistics C89 declarations. Left untouched. +- Scoped `git diff --check -- scripts/vc6-obmalloc-pymalloc-free-c89.test.py` and `git -C cpython diff --check -- Objects/obmalloc.c` — exit 0. Nested CPython baseline verified unchanged: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Files changed by this slice: `cpython/Objects/obmalloc.c`, new `scripts/vc6-obmalloc-pymalloc-free-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: fresh forced-fresh probe before any new edit; if the recorded post-change frontier remains current, isolate only the first `debug_alloc_api_t api` C89 declaration family with its own TDD slice. Do not claim port completion. + +--- +## Latest run (fresh `mutablemapping_update()` probe; coding lane unavailable) + +Date: 2026-10-09 11:46 UTC + +Read `PORT_STATUS.md` and `README.md` before acting. The requested legacy-toolchain reference `references/python-3-win9x-msvc6.md` is absent from the project checkout and could not be located under `/home/ubuntu`; no claims rely on its contents. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Exact CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded `_blake2/blake2s_impl.c` / `mutablemapping_update()` frontier was freshly confirmed before any edit using the forced-fresh MSVC600/Wine source-list probe. `_blake2/blake2s_impl.c` compiled. First stable blocker remains the late `Py_ssize_t len` declaration at `Objects/odictobject.c(2299)`, followed by C2065 for `len` at `(2300)`. One focused coding-agent delegation was attempted for this precise defect family with TDD/preservation constraints, but failed before child startup because the Anthropic package is missing and lazy installs are disabled. Per the coding-agent delegation workflow, no direct substitute implementation was made. No source or tests were changed; diagnostics-only. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261009-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009-current/pre-change-probe.log 2>&1` — actual probe exit 2; summary `total=102 compiled=101 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2143 at `Objects/odictobject.c(2299)` and C2065 `len` at `(2300)`. Capture: `build/cron-20261009-current/pre-change-probe.log`. +- Focused coding-agent delegation for only the confirmed `len` declaration family — failed before child startup: missing `anthropic` package; lazy installs disabled. No child edits occurred. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/odictobject.c` exited 0. +- No source/test regressions were run because neither source nor tests changed. No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. This is compiler-probe progress only. Next frontier remains the late `Py_ssize_t len` declaration in `mutablemapping_update()`; retry the same narrow TDD slice when a coding agent can start. Do not claim port completion. + +--- +## Latest run (`picklebuf_as_buffer` designated initializer; frontier advances) + +Date: 2026-10-09 18:23 UTC + +Read `PORT_STATUS.md`, `README.md`, and `references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `picklebuf_raw()` declaration family was already resolved in the preserved local state. A forced-fresh MSVC600/Wine source-list probe reconfirmed the current first blocker as C2059 at `Objects/picklebufobject.c(142)` on `.bf_getbuffer`; the distinct designated initializer at line 211 was also reported and left untouched. Native Hermes coding delegation failed before startup because the Anthropic package is unavailable and lazy installs are disabled. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a121e2-95d9-7f21-96b3-6a70b3c7c102`) performed strict TDD. It added a focused C89 compile/runtime test that extracts the exact `PyBufferProcs` initializer, checks the actual header field order and both semantic mappings, and observed expected RED before the source edit. Only the two initializer entries were changed to positional initializers with field-name comments; `bf_getbuffer` and `bf_releasebuffer` mappings are preserved. The existing `picklebuf_raw()` test and all other pre-existing dirty/untracked files were byte-identical after the lane. + +Exact verification: + +- Pre-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-20261009T1610" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/reprobe-20261009T1610.log 2>&1` — actual probe exit 2; summary `total=103 compiled=102 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First blocker C2059 at `picklebufobject.c(142)`; separate C2059 at `(211)`. Captured in `build/cron-20261009Tcurrent/reprobe-20261009T1610.log`. +- TDD RED: `python3 scripts/vc6-picklebuf-buffer-c89.test.py cpython/Objects/picklebufobject.c` — exit 1 before production edit; expected host C90 diagnostics on both designated entries (`ISO C90 forbids specifying subobject to initialize`). GREEN: same command after edit — exit 0, `picklebuf_as_buffer C89 compile and both semantic field mappings: PASS`. +- Applicable picklebuf regressions: `python3 scripts/vc6-picklebuf-buffer-c89.test.py cpython/Objects/picklebufobject.c && python3 scripts/vc6-picklebuf-raw-c89.test.py cpython/Objects/picklebufobject.c` — exit 0; raw regression reports five validation/allocation-order cases passed. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261009Tcurrent/runtime-post-20261009T1620" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261009Tcurrent/probe-post-picklebuf-buffer.log 2>&1` — actual probe exit 2; summary remains `total=103 compiled=102 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/picklebufobject.c` compile past the changed initializer. Previous line-142 C2059 is gone; first remaining blocker is C2059 at line 211 (`PyPickleBuffer_Type` designated initializer), intentionally untouched. Capture: `build/cron-20261009Tcurrent/probe-post-picklebuf-buffer.log`. +- `git -C cpython diff --check -- Objects/picklebufobject.c` and `git diff --check -- scripts/vc6-picklebuf-buffer-c89.test.py` — exit 0. CPython exact tag/commit unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/picklebufobject.c` (only the two `picklebuf_as_buffer` entries), new `scripts/vc6-picklebuf-buffer-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed interpreter port. Next: force-fresh probe before edits, then isolate only the remaining first blocker, `PyPickleBuffer_Type` designated initialization at line 211, in a separate TDD slice. Do not claim port completion. + +--- +## Latest run (`set_table_resize()` C89 local declaration; frontier advances) + +Date: 2026-10-10 UTC + +Read this status, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier was freshly forced-reprobed before editing. `_blake2/blake2s_impl.c` and `Objects/rangeobject.c` compiled; first stable blocker was `Objects/setobject.c(244)` C2143 at the late initialized `size_t newsize`, followed by C2065 `newsize` at line 245. A focused coding-subagent dispatch was attempted as required but failed before startup because the Anthropic package is unavailable and lazy installs are disabled. No child changes occurred. Implemented one narrow test-first slice locally: added a regression asserting that `newsize` is declared in the function declaration block and initialized at its original location after the assertion, then ran it RED before changing production. Moved only the declaration to the entry declarations and retained initialization/evaluation order. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T071759Z-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T071759Z-reprobe/probe.log 2>&1` — actual probe exit 2; `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` and `Objects/rangeobject.c` compiled. First stable errors: C2143 at `setobject.c(244)`, C2065 `newsize` at `(245)`. Capture: `build/cron-20261010T071759Z-reprobe/probe.log`. +- Coding subagent — failed before startup: missing `anthropic` package; lazy installs disabled. No child edits. +- TDD RED: `python3 scripts/vc6-setobject-table-resize-c89.test.py cpython/Objects/setobject.c` before source edit — exit 1, expected assertion that `newsize` must be declared without initializer in the declaration block. +- Focused GREEN: same command after edit — exit 0, `set_table_resize C89 declaration and sizing order: PASS`. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T072321Z-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T072321Z-post/probe.log 2>&1` — actual probe exit 2; `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` and `Objects/setobject.c` compiled. The prior line-244/245 diagnostics are gone. First stable blocker advances within `setobject.c` to C2275/C2065 at line 779 (`PyObject *list`); later independent blockers remain at lines 956, 1033, 1038, 1778, 2017, 2179, and 2280. Capture: `build/cron-20261010T072321Z-post/probe.log`. +- Scoped `git -C cpython diff --check -- Objects/setobject.c` and outer `git diff --check -- scripts/vc6-setobject-table-resize-c89.test.py` — exit 0. Exact nested CPython tag/commit verified unchanged. + +Files changed by this slice: `cpython/Objects/setobject.c` (only declaration/assignment split in `set_table_resize()`), new `scripts/vc6-setobject-table-resize-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next: forced-fresh probe before any further edit; if unchanged frontier state, isolate only the first blocker at `setobject.c(779)` using a focused TDD slice. Do not claim port completion. + +--- +## Latest run (set iterator frontier confirmed; coding lane unavailable) + +Date: 2026-10-10 09:28 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Initial worktree inventory showed 36 outer and 126 nested dirty/untracked paths; all were left intact. + +The previously recorded setobject frontier was stale and was freshly checked with forced-fresh MSVC600/Wine compilation. `_blake2/blake2s_impl.c` compiled. The first stable blocker is `setiter_reduce()` in `Objects/setobject.c`: C2275 at line 779 for late `PyObject *list`, followed by C2065 `list` at the same line. Later independent diagnostics at lines 956, 1033, 1038, 1778, 2017, 2179, and 2280 are untouched. One focused coding-subagent lane was attempted for only this first blocker with preservation/TDD constraints, but failed before startup because the Anthropic package is unavailable and lazy installs are disabled. No production or test source was changed; no RED/GREEN or regression pass is claimed. This run is diagnostics-only. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T092855Z/runtime-reprobe" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T092855Z/probe-before.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: C2275 `PyObject` and C2065 `list` at `Objects/setobject.c(779)`. Capture: `build/cron-20261010T092855Z/probe-before.log`. +- Focused coding-agent delegation for exactly `setiter_reduce()`'s first C89 declaration blocker — failed before child startup: required `anthropic` package missing; lazy installs disabled. No child edits were applied. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. No source/test regression suite was run because no source or test changed. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next: retry one focused TDD implementation lane for the confirmed `setiter_reduce()` declaration at line 779 when a coding provider can start; keep `PySequence_List()` after the incref and preserve the decref/error order. Then force-fresh probe again. Do not claim port completion. + +--- +## Latest run (`frozenset_vectorcall()` C89 declarations; frontier advances) + +Date: 2026-10-10 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved all pre-existing dirty and untracked content; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. The recorded `_blake2/blake2s_impl.c` compilation was freshly confirmed, but the recorded next frontier required reprobe: the actual first stable blocker was `frozenset_vectorcall()` in `Objects/setobject.c`, not the separately compiled blake2 source. + +One focused Codex CLI lane (`codex-cli 0.153.4`, one-shot `codex exec`, workspace-write) followed strict TDD. The Hermes delegation API attempt did not start because the Anthropic package is absent and lazy installation is disabled; the available Codex CLI was used instead. The lane added `scripts/vc6-setobject-frozenset-vectorcall-c89.test.py`, observed expected RED before production changes (the entry declaration assertion failed), and then moved only `nargs` and `iterable` declarations to the function's initial declaration block. Their assignments remain at their original evaluation points after the keyword and positional checks. The lane's exact-source snapshot check reports all pre-existing dirty/untracked contents, both indexes, and `PORT_STATUS.md` unchanged apart from the authorized source/test edits. No unrelated source was changed. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T155705Z-blake2-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261010T155705Z-blake2-frontier/probe-before.log 2>&1` — actual probe exit 2; `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: C2275/C2146/C2065 at `Objects/setobject.c(1034)` for `nargs`; then C2275/C2065 at `(1039)` for `iterable`. Further distinct diagnostics at lines 1779, 2018, 2180, and 2281. Capture: `build/cron-20261010T155705Z-blake2-frontier/probe-before.log`. +- TDD RED/GREEN and applicable regressions, as run by the coding lane: new `vc6-setobject-frozenset-vectorcall-c89.test.py` failed before edit with the expected initial-declaration assertion, then passed after edit. All four `scripts/*setobject*.test.py` tests passed; output explicitly includes `setiter_reduce` (8 cases) and `set_table_resize` PASS. `git diff --check` and `git -C cpython diff --check` passed. No regression failure reported. +- Post-change forced-fresh command: same probe with `XDG_RUNTIME_DIR="$PWD/build/cron-20261010T155705Z-blake2-frontier/runtime-post"`, output to `build/cron-20261010T155705Z-blake2-frontier/probe-after.log` — actual probe exit 2; `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The former diagnostics at lines 1034/1039 are gone and `setobject.c` compiles past `frozenset_vectorcall()`. First remaining stable errors advance to C2275/C2065/C2100 at `Objects/setobject.c(1782)` (`key`/`it`); later blockers remain at lines 2021, 2183, and 2284. Capture: `build/cron-20261010T155705Z-blake2-frontier/probe-after.log`. +- CPython tag/commit checked before change and unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. + +Files changed by this slice: `cpython/Objects/setobject.c` (only declarations/assignments in `frozenset_vectorcall()`), new `scripts/vc6-setobject-frozenset-vectorcall-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed port. Next: force-fresh reprobe before editing; if confirmed, isolate only the first current `setobject.c` blocker around line 1782 in a separate TDD slice. + +--- +## Latest run (`set_vectorcall()` `nargs` declaration hoisted; frontier advances) + +Date: 2026-10-11 00:33 UTC + +Read `PORT_STATUS.md`, `README.md`, and attempted the applicable CPython Win9x/MSVC6 reference before acting. The reference path available from the invoked skill is absent in this runtime; other searches did not find a local copy. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded first blocker was freshly force-reprobed before editing using MSVC600 under Wine. `_blake2/blake2s_impl.c` compiled. The first stable diagnostics were at `Objects/setobject.c(2024)` in `set_vectorcall()`: C2275 `Py_ssize_t`, C2146 before `nargs`, and C2065 `nargs`. Later independent designated-initializer blockers were at lines 2186 and 2287. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write, ephemeral; session `01a12865-1451-7021-a43e-bdb0c99330fc`) followed strict TDD. The new regression failed before production edits with the expected assertion that `nargs` must be declared before executable statements. The only production change hoisted `Py_ssize_t nargs;` into the function declaration block and moved its `PyVectorcall_NARGS(nargsf)` initializer to an assignment at its original evaluation point after keyword validation. Argument checks, branches, and return behavior are unchanged. Hash verification confirmed all 165 other pre-existing dirty/untracked files remained byte-for-byte unchanged; exact comparison confirmed only this intended slice in the already-dirty `setobject.c`. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T003257Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T003257Z/probe-before.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: C2275/C2146/C2065 at `Objects/setobject.c(2024)`; later C2059 at lines 2186 and 2287. Capture: `build/cron-20261011T003257Z/probe-before.log`. +- TDD RED: `python3 scripts/vc6-setobject-vectorcall-c89.test.py cpython/Objects/setobject.c` before production edit — exit 1 with the expected missing-entry-declaration assertion. +- Focused GREEN and applicable setobject regressions: `python3 scripts/vc6-setobject-vectorcall-c89.test.py cpython/Objects/setobject.c` and `for test in scripts/*setobject*.test.py; do echo "$ python3 $test cpython/Objects/setobject.c"; python3 "$test" cpython/Objects/setobject.c || exit; done` — exit 0. All six setobject scripts passed, including the new declaration/evaluation-order check and existing frozenset-vectorcall, issuperset, make-new-set, setiter-reduce, and table-resize checks. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T003257Z/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T003257Z/probe-post.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. No diagnostics remain at `set_vectorcall()` line 2024. The next designated-initializer blockers are at `setobject.c` lines 2188 and 2289. Capture: `build/cron-20261011T003257Z/probe-post.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-setobject-vectorcall-c89.test.py` and `git -C cpython diff --check -- Objects/setobject.c` — exit 0. `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/setobject.c` (only `set_vectorcall()` declaration/assignment split), new `scripts/vc6-setobject-vectorcall-c89.test.py`, and this status entry. Compiler-probe progress only, not a completed port. Next: force-fresh probe before editing; if unchanged, handle only the first designated initializer at `setobject.c(2188)` in its own TDD slice. Do not combine the later initializer at 2289 or claim a completed port. + +--- +## Latest run (fresh frontier confirmed; focused coding lane unavailable) + +Date: 2026-10-11 02:49 UTC + +Read `PORT_STATUS.md`, `README.md`, and the applicable CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded compiler frontier was force-reprobed under MSVC600/Wine before any edits. `_blake2/blake2s_impl.c` compiled. The logged `setobject.c(2024)` declaration blocker is no longer present; the actual first stable errors are C2059 at `Objects/setobject.c(2188)` on the designated `.tp_vectorcall` initializer in `PySet_Type`, followed by a distinct C2059 at line 2289 in `PyFrozenSet_Type`. A single focused coding-agent delegation was attempted for only the first initializer and strict TDD, but failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. Therefore this run is diagnostics-only: no source/test implementation was attempted, no TDD RED/GREEN is claimed, and no production source was modified. Existing local changes remain preserved. + +Exact verification: + +- Forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T-current/probe.log 2>&1` — actual probe exit 2; summary `total=105 compiled=104 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostic C2059 at `Objects/setobject.c(2188)`; separate C2059 at `(2289)`. Capture: `build/cron-20261011T-current/probe.log`. +- Compiler banner independently captured using the MSVC600 environment batch under Wine: `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86` (VC6.0). +- Focused coding-agent delegation for only the line-2188 `PySet_Type` initializer failed before child startup: missing `anthropic` package; lazy installs disabled. No child edits occurred. +- All six applicable existing `scripts/vc6-setobject-*.test.py` regressions were run against `cpython/Objects/setobject.c`; each exited 0: frozenset vectorcall, issuperset, make-new-set, setiter-reduce, table-resize, and set-vectorcall. +- `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/setobject.c` — exit 0. Exact baseline tag/commit verified unchanged. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next: retry one focused TDD coding lane for only the `PySet_Type` positional initializer at line 2188 when a coding provider can start; leave the separate `PyFrozenSet_Type` initializer at line 2289 untouched. Do not claim port completion. + +--- +## Latest run (fresh frontier confirmed; coding delegation unavailable) + +Date: 2026-10-11 07:02 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference (`/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`) before acting. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior status frontier was force-reprobed. `_blake2/blake2module.c`, `_blake2/blake2b_impl.c`, and `_blake2/blake2s_impl.c` all compiled, so the suggested `_blake2/blake2s_impl.c` sequence is no longer current. The first stable diagnostics are in `Objects/sliceobject.c` inside `PySlice_New()`: late declarations of `PyInterpreterState *interp` and `PySliceObject *obj` at lines 126-127 produce C2275/C2065, with subsequent member-access errors cascading. Separate later declaration families at lines 600, 608, and 617 remain out of scope. One focused coding-subagent attempt was made for only the first family, but failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. Therefore this run is diagnostics-only: no TDD RED/GREEN, production edit, or regression pass is claimed. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T070252Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T070252Z/probe.log 2>&1` — actual probe exit 2; summary `total=106 compiled=105 cached=0 skipped=0`. The three `_blake2` sources compiled. First diagnostics: `sliceobject.c(126)` C2275 `PyInterpreterState` / C2065 `interp`, `sliceobject.c(127)` C2275 `PySliceObject` / C2065 `obj`, then cascading C2223 errors at 128-130; additional distinct late-declaration errors remain at 141, 143, 145, 600, 608, and 617. Capture: `build/cron-20261011T070252Z/probe.log`. +- Focused coding delegation for only the `PySlice_New()` declaration family — failed before child startup: Anthropic package required; lazy installs disabled. No child edits occurred. +- Search for existing focused tests (`vc6-sliceobject-*.test.py`) found none. No source/test changes were made, so no regression suite was run. +- `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/sliceobject.c` — exit 0. Exact baseline tag/commit verified unchanged. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. This is compiler-probe progress, not a completed port. Next: retry one focused TDD coding lane for only the two `PySlice_New()` declarations, preserving initializer evaluation at the original locations; do not edit the later sliceobject families or the already compiling `_blake2` sources. + +--- +## Latest run (`slice_richcompare()` C89 declaration family; compiler frontier advances) + +Date: 2026-10-11 11:30 UTC + +Read `PORT_STATUS.md`, `README.md`, and attempted to read the CPython Win9x/MSVC6 reference before acting; the reference path available in prior records was not present in this runtime. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` state was force-reprobed before any source edit. `_blake2/blake2s_impl.c` compiled; the actual first blocker was `Objects/sliceobject.c:slice_richcompare()`, with VC6 C2275/C2065 diagnostics on late `PyObject *t1`, `*t2`, and `*res` declarations at lines 602, 610, and 619, followed by cascades. One focused Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral; session `01a12ab5-68eb-7a70-a4b1-adfe714bd9be`) followed TDD. It added a focused regression first and observed the expected RED (`t1`, `t2`, `res` not declared at function entry), then hoisted only those declarations into the function declaration block. The tuple allocations, rich comparison assignment, error checks, decrefs, and return remain in their original order. The lane reported a focused compile attempt blocked before compilation by Wine's `/run/user/1000/wine/.../lock` read-only error; a parent-run forced-fresh full source-list probe subsequently compiled the edited sliceobject and advanced to `Objects/structseq.c`. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011Tcurrent-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011Tcurrent-reprobe/probe.log 2>&1` — actual probe exit 2; summary `total=106 compiled=105 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics were C2275/C2065 at `sliceobject.c(602)` (`PyObject`/`t1`), `(610)` (`PyObject`/`t2`), and `(619)` (`PyObject`/`res`), with later cascades. Capture: `build/cron-20261011Tcurrent-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-sliceobject-richcompare-c89.test.py` — exit 1 before production edit, expected assertion `slice_richcompare must declare t1, t2, res without initializers at function entry`. +- Focused GREEN and all directly applicable sliceobject regression tests: `python3 scripts/vc6-sliceobject-richcompare-c89.test.py cpython/Objects/sliceobject.c` and `for test in scripts/vc6-sliceobject-*.test.py; do python3 "$test" cpython/Objects/sliceobject.c || exit $?; done` — exit 0; both the richcompare and existing `PySlice_New()` regression pass. Scoped nested/outer `git diff --check` — exit 0. +- Post-change forced-fresh source-list probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011Tcurrent-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011Tcurrent-post/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` and `Objects/sliceobject.c` compile; all prior sliceobject diagnostics are gone. First blocker advances to `Objects/structseq.c`, starting at line 58 (C2275/C2146/C2065 for `Py_ssize_t vsize`), with additional declaration and initializer errors later in that file. Capture: `build/cron-20261011Tcurrent-post/probe.log`. +- Exact tag/commit verified unchanged. No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/sliceobject.c` (only declarations/assignment forms in `slice_richcompare()`), new `scripts/vc6-sliceobject-richcompare-c89.test.py`, and this status entry. Compiler-probe progress only; no port completion is claimed. Next: force-fresh probe before editing and isolate only the first current `Objects/structseq.c` defect family with a focused TDD test. Do not infer the full file's fix from the initial diagnostic or conflate source compilation with linking/runtime acceptance. + +--- +## Latest run (`PyStructSequence_New()` C89 declaration; frontier advances) + +Date: 2026-10-11 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previously recorded compiler frontier was not the current one: a forced-fresh VC6/Wine source-list probe confirmed `_blake2/blake2s_impl.c` compiles and the first blocker was `Objects/structseq.c(58)`, a late initialized declaration of `vsize` in `PyStructSequence_New()`. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a12b2e-4aca-76f2-878d-6937ceb60c69`, workspace-write/ephemeral) followed strict TDD. New regression `scripts/vc6-structseq-new-c89.test.py` failed before production edits as expected, asserting `vsize` must be declared at function entry. The only production edit declares `Py_ssize_t vsize;` before the early return and moves `VISIBLE_SIZE_TP(type)` evaluation to an assignment at its original point after the `size < 0` check. Allocation, error handling, and subsequent behavior were not changed. No pre-existing `vc6-structseq-*.test.py` existed. Later diagnostics in `structseq.c` were left untouched. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T133200Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T133200Z/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics at `structseq.c(58)`: C2275 `Py_ssize_t`, C2146 before `vsize`, C2065 `vsize`; cascades followed. Capture: `build/cron-20261011T133200Z/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-new-c89.test.py cpython/Objects/structseq.c` before production edit — exit 1, expected assertion `vsize must be declared without initializer before the size < 0 check`. +- GREEN: same command after source edit — exit 0, `PyStructSequence_New C89 declaration and size lookup order: PASS`. No existing `vc6-structseq-*.test.py` regressions were present. Scoped `git diff --check -- PORT_STATUS.md scripts/vc6-structseq-new-c89.test.py` and `git -C cpython diff --check -- Objects/structseq.c` — exit 0. +- Post-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T133200Z-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T133200Z-post/probe-post.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled; the previous diagnostics at line 58 are gone. First remaining diagnostics are now `structseq.c(95)` C2143 and cascades at `(96-97)` in `structseq_traverse()`. Further independent diagnostics remain at lines 109, 262, 271-294, 402-413, 582-589, and 616-618. Capture: `build/cron-20261011T133200Z-post/probe-post.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/structseq.c` (only the `PyStructSequence_New()` declaration/assignment split), new `scripts/vc6-structseq-new-c89.test.py`, and this status entry. Compiler-probe progress only, not a completed port. Next: force-fresh probe before editing; if unchanged, isolate only the `structseq_traverse()` declaration blocker at line 95 in its own TDD slice. + +--- +## Latest run (`structseq_traverse()` C89 declaration; frontier advances) + +Date: 2026-10-11 UTC + +Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython work. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2`/slice frontier was force-reprobed first. The recorded state was stale: `_blake2/blake2s_impl.c` compiled, but the actual first blocker was `Objects/structseq.c` mixed declarations in `structseq_traverse()` and later functions. One focused Codex CLI lane (`codex-cli 0.153.4`, session `01a12ba6-de06-75e3-97dc-77f68c3f7ab7`, workspace-write/ephemeral) followed TDD for only the first declaration family. New test `scripts/vc6-structseq-traverse-c89.test.py` failed before production edits with the expected assertion on the late `Py_ssize_t i, size;`; the sole production edit hoisted that declaration before the heap-type visit. `size = REAL_SIZE(obj)` remains after the visit, preserving lookup/evaluation order. No other source location was edited. Snapshot verification confirmed all 173 pre-existing changed/untracked files remained byte-identical. + +Exact verification: + +- Before-change forced-fresh: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011-blake2-check/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011-blake2-check/probe.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics in `structseq.c` were C2143 at line 95, then C2065 `size`/`i` at lines 96-97 and cascades; separate later declaration/initializer families followed. Capture: `build/cron-20261011-blake2-check/probe.log`. +- TDD RED: `python3 scripts/vc6-structseq-traverse-c89.test.py` — exit 1 before source edit, expected assertion that `i` and `size` must precede the heap-type check. GREEN: same command after edit — exit 0. +- Applicable regressions: `python3 scripts/vc6-structseq-traverse-c89.test.py` and `python3 scripts/vc6-structseq-new-c89.test.py` — exit 0. Outer and scoped nested `git diff --check` — exit 0. +- Post-change forced-fresh probe: same command with output `build/cron-20261011-blake2-check/probe-post.log` and runtime `build/cron-20261011-blake2-check/post-runtime` — actual probe exit 2; `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The former traverse diagnostics at lines 95-97 are gone; the first remaining diagnostic family advances to `structseq_dealloc()` at line 109 (C2275 `PyTypeObject`, C2065 `tp`), followed by distinct later mixed-declaration and initializer errors. No separate compiler banner captured. +- The existing Codex snapshot comparison reported 173 pre-existing modified/untracked files preserved. Exact baseline tag/commit unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/structseq.c` (one declaration move), new `scripts/vc6-structseq-traverse-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed port. Next: force-fresh probe before editing and isolate only the first current `structseq_dealloc()` declaration family at line 109 in its own TDD slice. + +--- +## Latest run (fresh probe moved first blocker to `structseq.c`; coding lane unavailable) + +Date: 2026-10-11 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing outer and detached CPython modifications; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `sliceobject.c` frontier was stale. A forced-fresh MSVC600/Wine source-list probe compiled `_blake2/blake2s_impl.c` and reported first stable errors in `Objects/structseq.c(109)`: C2275 (`PyTypeObject` illegal use as expression) and C2065 (`tp` undeclared) for the initialized declaration in `structseq_dealloc()`. Separate later mixed-declaration diagnostics occur at line 262; they are not part of this attempted first slice and remain untouched. A single focused coding-agent delegation was attempted, as required for implementation, but failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. Thus this run is diagnostics-only: no TDD RED/GREEN cycle, source edit, or new regression is claimed. Existing applicable `structseq` regressions passed. + +Exact verification: + +- `XDG_RUNTIME_DIR="$PWD/build/cron-20261011-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011-current/probe-before.log 2>&1` — probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostics: `Objects/structseq.c(109)` C2275 `PyTypeObject` and C2065 `tp`; later separate C2143/C2065/C2059 diagnostics at line 262. Capture: `build/cron-20261011-current/probe-before.log`. +- Exact baseline checks: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. `codex --version` → `codex-cli 0.153.4`; `codex login status` → logged in using ChatGPT. The focused `delegate_task` coding lane failed before startup with the Anthropic package/lazy-install error. No child edits occurred. +- `python3 scripts/vc6-structseq-new-c89.test.py cpython/Objects/structseq.c` — exit 0, `PyStructSequence_New C89 declaration and size lookup order: PASS`. +- `python3 scripts/vc6-structseq-traverse-c89.test.py cpython/Objects/structseq.c` — exit 0, `structseq_traverse C89 declarations and visit/size lookup order: PASS`. +- `git diff --check -- PORT_STATUS.md` and `git -C cpython diff --check -- Objects/structseq.c` — exit 0. No standalone MSVC compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next: use a working focused coding lane (Codex CLI is installed/authenticated, but the available native delegate backend failed before startup) for a strict TDD test of only the `structseq_dealloc()` declaration at line 109; preserve `tp = Py_TYPE(obj)` after `PyObject_GC_UnTrack(obj)`. Then rerun the forced-fresh probe to establish the next actual frontier. Do not touch the independent line-262 blocker in that slice. + +--- +## Latest run (`structseq_repr()` C89 loop declaration; frontier advances) + +Date: 2026-10-11 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The previous compiler frontier was re-probed with a forced-fresh MSVC600/Wine source-list run before editing. `_blake2/blake2s_impl.c` compiled. The first blocker was the C99 loop initializer declaration `for (Py_ssize_t i=0; ...)` in `Objects/structseq.c:structseq_repr()` at line 263. One focused Codex CLI lane (`codex-cli 0.153.4`, one-shot `codex exec`, workspace-write/ephemeral; logged in with ChatGPT) followed strict TDD. Its new `scripts/vc6-structseq-repr-c89.test.py` failed before the production edit with the expected assertion that the VC6-incompatible loop declaration remained. The only production change declares `Py_ssize_t i;` in the function declaration block and changes the loop initializer to `i=0`; the loop still starts after writing `(`, performs the same per-iteration visible-size check, and increments once per iteration. No other function or defect family changed. Independent scope verification confirmed the exact intended two-line production delta, with pre-existing changes and `PORT_STATUS.md` preserved by the lane. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T221407Z-fresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T221407Z-fresh/probe-before.log 2>&1` — actual probe exit 2; summary `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostic family at `structseq.c(263)` was C2143 declaration/statement syntax diagnostics and C2065 `i`. Capture: `build/cron-20261011T221407Z-fresh/probe-before.log`. +- TDD RED: `python3 scripts/vc6-structseq-repr-c89.test.py` before production edit — exit 1, expected assertion `structseq_repr: VC6 rejects the C99 loop initializer declaration; declare i in the function declaration block`. +- TDD GREEN and all applicable structseq regressions: `python3 scripts/vc6-structseq-repr-c89.test.py` and `for test in scripts/vc6-structseq-*.test.py; do python3 "$test" || exit $?; done` — exit 0. All four structseq tests passed (`dealloc`, `new`, `repr`, `traverse`). `git -C cpython diff --check -- Objects/structseq.c` and `git diff --check -- scripts/vc6-structseq-repr-c89.test.py` — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261011T221407Z-fresh/runtime-post" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261011T221407Z-fresh/probe-after.log 2>&1` — actual probe exit 2; summary remains `total=107 compiled=106 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. The former `structseq_repr()` line-263 diagnostics are gone; first remaining diagnostics now begin at line 273 (`C2143` before `const`, then C2065 `name_utf8`), followed by distinct late declaration families at lines 280, 294, 296, and 404 and designated initializer errors at 584-591. Capture: `build/cron-20261011T221407Z-fresh/probe-after.log`. +- CPython tag/commit remain unchanged. No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/structseq.c` (only `structseq_repr()` loop variable declaration/initializer), new `scripts/vc6-structseq-repr-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed port. Next: force-fresh probe before editing and isolate only the first actual remaining `structseq_repr()` declaration family at line 273; do not combine later declarations or initializer errors. + +--- +## Latest run (`tuple_alloc()` C89 declaration; frontier advances) + +Date: 2026-10-12 15:53 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded tupleobject frontier was freshly force-reprobed. `_blake2/blake2s_impl.c` compiled. The current first errors were `Objects/tupleobject.c(43)` C2275 (`PyTupleObject`) and C2065 (`op`) on `PyTupleObject *op = maybe_freelist_pop(size);`. A native coding-subagent attempt failed before startup because `anthropic` is unavailable and lazy installs are disabled; the installed Codex CLI was then used as one focused coding lane. Strict TDD added `scripts/vc6-tupleobject-alloc-c89.test.py`; RED failed before the source edit on the expected declaration-placement assertion. The only source change declares `op` in `tuple_alloc()`'s initial declaration block and leaves `op = maybe_freelist_pop(size)` at its original point after size validation and the debug assertion. Regression verifies the full function's validation, freelist, overflow, allocation, error, and return order. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p build/cron-current-evidence/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-current-evidence/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-evidence/probe.log 2>&1` — probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `tupleobject.c(43)` C2275/C2065. Full log: `build/cron-current-evidence/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-alloc-c89.test.py cpython/Objects/tupleobject.c` before the production change — exit 1, expected assertion that `op` must be declared before the size-check statement. GREEN: same command after edit — exit 0, `tuple_alloc C89 declaration and validation/allocation order: PASS`. +- Applicable tupleobject C89 regression set: one script exists, the new `vc6-tupleobject-alloc-c89.test.py`; focused run exited 0. `git -C cpython diff --check -- Objects/tupleobject.c` exited 0. Snapshot/hash verification confirmed previously dirty/untracked content, `PORT_STATUS.md` before its entry, and probe log were unchanged by the coding lane; the nested source has exactly the intended declaration/assignment split. +- Post-change forced-fresh command: `mkdir -p build/cron-current-evidence-post/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-current-evidence-post/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-evidence-post/probe.log 2>&1` — probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Prior `tuple_alloc()` diagnostics at line 43 are gone. The next first stable diagnostics are in `tupleobject.c(80)` (C2143/C2065 for the loop declaration/`i`); later distinct diagnostics include lines 167, 207, and 219. These remain untouched. Full capture: `build/cron-current-evidence-post/probe.log`. +- CPython tag and commit verified unchanged. No standalone compiler banner, linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (one declaration/assignment split), new `scripts/vc6-tupleobject-alloc-c89.test.py`, and this status entry. This is compiler-probe progress only, not a completed port. Next frontier: force-fresh probe before edits; if unchanged, isolate only the current `tupleobject.c` loop-declaration blocker at line 80 in its own TDD slice. Do not conflate compiler progress with linked or target-runtime acceptance. + +--- +## Latest run (PyTuple_Pack frontier confirmed; coding lane unavailable) + +Date: 2026-10-12 UTC + +Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains at exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded tupleobject frontier was freshly force-reprobed before any edits and remains current. `_blake2/blake2s_impl.c` compiled. First stable MSVC600/Wine diagnostics are in `Objects/tupleobject.c:PyTuple_Pack()` at line 168: C2275 (`PyTupleObject`) and C2065 (`result`) on the late initialized declaration, followed by cascading errors at lines 169 and 173. Later, distinct tupleobject blockers remain untouched. One focused coding-subagent delegation was attempted for this single defect family and strict TDD, but failed before child startup because the Hermes runtime requires the unavailable `anthropic` package and lazy installs are disabled. This run is therefore diagnostics-only: no production/test edits, TDD RED/GREEN cycle, or implementation regression is claimed. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Forced-fresh probe: `mkdir -p build/cron-20261012T-current/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-current/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261012T-current/probe-before.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `tupleobject.c(168)` C2275/C2065 (`PyTupleObject` / `result`); subsequent cascades at `(169)` and `(173)`. Later independent diagnostics start at `(208)`. Full capture: `build/cron-20261012T-current/probe-before.log`. +- Focused coding-agent delegation for only the line-168 declaration — failed before startup: `anthropic` package unavailable; lazy installs disabled. No child edits or tests occurred. +- Existing applicable tupleobject tests: `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; ...; done` — exit 0. `vc6-tupleobject-alloc-c89.test.py` and `vc6-tupleobject-new-c89.test.py` each exited 0. `git -C cpython diff --check -- Objects/tupleobject.c` — exit 0. +- No standalone compiler banner, linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no port completion is claimed. Next: retry one focused TDD coding lane for the confirmed `PyTuple_Pack()` declaration at line 168 when a coding agent can start; leave subsequent tupleobject blockers untouched. + +--- +## Latest run (`PyTuple_Pack()` C89 declaration; frontier advances) + +Date: 2026-10-12 22:27 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all existing root and detached CPython work. No reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused coding-agent lane (Codex CLI 0.153.4, OpenAI, workspace-write/ephemeral; session `01a13235-805c-7691-8bb8-6f0ffaab93a8`) was used after the fresh probe confirmed the prior `PyTuple_Pack()` line-168 declaration blocker. TDD RED: new `scripts/vc6-tupleobject-pack-c89.test.py` failed before the source edit with the intended assertion that `result` must be declared in the function declaration block. The sole production change declares `PyTupleObject *result` with the other locals and changes the later initialized declaration to `result = tuple_alloc(n);` immediately after `va_start`. Allocation timing, empty-tuple path, error cleanup, item/refcount operations, GC tracking, and return order are preserved. Snapshot/hash comparison verified all 183 other pre-existing dirty/untracked files unchanged. + +Exact verification: + +- Before-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T221714Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; `_blake2/blake2s_impl.c` compiled; first diagnostics were `tupleobject.c(168)` C2275/C2065 (`PyTupleObject`/`result`), followed by C2223 at line 173. Full capture: `build/cron-20261012T221714Z/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-pack-c89.test.py` — exit 1 on the expected declaration-placement assertion, before production edit. +- GREEN and applicable regressions: `python3 scripts/vc6-tupleobject-alloc-c89.test.py`, `python3 scripts/vc6-tupleobject-new-c89.test.py`, and `python3 scripts/vc6-tupleobject-pack-c89.test.py` — all exit 0. Scoped `git diff --check` commands for `cpython/Objects/tupleobject.c` and the new test — exit 0. +- Post-change forced-fresh probe: `XDG_RUNTIME_DIR="$PWD/build/cron-20261012T-after-pack/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-168/173 diagnostics are gone. The first stable blocker is now `tupleobject.c(209)` C2143 followed by `(210)` C2065 `i` in the next function; later tupleobject blockers remain untouched. Full capture: `build/cron-20261012T-after-pack/probe.log`. +- Exact CPython tag and commit verified unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `PyTuple_Pack()` declaration split), new `scripts/vc6-tupleobject-pack-c89.test.py`, and this status entry. Next: force-fresh probe before changes, then address only the newly confirmed first blocker at `tupleobject.c(209-210)` in a separate TDD slice. No completed port is claimed. + +--- +## Latest run (forced-fresh tupleobject frontier; coding lane unavailable) + +Date: 2026-10-13 00:33 UTC + +Read `PORT_STATUS.md`, `README.md`, and the applicable CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. The CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier was not current, so it was force-reprobed before any implementation work. `_blake2/blake2s_impl.c` compiled successfully; the first stable blocker is now `Objects/tupleobject.c:tupledealloc()` at line 209, where `Py_ssize_t i = Py_SIZE(op);` follows statements and triggers C2143, followed by C2065 for `i` at line 210. The earlier status-described `PyTuple_Pack()` frontier is stale. One focused coding-agent delegation was attempted, but failed before child startup because the Anthropic package is unavailable and lazy installs are disabled. Therefore this run was diagnostics-only: no production/test changes and no TDD RED/GREEN implementation cycle are claimed. The tracked-state change is this status entry only; the compiler log is an untracked diagnostic artifact under `build/`. + +Exact verification: + +- Forced-fresh command: `mkdir -p build/cron-20261013T-current-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261013T-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261013T-current-reprobe/probe.log 2>&1` — compiler/probe exit 2; `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `tupleobject.c(209)` C2143 and `(210)` C2065 `i`. Full capture: `build/cron-20261013T-current-reprobe/probe.log`. +- Focused coding-agent delegation — failed before child startup: missing `anthropic` package; lazy installs disabled. No child edits occurred. +- Existing applicable regressions `python3 scripts/vc6-tupleobject-alloc-c89.test.py`, `python3 scripts/vc6-tupleobject-new-c89.test.py`, and `python3 scripts/vc6-tupleobject-pack-c89.test.py` — all exit 0. They validate existing separate tupleobject slices; no new test or implementation was made for `tupledealloc()`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. The outer checkout already had many unrelated dirty/untracked changes; all were preserved. +- No standalone compiler banner was captured. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only, not a completed port. + +Files changed by this run: `PORT_STATUS.md` only. Next frontier: when the focused coding-agent provider can start, address only the confirmed `tupledealloc()` declaration family at line 209 with TDD, preserving the assignment's existing point after `Py_TRASHCAN_BEGIN`; then rerun its focused VC6 probe and applicable regressions. Leave later tupleobject diagnostics untouched. + +--- +## Latest run (`_PyTuple_FromArraySteal()` allocation declaration; frontier advances) + +Date: 2026-10-13 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all prior work; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine probe confirmed `_PyTuple_FromArraySteal()`'s late initialized `PyTupleObject *tuple` declaration at line 408 as the current first blocker. One focused Codex CLI coding lane (`codex-cli 0.153.4`, workspace-write/ephemeral) added a focused C89/order regression and changed only this declaration family: `tuple` is declared at function entry, with `tuple = tuple_alloc(n);` retained after the `n == 0` return. Later loop-index and `dst` declarations, refcount and error behavior remain untouched. No unrelated existing content was overwritten. The lane's exact TDD RED output was not independently captured in this run record; only post-change test success is claimed here. + +Exact verification: + +- Forced-fresh command: `mkdir -p build/cron-20261014-blake2-frontier/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-blake2-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-blake2-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics are `tupleobject.c(408)` C2275/C2065 (`PyTupleObject`/`tuple`); distinct subsequent loop and destination declarations remain. Capture: `build/cron-20261014-blake2-frontier/probe.log`. +- `python3 scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py` — exit 0; reports declaration placement and evaluation/refcount/error order PASS. All six `scripts/vc6-tupleobject-*.test.py` scripts — exit 0. `git -C cpython diff --check -- Objects/tupleobject.c` — exit 0. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (one declaration/assignment split), new `scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py`, and `PORT_STATUS.md`. Next frontier: force-fresh probe first; if unchanged, isolate the `_PyTuple_FromArraySteal()` loop index declaration at line 410 in a separate TDD slice, leaving `dst` and all later tupleobject blockers distinct. + +--- +## Latest run (`_PyTuple_FromArraySteal()` destination declaration; frontier advances) + +Date: 2026-10-14 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine probe confirmed the recorded `dst` declaration blocker in `_PyTuple_FromArraySteal()`. One focused Codex CLI lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a13750-9c4c-70e1-acb0-fb6882e3546e`) used strict TDD. The newly added focused test failed before production edit with the expected assertion that function-scope `PyObject **dst` must precede statements. The sole production change hoists `PyObject **dst;` into the function declaration block and retains `dst = tuple->ob_item;` immediately after the allocation-success check. The subsequent loop index and item declarations remain untouched. Two pre-existing focused expectation tests necessarily encoded the former declaration layout; they were narrowly updated to expect the hoisted declaration and assignment. Other tupleobject code/tests were preserved. The lane reported hash-snapshot verification; independent source-diff inspection confirms only the intended declaration/assignment transformation. No commit or publication was performed. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261014-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-reprobe/probe.log 2>&1` — compiler/probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors were `tupleobject.c(417)` C2275/C2065/C2100 for `PyObject`/`dst`; separate loop diagnostics followed. A log-filter helper then exited 1 due to its own Python slicing-expression bug; the saved probe log is valid and the diagnostics were recovered from it. Capture: `build/cron-20261014-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py` before source edit — exit 1 on the expected function-scope declaration assertion. GREEN after the edit — exit 0. +- Applicable regressions: `set -e; python3 scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py; python3 scripts/vc6-tupleobject-from-array-steal-c89.test.py; python3 scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py; for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test"; done` — exit 0; all eight tupleobject scripts passed. An initial loop without `set -e` revealed that the two old focused expectations failed on stale layout assertions; those directly related expectations were updated and the complete suite then passed. +- Post-change forced-fresh command: `mkdir -p build/cron-20261014-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261014-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014-after/probe.log 2>&1` — compiler/probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `dst` diagnostics at line 417 are gone. First remaining blocker is the separate C99 loop-index declaration at line 419 (C2143/C2059); later tupleobject blockers remain untouched. Capture: `build/cron-20261014-after/probe.log`. +- `git -C cpython diff --check -- Objects/tupleobject.c` and outer `git diff --check` for the status/focused tests — exit 0. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution was produced. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `_PyTuple_FromArraySteal()` `dst` declaration/assignment split), new `scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py`, narrowly updated `scripts/vc6-tupleobject-from-array-steal-c89.test.py` and `scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py`, and this status entry. Next: force-fresh probe before editing; if unchanged, isolate only `_PyTuple_FromArraySteal()`'s success-path loop-index declaration at line 419 in a separate TDD slice. Do not claim port completion. + +--- +## Latest verified slice (`tuple_vectorcall()` `nargs` declaration; frontier advances) + +Date: 2026-10-14 13:15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The top-recorded `tuplerepeat()` `dest_end` frontier was force-reprobed first and confirmed fixed in the current checkout. The actual first compiler blocker was the next distinct defect family: `tuple_vectorcall()`'s late initialized `Py_ssize_t nargs` declaration at `tupleobject.c:733`. One focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a13a92-0248-7e32-9a21-722106ba2320`) followed strict TDD. New `scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py` failed before the production edit on the expected missing function-entry declaration assertion. The sole production edit declares `nargs` in the function's initial declaration block and assigns `nargs = PyVectorcall_NARGS(nargsf);` at the original point immediately after keyword validation. The argument validation and return paths are unchanged. A hash snapshot verified all pre-existing dirty/untracked files except the intended `cpython/Objects/tupleobject.c` were byte-identical during the coding lane. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261014T131503Z-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014T131503Z-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled, then `tupleobject.c(733)` reported C2275 (`Py_ssize_t` used as expression), C2146 (missing `;` before `nargs`), C2065 (`nargs` undeclared). Later distinct diagnostics included designated initializer at line 917, `index` at 1236, and C89 loops at 1257/1276. Capture: `build/cron-20261014T131503Z-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py` before production edit — exit 1 on the expected assertion that `nargs` must be in the opening declaration block. +- GREEN and applicable regression suite: focused test and `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" cpython/Objects/tupleobject.c || exit "$?"; done` — exit 0; all 12 tupleobject regression scripts pass. +- After-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261014T131503Z-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014T131503Z-frontier/probe-after.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled; former `tupleobject.c(733)` diagnostics are gone. Next tupleobject blocker is C2059 on the separate designated initializer at line 919; distinct late `index` declaration at 1238 and C89 loops at 1259/1278 remain untouched. Capture: `build/cron-20261014T131503Z-frontier/probe-after.log`. +- `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py` — exit 0. Baseline tag/commit remain unchanged. +- No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `tuple_vectorcall()` `nargs` declaration/assignment split), new `scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py`, and this status entry. Next frontier: in a separate TDD slice, force-fresh confirm and address only the `tupleobject.c:919` designated initializer; leave `index` and later C89 loop declarations separate. No completed port is claimed. + +--- +## Latest verified slice (`tuple_vectorcall()` `nargs` declaration; frontier advances) + +Date: 2026-10-14 13:15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The top-recorded `tuplerepeat()` `dest_end` frontier was force-reprobed first and confirmed fixed in the current checkout. The actual first compiler blocker was the next distinct defect family: `tuple_vectorcall()`'s late initialized `Py_ssize_t nargs` declaration at `tupleobject.c:733`. One focused Codex CLI coding lane (`codex-cli 0.153.4`, OpenAI provider, workspace-write/ephemeral; session `01a13a92-0248-7e32-9a21-722106ba2320`) followed strict TDD. New `scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py` failed before the production edit on the expected missing function-entry declaration assertion. The sole production edit declares `nargs` in the function's initial declaration block and assigns `nargs = PyVectorcall_NARGS(nargsf);` at the original point immediately after keyword validation. The argument validation and return paths are unchanged. A hash snapshot verified all pre-existing dirty/untracked files except the intended `cpython/Objects/tupleobject.c` were byte-identical during the coding lane. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261014T131503Z-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014T131503Z-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled, then `tupleobject.c(733)` reported C2275 (`Py_ssize_t` used as expression), C2146 (missing `;` before `nargs`), C2065 (`nargs` undeclared). Later distinct diagnostics included designated initializer at line 917, `index` at 1236, and C89 loops at 1257/1276. Capture: `build/cron-20261014T131503Z-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py` before production edit — exit 1 on the expected assertion that `nargs` must be in the opening declaration block. +- GREEN and applicable regression suite: focused test and `for test in scripts/vc6-tupleobject-*.test.py; do python3 "$test" cpython/Objects/tupleobject.c || exit "$?"; done` — exit 0; all 12 tupleobject regression scripts pass. +- After-change forced-fresh command: `XDG_RUNTIME_DIR="$PWD/build/cron-20261014T131503Z-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261014T131503Z-frontier/probe-after.log 2>&1` — actual probe exit 2; summary `total=108 compiled=107 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled; former `tupleobject.c(733)` diagnostics are gone. Next tupleobject blocker is C2059 on the separate designated initializer at line 919; distinct late `index` declaration at 1238 and C89 loops at 1259/1278 remain untouched. Capture: `build/cron-20261014T131503Z-frontier/probe-after.log`. +- `git -C cpython diff --check -- Objects/tupleobject.c` and `git diff --check -- scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py` — exit 0. Baseline tag/commit remain unchanged. +- No `pythoncore.dll`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/tupleobject.c` (only `tuple_vectorcall()` `nargs` declaration/assignment split), new `scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py`, and this status entry. Next frontier: in a separate TDD slice, force-fresh confirm and address only the `tupleobject.c:919` designated initializer; leave `index` and later C89 loop declarations separate. No completed port is claimed. + +--- +## Latest verified slice (`type_cache_clear()` C89 loop index; frontier advances) + +Date: 2026-10-15 UTC + +Read `PORT_STATUS.md` and `README.md` before acting. The referenced CPython-specific legacy-toolchain reference was not available as a readable file in this workspace; the invoked skill guidance was applied. Preserved all pre-existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior `_blake2/blake2s_impl.c` frontier is stale: the forced-fresh compiler probe compiled it and advanced to `Objects/typeobject.c`. The first blocker was the C99 loop-index declaration in `type_cache_clear()` at line 214. One focused authenticated Codex CLI coding lane (`codex-cli 0.153.4`, workspace-write/ephemeral; session `01a13cf7-8be8-74c3-b839-7fd408fcd96d`) used strict TDD. The new `scripts/vc6-typeobject-cache-clear-index-c89.test.py` failed before the production edit (exit 1) because `Py_ssize_t i` was not declared at function entry. The sole production change hoists that declaration and changes the loop initializer to assignment; loop bound, increment, and body order remain unchanged. `_PyType_InitCache()`'s separate loop at line 227 was not touched. The agent reported its tracked/untracked file hash snapshot remained unchanged outside these two authorized paths. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261015-frontier/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261015-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261015-frontier/probe.log 2>&1` — actual probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First errors: `typeobject.c(214)` C2143/C2065/C2059 on `for (Py_ssize_t i = 0; ...)`; next separate loop at line 227 left untouched. `_blake2/blake2s_impl.c` was not the frontier. Full capture: `build/cron-20261015-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-cache-clear-index-c89.test.py` before source edit — exit 1, expected missing function-entry declaration assertion. +- Focused GREEN and applicable regressions: `python3 scripts/vc6-typeobject-cache-clear-index-c89.test.py` — exit 0; `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit; done` — exit 0, one matching test. +- After-change forced-fresh command: `mkdir -p build/cron-20261015-frontier-after/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261015-frontier-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261015-frontier-after/probe.log 2>&1` — actual probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Former line-214 diagnostics are gone; next distinct blocker is `_PyType_InitCache()`'s separate C99 loop declaration at `typeobject.c(228)` (C2143/C2065/C2059). Full capture: `build/cron-20261015-frontier-after/probe.log`. +- Independent checks: focused/all matching typeobject tests and scoped nested/outer `git diff --check` — exit 0. Detached baseline unchanged. No linked `pythoncore.dll`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution occurred. Compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only the `type_cache_clear()` loop-index declaration/initializer split), new `scripts/vc6-typeobject-cache-clear-index-c89.test.py`, and this status entry. Next frontier: force-fresh confirm before a separate strict-TDD slice for only `_PyType_InitCache()`'s loop index. No completed port is claimed. + +--- +## Latest run (forced-fresh typeobject frontier; implementation lane unavailable) + +Date: 2026-10-15 02:42 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved the existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, publication, or patch regeneration. Baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The requested `_blake2/blake2s_impl.c` sequence was not the current frontier. The forced-fresh probe compiled `_blake2/blake2s_impl.c`; the first stable blocker remains `_PyType_InitCache()`'s separate C99 loop-index declaration at `Objects/typeobject.c:228`, following the already-fixed `type_cache_clear()` loop. One focused coding-agent delegation was attempted for this defect only, but the provider could not start because no Anthropic credentials are configured. Accordingly this run is diagnostics-only: no production or regression-test edits and no TDD cycle are claimed. Existing work remains untouched. + +Exact verification: + +- Fresh probe command: `mkdir -p build/cron-20261016-frontier-refresh/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261016-frontier-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261016-frontier-refresh/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(228)` C2143/C2065/C2059 for `for (Py_ssize_t i = 0; ...)`; the next distinct compiler errors begin at `typeobject.c(306)`. Capture: `build/cron-20261016-frontier-refresh/probe.log`. +- Coding-agent delegation for the single confirmed loop-index defect — failed before child startup: no Anthropic credentials configured. No child edits occurred. +- Existing focused regression: `python3 scripts/vc6-typeobject-cache-clear-index-c89.test.py` — exit 0 (`type_cache_clear index C89 declaration and unchanged loop body: PASS`). This tests the preceding fixed loop, not the current `_PyType_InitCache()` blocker; no new test was added. +- Baseline checks: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped nested and outer `git diff --check` — both exit 0. +- The probe did not link `pythoncore.dll`/`python.exe`, run an interpreter under Wine, or execute on Windows 98 SE. This is compiler-probe progress only. + +Files changed this run: `PORT_STATUS.md` only; diagnostic capture is under `build/cron-20261016-frontier-refresh/`. Next frontier: when an authorized coding-agent provider is available, use one strict-TDD slice for only `_PyType_InitCache()`'s loop index at line 228, then run the forced-fresh probe and applicable typeobject regressions. No completed port is claimed. + +--- +## Latest run (fresh type_mro_modified frontier; implementation lane unavailable) + +Date: 2026-10-15 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython 3.11.16 Win9x/MSVC6 reference before acting. Preserved all existing outer and detached CPython changes; no reset, clean, stash, discard, commit, push, publication, or compatibility-patch regeneration. Baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier remains current: `_blake2/blake2s_impl.c` compiled, then the first compiler diagnostic was the C89 declaration in `type_mro_modified()` at `cpython/Objects/typeobject.c(362)` (C2143, missing `;` before `type`). The later `custom_mro` diagnostic at line 365 is separate and was left untouched. One focused coding-subagent delegation was attempted for a single TDD fix but failed before child startup because no Anthropic credentials are configured. Following the delegation workflow, this run is diagnostics-only: no source/test edits or TDD RED/GREEN cycle are claimed. + +Exact verification: + +- Forced-fresh command: `mkdir -p "$TMPDIR/cp311-current-reprobe/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-current-reprobe/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic is `typeobject.c(362)` C2143. Next distinct diagnostic: `typeobject.c(365)` C2065 for `custom_mro`. Capture: `$TMPDIR/cp311-current-reprobe/probe.log`. +- Applicable regressions: `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit $?; done` — exit 0; all five typeobject scripts passed. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. +- No production or regression-test files changed this run. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only, not a completed port. + +Files changed this run: `PORT_STATUS.md` only. Next frontier: once a focused coding lane can start, use one strict-TDD slice for only the `type_mro_modified()` declaration at line 362; preserve initialization/evaluation timing and keep `custom_mro` separate. Do not claim port completion. + +--- +## Latest verified slice (`assign_version_tag()` bases declaration; frontier advances) + +Date: 2026-10-15 UTC + +Read `PORT_STATUS.md`, `README.md`, and `legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved the extensive pre-existing dirty/untracked root and detached CPython work. No reset, clean, stash, discard, commit, push, publication, or patch regeneration. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier was force-reprobed first and confirmed: `_blake2/blake2s_impl.c` compiled, then the first stable errors were `typeobject.c(407)` C2275/C2065 for late `PyObject *bases = type->tp_bases;`, followed by the separate `n` declaration and loop-index declaration. Note the prior status described line 407 as `type_mro_modified()`; source inspection established it is actually `assign_version_tag()`. One authenticated Codex CLI 0.153.4 workspace-write/ephemeral lane applied strict TDD to only the `bases` declaration: new test failed before the source edit on the expected declaration assertion, then passed after hoisting `PyObject *bases;` and assigning `bases = type->tp_bases;` at the original evaluation point. `n`, loop index, and subsequent blockers were untouched. Coding lane preservation report was independently inspected; source diff is restricted to this function's bases declaration plus earlier pre-existing changes, and PORT_STATUS.md remained unchanged during that lane. + +Exact verification: + +- Before-change forced-fresh command: `XDG_RUNTIME_DIR="$TMPDIR/cp311-frontier-cron-20261015T200131Z/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors at `typeobject.c(407)` C2275/C2065 (`PyObject`/`bases`); the next distinct declaration family was `n` at line 408. Capture: `$TMPDIR/cp311-frontier-cron-20261015T200131Z/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-mro-bases-c89.test.py` before production edit — exit 1 at the expected missing opening-declaration assertion. Focused GREEN — exit 0. +- Focused regression plus all `scripts/vc6-typeobject-*.test.py` — exit 0; all seven tests pass. `git -C cpython diff --check -- Objects/typeobject.c` and `git diff --check -- scripts/vc6-typeobject-mro-bases-c89.test.py` — exit 0. +- After-change forced-fresh command with equivalent Wine environment — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-407 `bases` diagnostics are gone. First remaining errors are the separate `Py_ssize_t n` declaration at `typeobject.c(409)` (C2275/C2146/C2065); loop-index diagnostics follow at line 410, both untouched. Capture: `$TMPDIR/cp311-frontier-after-bases-20261015T200733Z/probe.log`. +- Exact baseline tag/commit verified unchanged. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only the `assign_version_tag()` `bases` declaration/assignment split), new `scripts/vc6-typeobject-mro-bases-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then address only `assign_version_tag()`'s `n` declaration in a separate slice. No completed port is claimed. + +--- +## Latest verified slice (`mro_hierarchy()` `new_mro` C89 declaration) + +Date: 2026-10-16 05:02 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. The requested `/home/ubuntu/projects/python-win9x` checkout does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Preserved all pre-existing root and detached CPython work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `_PyType_Name()` frontier was no longer first. A forced-fresh VC6/Wine probe confirmed `_blake2/blake2s_impl.c` compiles and exposed `mro_hierarchy()`'s late initialized `PyObject *new_mro` declaration as the first blocker. The Hermes delegation provider could not start because Anthropic credentials are unavailable. The installed authenticated `codex-cli 0.153.4` performed one focused implementation lane under strict TDD. New test RED failed on the expected missing opening-block declaration before production change. The sole production change hoists `PyObject *new_mro;` and assigns `new_mro = type->tp_mro;` after the existing `res <= 0` return guard. The later `tuple` declaration and other defect families remain untouched. + +Exact verification: + +- Before-change: `mkdir -p "$TMPDIR/cp311-cron-frontier/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-cron-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-cron-frontier/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(677)` C2275 (`PyObject`) and C2065 (`new_mro`). +- TDD RED: `python3 scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py` before the source edit — exit 1 with the expected assertion that `new_mro` must be in the opening declarations. +- TDD GREEN and applicable regressions: the focused test and every `scripts/vc6-typeobject-*.test.py` — exit 0; all 11 typeobject scripts passed. +- After-change forced-fresh probe using the same command/environment, captured at `$TMPDIR/cp311-cron-after-mro-hierarchy/probe.log` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former line-677 diagnostics are gone. First current errors are `typeobject.c(680)` C2275/C2065 for the distinct later `tuple` declaration; untouched. Subsequent diagnostics include C89 declarations/loops at lines 720-725. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped `git diff --check` commands for the source, test, and status file exited 0. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred; this is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only the `mro_hierarchy()` declaration/assignment split), new `scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py`, and this status entry. Next frontier: force-fresh re-probe, then address only the `tuple` declaration if still first. Do not claim a completed port. + +--- +## Latest verified slice (`mro_hierarchy()` tuple declaration; frontier advances) + +Date: 2026-10-16 UTC + +The requested path `/home/ubuntu/projects/python-win9x` does not exist; used the actual checkout at `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the CPython 3.11.16/MSVC6 reference at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved the extensive pre-existing dirty/untracked state. No reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_PyType_Name()` state was stale. Fresh forced probes confirmed it already passes and the actual first blocker was the late `PyObject *tuple` declaration in `mro_hierarchy()` at `typeobject.c(680)`. Hermes delegation could not start because its configured Anthropic provider lacks credentials; the installed authenticated Codex CLI (`codex-cli 0.153.4`) performed one focused implementation lane under strict TDD. New `scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py` failed before production editing (exit 1) on the intended opening-declaration assertion. The only production change hoists `PyObject *tuple;` to the opening declaration block. Both original branch assignments and their evaluation timing remain unchanged. Updated the directly applicable existing `scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py` expectation. No other defect family changed. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p "$TMPDIR/cron-20261016-refresh/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cron-20261016-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cron-20261016-refresh/probe.log" 2>&1` — actual exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostic family: `typeobject.c(680)` C2275 (`PyObject`) and C2065 (`tuple`). Capture: `$TMPDIR/cron-20261016-refresh/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py` before production edit — exit 1, expected assertion `PyObject *tuple; must be in the opening declarations`. +- GREEN and applicable regressions: focused test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test"; result=$?; printf '%s: exit %s\\n' "$test" "$result"; if [ "$result" -ne 0 ]; then exit "$result"; fi; done` — exit 0; all 12 typeobject scripts passed. +- After-change forced-fresh command: `mkdir -p "$TMPDIR/cron-20261016-after-mro-tuple/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cron-20261016-after-mro-tuple/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cron-20261016-after-mro-tuple/probe.log" 2>&1` — actual exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former line-680 diagnostics are gone. Next first blocker: `typeobject.c(720)` C2275/C2146/C2065 on the `Py_ssize_t n` declaration, followed by the C89 loop declaration at line 721; untouched. Capture: `$TMPDIR/cron-20261016-after-mro-tuple/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Scoped nested source and outer focused-test `git diff --check` — exit 0. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py`, focused expectation update in `scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py`, and this status entry. Next frontier: force-fresh confirm, then isolate only `mro_hierarchy()`'s `Py_ssize_t n` declaration at line 720. Do not conflate compiler-probe progress with a linked or target-running interpreter; no completed port is claimed. + +--- +## Latest verified slice (`type_set_bases()` n C89 declaration; frontier advances) + +Date: 2026-10-16 UTC + +Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before acting. The requested `/home/ubuntu/projects/python-win9x` path is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Preserved all existing outer and detached CPython work; no reset, clean, stash, discard, commit, push, or publication. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced VC6/Wine probe confirmed the current first blocker was `type_set_bases()` at `Objects/typeobject.c:757`: late `Py_ssize_t n = PyTuple_GET_SIZE(new_bases);`. `_blake2/blake2s_impl.c` compiled. One focused coding-agent lane used Codex CLI 0.153.4 (workspace-write, ephemeral), since Hermes' configured delegation provider could not start without Anthropic credentials. Strict TDD added `scripts/vc6-typeobject-set-bases-n-c89.test.py`; its first run failed as expected because `n` was not declared in the opening block. A flawed initial test assertion counted a later rollback reassignment and failed after the implementation; the assertion was narrowed to the `PyTuple_GET_SIZE(new_bases)` read, and RED was repeated against the preserved pre-edit source, exiting 1 as expected. The only production change hoists `Py_ssize_t n;` and leaves `n = PyTuple_GET_SIZE(new_bases);` after all argument validation and the empty-tuple check. The C89 loop index and all later declarations remain unchanged. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p "$TMPDIR/cron-recheck-frontier/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cron-recheck-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cron-recheck-frontier/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable errors were `typeobject.c(757)` C2275/C2146/C2065 on `n`, followed by C89 loop declaration diagnostics at line 758. `_blake2/blake2s_impl.c` compiled. Log: `$TMPDIR/cron-recheck-frontier/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-n-c89.test.py` on unchanged production source — exit 1, expected opening-declaration assertion. After correcting the overbroad rollback-count assertion, repeated RED against original source — exit 1 on the same expected missing declaration. GREEN: focused script — exit 0. +- Applicable tests: `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all 14 typeobject tests passed. +- After-change forced-fresh command: `mkdir -p "$TMPDIR/cron-after-set-bases-n/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cron-after-set-bases-n/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cron-after-set-bases-n/probe.log" 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Former line-757 errors are gone; first blocker advances to `typeobject.c(760)` C2143/C2065/C2059 for the separate C89 loop-index declaration. Log: `$TMPDIR/cron-after-set-bases-n/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Nested and outer focused `git diff --check` — exit 0. The coding lane's preservation hash check passed; unrelated dirty/untracked files are preserved. +- No pythoncore/python.exe link, Wine interpreter execution, or Windows 98 SE execution occurred. Compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c` (only `type_set_bases()`'s `n` declaration/assignment split), new `scripts/vc6-typeobject-set-bases-n-c89.test.py`, and this status entry. Next frontier: force-fresh confirmation, then address only the `type_set_bases()` loop-index declaration at line 760 if it remains first. No completed port is claimed. + +--- +## Previous verified slice (`mro_hierarchy()` subclass-loop C89 declarations; frontier advances) + +Date: 2026-10-16 UTC + +Read `PORT_STATUS.md`, `README.md`, and searched both active-profile and project locations for the specified legacy-toolchain reference; that reference file is absent. Preserved all existing outer and detached CPython changes. No reset, clean, stash, discard, commit, push, publication, or patch regeneration. The requested path `/home/ubuntu/projects/python-win9x` does not exist in this runtime; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The current frontier was confirmed with a forced-fresh MSVC600/Wine probe before implementation: `_blake2/blake2s_impl.c` compiled, then VC6 reported C2275/C2146/C2065 at `Objects/typeobject.c(720)` on `Py_ssize_t n`, and C2143/C2065/C2059 at line 721 on `Py_ssize_t i`. One focused Hermes coding-subagent attempt failed before startup because Anthropic credentials are unavailable. The installed authenticated Codex CLI (`codex-cli 0.153.4`, workspace-write/ephemeral) performed the single scoped implementation lane under strict TDD. Its new regression failed before production changes as expected; the two existing `mro_hierarchy` test expectations also failed against the unchanged loop because they encode its prior tail. The lane updated only those directly applicable expectations and hoisted `n`/`i` to the opening declaration block. `n = PyList_GET_SIZE(subclasses)` remains after the NULL check; `i = 0` remains at the original loop initializer. Iteration, recursion, cleanup, and return ordering are unchanged. No other production defect family was edited. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-run-current-retry/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-run-current-retry/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-run-current-retry/probe.log" 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors at lines 720-721 as above. The immediately preceding identical attempt with a different fresh runtime timed out at 300s (exit 124); rerun completed. Log: `$TMPDIR/cp311-run-current-retry/probe.log`. +- TDD RED: new `python3 scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py` before production edit — exit 1 at expected opening declaration assertion. Existing `mro-hierarchy-new-mro` and `mro-hierarchy-tuple` tests also failed (exit 1) against unchanged source because their expected function prefix included the pre-slice loop syntax. +- GREEN/regressions: focused new test and all 13 `scripts/vc6-typeobject-*.test.py` scripts — exit 0; each reports PASS. The two prior expectations were narrowly updated to include the opening `n`/`i` declarations. +- After-change forced-fresh command: `mkdir -p "$TMPDIR/cp311-run-after/runtime"; XDG_RUNTIME_DIR="$TMPDIR/cp311-run-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > "$TMPDIR/cp311-run-after/probe.log" 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `mro_hierarchy()` line 720-721 diagnostics are gone. New first blocker is `typeobject.c(757)` C2275/C2146/C2065 on late `Py_ssize_t n`, followed at line 758 by the C89 loop-index errors in the next function. Full log: `$TMPDIR/cp311-run-after/probe.log`. +- `git -C cpython diff --check -- Objects/typeobject.c` and outer `git diff --check -- scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py` — exit 0. Nested HEAD/tag remain exact. Porcelain comparison confirms no previously existing status entries changed; the sole new outer untracked path from this slice is the focused new regression test. +- No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py`; focused expected-prefix updates in `scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py` and `scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py`; and this status entry. Next frontier: force-fresh confirm, then isolate only the `typeobject.c(757)` declaration defect family if still first. No completed port is claimed. + +--- +## Latest verified slice (`type_set_bases()` `new_base` C89 declaration; frontier advances) + +Date: 2026-10-16 18:34 UTC + +Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. The requested `/home/ubuntu/projects/python-win9x` path does not exist; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Preserved pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The status-recorded `type_set_bases()` `new_base` blocker was force-reprobed before editing and confirmed; `_blake2/blake2s_impl.c` compiled. One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, OpenAI, workspace-write/ephemeral) implemented only this C89 declaration slice using TDD. New `scripts/vc6-typeobject-set-bases-new-base-c89.test.py` failed before the production edit with the intended missing opening-declaration assertion. The source change hoists `PyTypeObject *new_base;` beside the function's existing `n`/`i` declarations and retains `new_base = best_base(new_bases);` at the original evaluation point after the validation loop. No behavior or evaluation order was intentionally changed. The directly applicable base/index/n test expectations were updated to reflect the hoist; unrelated dirty/untracked paths were preserved. A pre-edit hash snapshot covered 217 dirty/untracked files; the agent verified all 216 other pre-existing files unchanged, and Hermes reviewed the exact source diff. + +Exact verification: + +- Before-change forced-fresh command: `mkdir -p build/cron-current-recheck/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-recheck/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-recheck/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(791)` C2275/C2065 for the late `PyTypeObject *new_base`. Capture: `build/cron-current-recheck/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-new-base-c89.test.py` before production edit — exit 1 with the expected assertion that `new_base` is missing from the opening declaration block. GREEN: same test after the source edit — exit 0. +- First applicable regression run found three existing set-bases tests encoded the old declaration layout (exit 1); updated only those narrow expectations. Final `set -e; for test in scripts/vc6-typeobject-*.test.py; do python3 "$test"; done` — exit 0; all 17 typeobject tests pass. Scoped `git diff --check` for source and four relevant tests — exit 0. +- After-change forced-fresh probe: `mkdir -p build/cron-current-after-new-base/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-after-new-base/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-after-new-base/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The prior `typeobject.c(791)` new_base errors are gone. First current diagnostic group advances to the distinct late `PyObject *old_bases` declaration at `typeobject.c(800)` (C2275/C2065); left untouched. Capture: `build/cron-current-after-new-base/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred: compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-set-bases-new-base-c89.test.py`, updated `scripts/vc6-typeobject-set-bases-base-c89.test.py`, `scripts/vc6-typeobject-set-bases-index-c89.test.py`, `scripts/vc6-typeobject-set-bases-n-c89.test.py`, and this status entry. Next frontier: force-fresh re-probe before handling only the `type_set_bases()` `old_bases` declaration if it remains first. No completed port is claimed. + +--- +## Latest run (fresh frontier probe; implementation lane unavailable) + +Date: 2026-10-16 UTC + +Read `PORT_STATUS.md`, `README.md`, and the applicable `python-3-win9x-msvc6.md` reference before acting. The requested `/home/ubuntu/projects/python-win9x` path does not exist; used the existing checkout at `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. The workspace already contains extensive tracked/untracked modifications; preserved them. No reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The older recorded `_blake2/blake2s_impl.c` frontier is not current. A forced-fresh probe compiled that source, then first stopped at `typeobject.c(800)` on the late `PyObject *old_bases` declaration in `type_set_bases()`. The requested single focused coding-subagent implementation lane could not start: provider `anthropic` has no credentials (available providers are openrouter, nous, zai, kimi-coding, minimax). Per scope/TDD and preservation constraints, this run made no speculative production or regression-test edits; this is diagnostics-only. + +Exact verification: + +- `mkdir -p build/cron-20261016-refresh/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261016-refresh/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261016-refresh/probe.log 2>&1` — probe exit 2. Summary: `total=109 compiled=108 cached=0 skipped=0`. Log confirms `compile: cpython/Modules/_blake2/blake2s_impl.c` and `blake2s_impl.c`; first compiler diagnostics are `typeobject.c(800)` C2275 (`PyObject`) and C2065 (`old_bases`). Capture: `build/cron-20261016-refresh/probe.log`. +- `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- No production source or test file was changed by this run. No pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. This is compiler-probe evidence only. + +Files changed by this run: `PORT_STATUS.md` only. Next frontier: in a later run with a usable focused coding lane, TDD-test and address only the `old_bases` declaration at `typeobject.c(800)` after a fresh probe; leave later `old_base`, `temp`, and other defect families separate. + +--- +## Latest verified slice (`type_set_bases()` `old_base` declaration; frontier advances) + +Date: 2026-10-17 UTC + +Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read this status, `README.md`, and the profile CPython Win9x/MSVC6 reference before acting. Preserved all existing dirty/untracked work. No reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `old_base` frontier was force-fresh confirmed before edits. A delegated Hermes implementation lane could not start because Anthropic credentials are unavailable; authenticated `codex-cli 0.153.4` performed one focused coding lane. Under TDD, new `scripts/vc6-typeobject-set-bases-old-base-c89.test.py` failed first as expected, requiring `old_base` in the opening declaration block. The only production change adds `PyTypeObject *old_base;` beside existing `type_set_bases()` locals; its assignment and evaluation/control-flow order remain unchanged. Three directly affected declaration-order test expectations were updated to recognize this additional local. + +Exact verification: + +- Before-edit forced-fresh probe: `mkdir -p build/cron-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-reprobe/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; first stable error `typeobject.c(803)` C2065 `old_base`, followed by distinct `temp` and `res` errors. +- TDD RED: `python3 scripts/vc6-typeobject-set-bases-old-base-c89.test.py` before production edit — exit 1 on expected missing opening declaration. +- GREEN/regressions: focused test and all `scripts/vc6-typeobject-*.test.py` — final run exit 0, 19/19 passed. Existing expectation adjustments were limited to the three set-bases tests. +- After-edit forced-fresh command: `mkdir -p build/cron-old-base-after/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-old-base-after/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-old-base-after/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; prior `old_base` diagnostic is gone. Next diagnostics advance to `typeobject.c(809)` C2065 `temp`, then `res` at line 820; neither changed. Full capture: `build/cron-old-base-after/probe.log`. +- Scoped `git diff --check` for nested production and outer tests exited 0. Baseline tag and commit verified unchanged. +- No pythoncore/python.exe link, Wine interpreter run, or real Windows 98 SE execution occurred. Compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-set-bases-old-base-c89.test.py`; updated declaration expectations in `scripts/vc6-typeobject-set-bases-index-c89.test.py`, `scripts/vc6-typeobject-set-bases-n-c89.test.py`, and `scripts/vc6-typeobject-set-bases-new-base-c89.test.py`; and this status entry. Next frontier: force-fresh re-probe, then isolate only `temp` if still first. No completed port is claimed. + +--- +## Latest verified slice (`lookup_maybe_method()` descriptor getter declaration; frontier advances) + +Date: 2026-10-18 UTC + +Used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before changing anything. Preserved the pre-existing extensive outer and detached CPython work; no reset, clean, stash, discard, commit, push, or publication. The previous `_blake2` frontier note was stale: a forced-fresh probe confirmed `_blake2/blake2s_impl.c` compiles, and the first stable blocker is in `lookup_maybe_method()` at `typeobject.c(1636)`. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, OpenAI; `--sandbox workspace-write --ephemeral`) followed strict TDD and preserved local changes. The new `scripts/vc6-typeobject-lookup-maybe-method-c89.test.py` failed against unchanged source (exit 1) on the intended missing opening-block declaration assertion. The sole production edit hoists `descrgetfunc f;` into `lookup_maybe_method()`'s opening declarations and changes its initialization to assignment immediately after the existing `*unbound = 0;`. Getter evaluation, branches, refcount behavior, and control flow remain in their original order. A source diff comparison confirmed this is the only `typeobject.c` delta from the pre-lane snapshot. `PORT_STATUS.md` was unchanged by the coding lane until this report was added. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh command: `mkdir -p build/cron-20261018-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-current-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; first diagnostic `typeobject.c(1636)` C2275 for `descrgetfunc`, followed by declaration cascades. `_blake2/blake2s_impl.c` compiled. Capture: `build/cron-20261018-current-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-lookup-maybe-method-c89.test.py` before production edit — exit 1, expected `lookup_maybe_method: f must be declared in the opening declaration block (C89)`; exact source comparison against pre-edit snapshot passed. +- GREEN: same focused test after edit — exit 0, `lookup_maybe_method descriptor getter C89 declaration and unchanged evaluation/control flow: PASS`. +- Applicable regression suite: all 30 `scripts/vc6-typeobject-*.test.py` scripts — exit 0, zero failures. Detailed output: `/tmp/vc6-typeobject-lookup-maybe-method-tests.log`. +- After-change forced-fresh command: `mkdir -p build/cron-20261018-after-lookup-maybe-method/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-lookup-maybe-method/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-lookup-maybe-method/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; former line-1636 diagnostic is gone. Next first stable blocker is a distinct declaration family in `vectorcall_method()` at `typeobject.c(1694)`, C2143 (followed by declaration cascades); left untouched. Capture: `build/cron-20261018-after-lookup-maybe-method/probe.log`. +- `git diff --check -- PORT_STATUS.md scripts/vc6-typeobject-lookup-maybe-method-c89.test.py` and `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. Baseline tag/commit unchanged. +- Compiler-probe progress only. No `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution occurred. No completed port is claimed. + +Files changed by this slice: `cpython/Objects/typeobject.c` (one declaration/assignment split); new `scripts/vc6-typeobject-lookup-maybe-method-c89.test.py`; and this `PORT_STATUS.md` entry. Next frontier: force-fresh confirm, then isolate only the first `vectorcall_method()` declaration blocker at line 1694. Keep later errors separate and do not conflate compiler-probe progress with a linked or running interpreter. + +--- +## Latest verified slice (`mro_implementation()` `bases` declaration; frontier advances) + +Date: 2026-10-18 UTC + +Used existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`; requested `/home/ubuntu/projects/python-win9x` does not exist. Read this status, `README.md`, and the active-profile CPython 3.11.16/MSVC6 reference at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved all pre-existing dirty/untracked work. No reset, clean, stash, discard, commit, push, or publication. CPython baseline remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` sequence was force-fresh reprobed and had advanced. Before edits, the actual first stable blocker was `mro_implementation()`'s late initialized `PyObject *bases` at `typeobject.c(1956)`, C2275/C2065; later `n`, loop-index and other errors were left untouched. Anthropic-backed delegation was unavailable (missing credentials). One focused authenticated Codex CLI 0.153.4 lane performed the implementation under strict TDD. New regression `scripts/vc6-typeobject-mro-implementation-bases-c89.test.py` failed on unchanged production source (exit 1, expected missing opening declaration assertion). The only production edit hoisted `PyObject *bases;` to the opening declaration block and retained `bases = type->tp_bases;` immediately after the original readiness guard, preserving read timing. The lane verified source-only delta and all snapshotted pre-existing dirty/untracked files unchanged. + +Exact verification: + +- Baseline: `git -C cpython describe --tags --exact-match HEAD` → `v3.11.16`; `git -C cpython rev-parse HEAD` → `41388c9cb160d0886d5ca00d2e6c8782608a4549`. +- Before-change forced-fresh probe: `mkdir -p build/cron-20261018-reprobe/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261018-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First diagnostics: `typeobject.c(1956)` C2275/C2065 for `bases`. Capture: `build/cron-20261018-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-mro-implementation-bases-c89.test.py` before production edit — exit 1, `AssertionError: mro_implementation: PyObject *bases; must be in the opening declarations`. GREEN: same command after edit — exit 0, `mro_implementation bases C89 declaration and guarded read timing: PASS`. +- Applicable regressions: `bash -o pipefail -c 'for test in scripts/vc6-typeobject-*.test.py; do printf "COMMAND: python3 %s\\n" "$test"; python3 "$test" || exit $?; done' | tee /tmp/mro-implementation-bases-tdd/typeobject-tests.log` — exit 0; all 33 scripts passed. +- After-change forced-fresh probe: `mkdir -p build/cron-20261018-after-mro-bases/runtime && XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-mro-bases/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-mro-bases/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former `bases` diagnostics are gone. First current diagnostic family is `typeobject.c(1958)` C2275/C2146/C2065 for the separate `Py_ssize_t n` declaration, followed by C89 loop-index errors at line 1959; neither changed. Capture: `build/cron-20261018-after-mro-bases/probe.log`. +- No `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution occurred. This is compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-mro-implementation-bases-c89.test.py`, and this status record. Next frontier: force-fresh confirm the `mro_implementation()` `Py_ssize_t n` declaration and address only that defect family. No completed port is claimed. + +--- +## MRO implementation `n` declaration slice (frontier advances) + +Date: 2026-10-18 UTC. Existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x` was used because requested `/home/ubuntu/projects/python-win9x` does not exist. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all existing outer and nested dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh MSVC600/Wine probe confirmed the recorded first family was stale in naming, but current at `mro_implementation()` line 1958: C2275/C2146/C2065 on late `Py_ssize_t n`. `_blake2/blake2s_impl.c` compiled. One focused Codex CLI lane (`codex-cli 0.153.4`, authenticated OpenAI, workspace-write/ephemeral) performed strict TDD. New `scripts/vc6-typeobject-mro-implementation-n-c89.test.py` failed before the source edit (exit 1, expected opening-declaration assertion); after minimal change, focused test and all 34 `scripts/vc6-typeobject-*.test.py` scripts passed (exit 0). The only production change hoists `Py_ssize_t n;` into the function declaration block and changes the later initialized declaration to `n = PyTuple_GET_SIZE(bases);` at its original point. `i` and later defect families were not changed. The existing `mro-implementation-bases` test expectation was updated only to account for the new declaration and assignment. + +Exact evidence: +- Before probe: `mkdir -p build/cron-20261018-blake-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-blake-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-blake-reprobe/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; first errors at `typeobject.c(1958)` C2275/C2146/C2065 for `n`, followed by separate `i` errors at line 1959. Capture: `build/cron-20261018-blake-reprobe/probe.log`. +- TDD RED: `python3 scripts/vc6-typeobject-mro-implementation-n-c89.test.py` before production edit — exit 1, expected missing declaration assertion. +- GREEN/regressions: focused test and `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" || exit "$?"; done` — exit 0; all 34 passed. +- After probe: `mkdir -p build/cron-20261018-after-mro-n/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261018-after-mro-n/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261018-after-mro-n/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; all former `n` errors cleared. First remaining diagnostic is the separate C99 loop index `i` at `typeobject.c(1960)` (C2143/C2065/C2059 cascade); untouched. Capture: `build/cron-20261018-after-mro-n/probe.log`. +- `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. Complete source delta was independently compared against the pre-edit snapshot; only the `n` declaration/assignment split is present. No pythoncore/python.exe link, Wine interpreter execution, or Windows 98 SE execution occurred; compiler-probe progress only. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-mro-implementation-n-c89.test.py`, adjusted expected prefix in `scripts/vc6-typeobject-mro-implementation-bases-c89.test.py`, and this entry. Next frontier: force-fresh confirm then handle only the separate loop index `i` in `mro_implementation()`. No completed port is claimed. + +--- +## Diagnostics-only: current typeobject frontier confirmed; coding lane unavailable + +Date: 2026-10-19 UTC. The user-specified checkout `/home/ubuntu/projects/python-win9x` is absent; used the existing checkout `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the active-profile legacy-toolchain reference `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing modified and untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier remains current: a forced-fresh VC6/Wine probe compiled `_blake2/blake2s_impl.c` and confirmed first stable diagnostics at `Objects/typeobject.c(2072)` for late `PyTypeObject *base` (C2275/C2065), followed by dependent C2223 at 2078. Thus the old `_blake2` sequence is not the current blocker. Before acting, attempted the required one focused coding delegation; provider startup failed because Anthropic credentials are unavailable. No external coding CLI fallback was used; this run therefore made diagnostics-only progress and did not edit production or test code. + +Exact verification: +- Forced-fresh probe: `mkdir -p build/cron-20261019-verify-frontier/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-verify-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-verify-frontier/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors: `typeobject.c(2072)` C2275/C2065 (`PyTypeObject`/`base`), then C2223 at 2078. Capture: `build/cron-20261019-verify-frontier/probe.log`. +- Applicable regression suite: `for test in scripts/vc6-typeobject-*.test.py; do python3 "$test" >/dev/null || exit 1; done` — exit 0; all 40 tests passed. +- `git -C cpython describe --tags --exact-match HEAD` and `git -C cpython rev-parse HEAD` verified baseline above; `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. + +Files changed this run: `PORT_STATUS.md` only. No `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred; compiler-probe progress only. Next narrow frontier: when a coding lane is available, use strict TDD to fix only the `typeobject.c(2072)` `base` declaration family, then rerun the forced-fresh probe and applicable regressions. No completed port is claimed. + +--- +## Diagnostics-only: stale `_blake2` frontier; current blocker is `type_new_copy_slots()` + +Date: 2026-10-19 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing tracked modifications and untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh VC6/Wine re-probe command: `mkdir -p build/cron-20261019-blake2-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-blake2-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-blake2-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The existing modified `_blake2/blake2s_impl.c` was compiled successfully (object path logged at line 74); its nested diff was not altered. The recorded `_blake2` frontier is therefore stale. First stable errors now occur in `cpython/Objects/typeobject.c` at line 2630: C2275 (`Py_ssize_t` illegal use as expression), C2146 (missing `;` before `j`), and C2065 (`j` undeclared); line 2631 has cascading loop-index errors involving `i`. Full capture: `build/cron-20261019-blake2-reprobe/probe.log`. + +No implementation or regression-test edit was made: this run establishes a different actual frontier, so the requested `_blake2/blake2s_impl.c` defect sequence was not touched. Compiler probe only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution. Files changed this run: this status record only; probe log under `build/cron-20261019-blake2-reprobe/`. Next step: one focused strict-TDD slice for the line-2630 `type_new_copy_slots()` C89 declaration family after fresh confirmation; keep the separate line-2631 loop-index defect untouched. No completed port is claimed. + +--- +## `type_new_copy_slots()` C89 declaration slice (frontier advances) + +Date: 2026-10-19 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile `python-3-win9x-msvc6.md` reference before work. Preserved all pre-existing dirty/untracked work. No reset, clean, stash, discard, commit, push, or publication. CPython baseline is tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced VC6/Wine probe command: `mkdir -p build/cron-20261019-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-current-reprobe/probe.log 2>&1` — exit 2; `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First errors were at `typeobject.c(2630)` C2275/C2146/C2065 on `Py_ssize_t j`, plus C2143/C2065 loop-index diagnostics at 2631. Capture: `build/cron-20261019-current-reprobe/probe.log`. + +One focused Codex CLI coding lane (`codex-cli 0.153.4`, workspace-write/ephemeral; Hermes delegation provider unavailable for missing Anthropic credentials) followed strict TDD. Added `scripts/vc6-typeobject-type-new-copy-slots-c89.test.py` first; against unchanged production source it failed as expected (RED exit 1: opening C89 declarations missing), and a `cmp` confirmed source unchanged. Minimal edit in `cpython/Objects/typeobject.c` moves only local declarations `j`, `i`, `r`, and `tuple` in `type_new_copy_slots()` to legal C89 positions, preserving assignment/evaluation timing and control flow. Focused regression passed (exit 0); all 44 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Preservation verification showed all previously dirty/untracked files unchanged apart from the intended nested source and added test. + +After-change forced-fresh command: `mkdir -p build/cron-20261019-after-copy-slots/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261019-after-copy-slots/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261019-after-copy-slots/probe.log 2>&1` — exit 2; same `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. The line-2630 and 2631 diagnostics are gone. First remaining diagnostics now occur at `typeobject.c(2698)` C2143/C2065 for a distinct C99 loop-index declaration in `type_new_slots_bases()`; later declarations remain untouched. Capture: `build/cron-20261019-after-copy-slots/probe.log`. Nested and outer `git diff --check` both exited 0. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Files changed: nested `cpython/Objects/typeobject.c`, new focused regression, and this status entry. Next frontier: force-fresh confirm and isolate only the line-2698 loop-index family. No completed port is claimed. + +--- +## `type_new_slots_bases()` `base` C89 declaration slice (frontier advances) + +Date: 2026-10-20 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile `python-3-win9x-msvc6.md` reference before acting. Preserved all existing local work. No reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded frontier was force-fresh confirmed. Before-change command: `mkdir -p build/cron-20261020-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261020-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261020-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics: `typeobject.c(2705)` C2143 on late `PyTypeObject *base`, followed by C2065 `base` at 2708 and consequent C2223 at 2708/2713. Capture: `build/cron-20261020-reprobe/probe.log`. + +The configured Hermes coding delegation provider was unavailable (Anthropic credentials missing); one authenticated Codex CLI lane (`codex-cli 0.153.4`, `gpt-6-astra`, workspace-write/ephemeral) performed the focused implementation. New `scripts/vc6-typeobject-type-new-slots-bases-base-c89.test.py` was run against byte-identical production source and failed as expected (RED exit 1: opening declaration assertion). The single production change declares `PyTypeObject *base;` after `obj` and before the skip condition, then assigns `base = _PyType_CAST(obj);` at the original point after the primary-base skip. This preserves retrieval, skip, and cast evaluation order. The child snapshot confirmed all 245 other pre-existing dirty/untracked files, including prior `typeobject.c` content outside this delta and this status file, remained byte-identical. + +Verification: focused regression after the edit — exit 0. All 46 `scripts/vc6-typeobject-*.test.py` scripts — exit 0. `git diff --check -- scripts/vc6-typeobject-type-new-slots-bases-base-c89.test.py` and `git -C cpython diff --check -- Objects/typeobject.c` — exit 0. After-change forced-fresh command: `mkdir -p build/cron-20261020-after-slots-base/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261020-after-slots-base/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261020-after-slots-base/probe.log 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former diagnostics at 2705/2708/2713 are gone. First current diagnostic advances to `typeobject.c(2746)` C2275/C2065 for the separate `PyObject *new_slots` declaration; left untouched. Capture: `build/cron-20261020-after-slots-base/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-slots-bases-base-c89.test.py`, and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only the `type_new_slots_impl()` line-2746 `new_slots` declaration family. No completed port is claimed. + +--- +## `type_new_set_module()` module declaration C89 slice (frontier advances) + +Date: 2026-10-21 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the legacy-toolchain CPython 3.11.16/MSVC6 reference before acting. Preserved existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. Baseline remains CPython tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change VC6/Wine probe confirmed the preceding `globals` declaration slice and identified the distinct `PyObject *module` declaration in `type_new_set_module()` as first blocker. Exact command: `mkdir -p build/cron-20261021-module-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-module-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-module-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First diagnostics: `typeobject.c(2872)` C2275 (`PyObject` illegal use as expression) and C2065 (`module` undeclared). `_blake2/blake2s_impl.c` was not listed as a failure in the captured first diagnostic group. Wine emitted a long socket-path warning for repository-local `XDG_RUNTIME_DIR`; compilation continued. Capture: `build/cron-20261021-module-reprobe/probe.log`. + +Hermes delegation was unavailable because the configured Anthropic provider has no credentials. Used the single authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral), which followed strict TDD. New `scripts/vc6-typeobject-type-new-set-module-module-c89.test.py` failed against byte-verified unchanged production source (RED exit 1, expected opening-declaration assertion). The minimal source change declares `PyObject *module;` with the opening locals and converts the later initialized declaration to assignment exactly at its prior lookup point. The directly affected globals regression was narrowly updated to expect the new declaration while retaining ordering checks. Focused tests passed; all 50 `scripts/vc6-typeobject-*.test.py` regressions passed (exit 0). A full workspace snapshot check confirmed only those two tests and `cpython/Objects/typeobject.c` changed during implementation; pre-existing paths remained byte-identical. Outer `git diff --check` and nested `git -C cpython diff --check -- Objects/typeobject.c` exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261021-after-module/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261021-after-module/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261021-after-module/probe.log 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former `typeobject.c(2872)` diagnostics are gone. First remaining diagnostic family advances to `typeobject.c(2937)` C2143 on the distinct `const char *doc_str` declaration, with C2065 `doc_str` consequence at 2938; left untouched. Capture: `build/cron-20261021-after-module/probe.log`. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-set-module-module-c89.test.py`, narrowly adjusted `scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py`, and this status entry. Next frontier: force-fresh confirm and isolate only the `type_new_set_doc()` `doc_str` declaration family. No completed port is claimed. + +--- +## Re-probe: current frontier is `type_new_classmethod()` (diagnostics only) + +Date: 2026-10-25 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the installed legacy-toolchain reference at `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Existing work remains preserved; no reset, clean, stash, discard, commit, push, or publication. CPython remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded prior frontier was stale: forced-fresh probe command `mkdir -p build/cron-current-frontier/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-current-frontier/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-current-frontier/probe.log 2>&1` returned exit 2. Summary: `total=109 compiled=108 cached=0 skipped=0`. The initial `_blake2/blake2s_impl.c` sequence compiled; first stable errors now occur at `cpython/Objects/typeobject.c(3001)`: C2275 (`PyObject`, illegal use of type as expression) and C2065 (`method`, undeclared identifier). Capture: `build/cron-current-frontier/probe.log`. `cpython/Modules/_blake2/blake2s_impl.c` already contains local changes in the existing dirty checkout; none were altered by this run. + +Delegation prerequisite check found `/home/ubuntu/.local/bin/codex` and `/usr/bin/wine`, but no `MSVC600/VC98/bin/VCVARS32.BAT` at the expected path. The focused coding subagent could not start: delegation provider `anthropic` has no credentials. Accordingly no implementation/test slice was attempted. This is diagnostics-only; no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution is verified. Next safe step: restore/check the VC6 environment prerequisite and run a single TDD slice for the `method` declaration at the actual frontier. No completed port is claimed. + +--- +## `type_new_classmethod()` method declaration C89 slice (frontier advances) + +Date: 2026-10-24 UTC. Requested path `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before work. Preserved all existing dirty and untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline: `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh before-change probe: `mkdir -p build/cron-20261024-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable blocker: `typeobject.c(3001)` C2275 (`PyObject`) and C2065 (`method`) in `type_new_classmethod()`; later declaration families left untouched. Capture: `build/cron-20261024-reprobe/probe.log`. + +Configured Hermes delegation provider was unavailable (Anthropic credentials missing); one authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) completed the focused implementation under TDD. New `scripts/vc6-typeobject-type-new-classmethod-c89.test.py` failed against unchanged production source (RED exit 1; expected late declaration condition). The sole source change hoists `PyObject *method;` to the function's opening local declarations and turns `PyObject *method = PyClassMethod_New(func);` into `method = PyClassMethod_New(func);` at its original evaluation point. No other defect family or existing regression fixture changed. Child reported source-delta/preservation checks exit 0. + +Parent verification: `python3 scripts/vc6-typeobject-type-new-classmethod-c89.test.py` — exit 0; all 55 `scripts/vc6-typeobject-*.test.py` fixtures run individually — 55 passed, 0 failed, runner exit 0. Outer `git diff --check` and nested `git -C cpython diff --check -- Objects/typeobject.c` both exit 0. After-change forced-fresh command: `mkdir -p build/cron-20261024-after-classmethod/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-after-classmethod/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-classmethod/probe.log 2>&1` — exit 2. The former line-3001 diagnostics cleared; first remaining diagnostics are at `typeobject.c(3025)`, C2143 and cascading undeclared `i`, the distinct C99 loop-index family, left untouched. Full capture: `build/cron-20261024-after-classmethod/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-classmethod-c89.test.py`, and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: fresh probe on the next run, then isolate only the verified `typeobject.c(3025)` loop-index family. No completed port is claimed. + +--- +## `type_new_get_bases()` empty-bases `new_bases` declaration slice + +Date: 2026-10-21 UTC. The requested `/home/ubuntu/projects/python-win9x` checkout is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all prior dirty and untracked work; no reset, clean, stash, discard, commit, push, or publication. Nested CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change command: `mkdir -p build/cron-20261029-current-reprobe/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261029-current-reprobe/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The first error family was actually `type_new_get_bases()` at `typeobject.c(3286)`, C2275 `PyObject` / C2065 `new_bases`; later C99 loop diagnostics at line 3294 were separate. Although the preceding status text labeled line 3286 as `type_new_impl()`, source and fresh diagnostics identify the correct function as `type_new_get_bases()`; the isolated slice below follows the actual source. Capture: `build/cron-20261029-current-reprobe/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral; no commit) followed strict TDD. New `scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py` failed against unchanged source (RED exit 1, expected declaration-placement assertion). The only production edit hoists `PyObject *new_bases;` to the start of the existing `if (nbases == 0)` block and makes the original allocation an assignment at the same point after `ctx->base` is set. Focused GREEN passed (exit 0); all 59 `scripts/vc6-typeobject-*.test.py` tests passed independently (exit 0). Snapshot check confirmed 258 pre-existing paths byte-identical and only the expected nested `typeobject.c` source delta plus new regression; `PORT_STATUS.md` was not changed by the coding lane. Nested and outer `git diff --check` both exited 0. + +After-change forced-fresh command: `mkdir -p build/cron-20261029-after-new-bases/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261029-after-new-bases/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-after-new-bases/probe.log 2>&1` — exit 2; summary unchanged `total=109 compiled=108 cached=0 skipped=0`. Former line-3286 C2275/C2065 errors cleared. First current blocker is the distinct C99 `for (Py_ssize_t i...)` in `type_new_get_bases()` at `typeobject.c(3295)`, with dependent undeclared `i` and syntax diagnostics; untouched. Capture: `build/cron-20261029-after-new-bases/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py`, and this status entry. Compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next: fresh-confirm and isolate only the loop-index declaration at line 3295. No completed port is claimed. + +--- +## `type_new_get_bases()` loop-index C89 slice (frontier advances) + +Date: 2026-10-29 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before work. Preserved pre-existing changes; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change VC6/Wine probe: `mkdir -p build/cron-20261029-current-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-current-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable family was `typeobject.c(3295)` C2143 on the C99 `for (Py_ssize_t i...)` initializer and dependent undeclared `i` / syntax diagnostics. Capture: `build/cron-20261029-current-reprobe/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral; no commit) followed strict TDD. New `scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py` failed against unchanged production source (RED exit 1, expected opening declaration assertion); `cmp` against the pre-edit `typeobject.c` snapshot exited 0. The only production edit hoists `Py_ssize_t i;` into `type_new_get_bases()` after `nbases` and changes the loop initializer to `i = 0`, preserving bounds, increment, body, and behavior. The directly affected `scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py` was minimally updated to allow this separate declaration while retaining its allocation-order assertions. Focused test passed (exit 0); all 60 `scripts/vc6-typeobject-*.test.py` regressions passed (0 failures). Snapshot checks confirmed the production source differs only by the intended declaration/initializer change, the existing fixture by its narrow expected-prefix allowance, and `PORT_STATUS.md` was not modified during the delegated lane. + +After-change forced-fresh probe: `mkdir -p build/cron-20261029-after-get-bases-index/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-after-get-bases-index/probe.log 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. The former line-3295 C2143/C2065 loop diagnostics cleared. First current diagnostic family advances to `typeobject.c(3301)` C2143 for the later `PyObject *mro_entries` declaration, followed by C2065 at 3303; left untouched. Additional late declarations at lines 3316 and 3336 remain distinct and untouched. Capture: `build/cron-20261029-after-get-bases-index/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py`, narrowly updated `scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py`, and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only `type_new_get_bases()`'s `mro_entries` declaration. No completed port is claimed. + +--- +## `type_new_get_bases()` `mro_entries` C89 declaration slice (frontier advances) + +Date: 2026-10-29 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the legacy-toolchain reference before work. Preserved all existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change VC6/Wine probe: `mkdir -p build/cron-20261029-current-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable diagnostics were `typeobject.c(3301)` C2143 and `(3303)` C2065 `mro_entries`; later declaration families remain distinct. Capture: `build/cron-20261029-current-reprobe/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write, ephemeral; no commit) followed strict TDD. New `scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py` failed against unchanged production source (RED exit 1: `mro_entries must precede loop statements (C89)`); a byte comparison confirmed source unchanged before implementation. The sole production edit moved `PyObject *mro_entries;` directly after the `base` declaration and before the type-check statement. Attribute lookup remains after the type check, preserving evaluation/control-flow order. Focused regression passed (exit 0), and all 61 `scripts/vc6-typeobject-*.test.py` scripts passed individually. Snapshot verification confirmed pre-existing dirty/untracked paths, including `PORT_STATUS.md`, remained unchanged during the coding lane. + +After-change forced-fresh probe: `mkdir -p build/cron-20261029-after-mro-entries/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261029-after-mro-entries/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. The former line-3301/3303 diagnostics cleared. First current blocker advances to `typeobject.c(3316)` C2275/C2065 for the separate `PyTypeObject *winner` declaration; related errors at 3323/3325 are cascading. Left untouched. Capture: `build/cron-20261029-after-mro-entries/probe.log`. Focused test rerun passed (exit 0); outer and nested `git diff --check` both exited 0. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py`, and this status entry. Compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next: force-fresh confirm and isolate only the `winner` declaration family. No completed port is claimed. + +--- +## `type_new_get_bases()` `winner` C89 declaration slice (frontier advances) + +Date: 2026-10-21 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference before work. Preserved all pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change VC6/Wine command: `mkdir -p build/cron-20261030-current-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261030-current-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics were `typeobject.c(3316)` C2275 (`PyTypeObject`) and C2065 (`winner`), with cascading C2223 at 3323/3325. The next distinct `base` declaration at 3336 was left untouched. Capture: `build/cron-20261030-current-reprobe/probe.log`. + +Hermes delegation provider could not start (no Anthropic credentials); one authenticated Codex CLI lane (`codex-cli 0.153.4`, ChatGPT auth, workspace-write/ephemeral) followed strict TDD. New `scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py` failed against unchanged source with the expected declaration-placement assertion (RED exit 1). The minimal production edit moved only `PyTypeObject *winner;` to the function's opening declaration block; its assignment remains at the original evaluation point. Three directly affected `type_new_get_bases()` tests had narrow declaration/block-boundary expectation changes. Focused test passed (exit 0); all 62 `scripts/vc6-typeobject-*.test.py` tests passed, individually (0 failures). Preservation snapshot verified all 11,474 other pre-existing files byte-identical, with only the intended source and three directly affected test fixtures changed, plus the new focused test; no deletions and no staged changes. Outer and nested `git diff --check` and `git diff --cached --check` all exited 0. Codex's first attempted insertion matched a similar declaration block in another function; the applicable tests detected it, and it was corrected before final verification. No unrelated change was retained. + +Forced-fresh after-change command: `mkdir -p build/cron-20261030-after-winner/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261030-after-winner/probe.log 2>&1` — probe exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`; former line-3316 winner errors cleared. First stable blocker advances to `typeobject.c(3336)` C2275 (`PyTypeObject`) and C2065 (`base`), with distinct later errors beginning at line 3354. Capture: `build/cron-20261030-after-winner/probe.log`. Focused test rerun and both outer/nested diff checks exited 0. + +Files changed by this slice: `cpython/Objects/typeobject.c`; new `scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py`; narrowly updated `scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py`, `scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py`, and `scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py`; and this status entry. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: force-fresh confirm and isolate only the `type_new_get_bases()` `base` declaration at line 3336. No completed port is claimed. + +--- +## Diagnostics-only: `type_new_ctx` initializer frontier verified; delegated lane pending + +Date: 2026-10-22 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the profile CPython Win9x/MSVC6 reference before work. Preserved the dirty tree; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh VC6/Wine reprobe command: `mkdir -p build/cron-20261022-reprobe-blake/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261022-reprobe-blake/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022-reprobe-blake/probe.log 2>&1` — exit 2, but the path exceeded the AF_UNIX socket limit (108 bytes), so reran with short runtime path: `mkdir -p /home/ubuntu/r; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022-reprobe-blake/probe-retry.log 2>&1` — exit 2. `_blake2/blake2s_impl.c` compiled. First stable diagnostics reconfirm the recorded frontier at `typeobject.c(3365)`: C2275 (`type_new_ctx`), C2146 before `ctx`, C2065 `ctx`, and C2059 at `{`. The distinct next diagnostic family begins at line 3379 (`PyObject *type`) and is untouched. Capture: `build/cron-20261022-reprobe-blake/probe-retry.log`. + +One Hermes coding subagent attempt failed because Anthropic credentials are unavailable. A single authenticated Codex CLI 0.153.4 lane was started (`codex exec --sandbox workspace-write --ephemeral`, process id 1360911); its TDD implementation result has not yet been retrieved. No implementation is claimed in this record. Probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Current observed outer status count was 135 dirty/untracked entries. Next frontier: complete the isolated TDD slice for the initializer only if the delegated lane returns and independent verification passes; otherwise report the delegation blocker. No completed port is claimed. + +--- +## Diagnostics-only: current `type_new_ctx` failure is a late local declaration + +Date: 2026-10-22 04:14 UTC. The requested `/home/ubuntu/projects/python-win9x` checkout is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this file, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md` before acting. Preserved all pre-existing dirty/untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `_blake2/blake2s_impl.c` frontier is stale. Forced-fresh command: `mkdir -p build/cron-20261022-current-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022-current-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable errors in `cpython/Objects/typeobject.c(3365)` are C2275 `type_new_ctx` illegal use as expression, C2146 missing `;` before `ctx`, C2065 undeclared `ctx`, and C2059 at `{`; subsequent `.metatype`/`.args`/etc. C2224 errors cascade. Full capture: `build/cron-20261022-current-reprobe/probe.log`. + +One focused coding-agent lane was attempted. Hermes delegation was unavailable because the configured Anthropic provider has no credentials; authenticated `codex-cli 0.153.4` inspected the workspace and stopped without edits because `cpython/Objects/typeobject.c` already has the `{0}` initializer plus explicit field assignments, and `scripts/vc6-typeobject-type-new-ctx-c89.test.py` already exists. Its test checks the initializer's C89 compilation and 13 field values, but does not enforce declaration-before-statements: `type_new_ctx ctx` remains introduced after executable statements. No RED test was run; no files changed by the coding lane. Parent ran `python3 scripts/vc6-typeobject-type-new-ctx-c89.test.py` — exit 0 — and all 65 `scripts/vc6-typeobject-*.test.py` scripts — 65 passed, 0 failed. This evidence indicates the next defect family is the late local declaration, distinct from the already replaced designated initializer. To avoid claiming an unsupported initializer diagnosis or weakening TDD by reusing an already-passing test, no production edit was made this run. + +Files changed this run: `PORT_STATUS.md` only. This remains compiler-probe progress; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: strict-TDD isolate only the late `type_new_ctx ctx` declaration (test must assert it is in the opening declaration block, fail against the current source, then verify minimal hoist/assignment behavior), followed by a forced-fresh VC6 probe. No completed port is claimed. + +--- +## Diagnostics-only: `type_new()` context declaration blocker confirmed; coding lane unavailable + +Date: 2026-10-22 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile CPython Win9x/MSVC6 reference before probing. The working tree already contains extensive local changes, including a pre-existing untracked `scripts/vc6-typeobject-type-new-ctx-c89.test.py` and modifications to `cpython/Objects/typeobject.c`; preserved these and all other work. No reset, clean, stash, discard, commit, push, or publication. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh probe command: `mkdir -p /home/ubuntu/r build/cron-20261022T061658Z-frontier-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022T061658Z-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. First stable diagnostic group is `typeobject.c(3365)`: C2275 on `type_new_ctx`, C2146 missing `;` before `ctx`, C2065 undeclared `ctx`, and C2059 at `{`; subsequent field-access diagnostics cascade. This is consistent with the declaration occurring after statements in `type_new()`. Exact capture: `build/cron-20261022T061658Z-frontier-reprobe/probe.log`. + +The requested single coding-agent lane was attempted but Hermes delegation could not start because the configured Anthropic provider has no credentials. Following the specified one-lane limit and delegation fallback rules, did not start another external coding CLI lane. No production or regression source was changed this run. The pre-existing `scripts/vc6-typeobject-type-new-ctx-c89.test.py` was run and passed (exit 0; it compiles/runs a C89 context field-value fixture), but this does not test declaration placement and is not a TDD RED/GREEN cycle. The nested diff shows `cpython/Objects/typeobject.c` already contains a local `type_new_ctx ctx = {0};` followed by field assignments; this existing user modification was preserved. `git -C cpython diff --check -- Objects/typeobject.c` exited 0. + +Files changed this run: `PORT_STATUS.md` only. This is compiler-probe progress only: no pythoncore/python.exe link, Wine interpreter execution, or real Windows 98 SE execution occurred. Next frontier: hoist only the `type_new_ctx ctx` declaration into the opening local declaration block of `type_new()` while preserving initialization and field assignments at their current execution point; first add a placement regression and observe RED. No completed port is claimed. + +--- +## Diagnostics-only: `type_new_ctx` frontier reconfirmed; no safe implementation lane + +Date: 2026-10-22 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; operated in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the profile skill reference `python-3-win9x-msvc6.md`. Preserved the pre-existing dirty/untracked workspace; no reset, clean, stash, discard, commit, push, or publication. CPython baseline is tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The recorded `type_new_ctx` frontier remains current. Forced-fresh probe command: `mkdir -p build/cron-20261022-frontier-reprobe/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261022-frontier-reprobe/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics reconfirm at `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, C2059 at `{`, then cascading field errors. Complete capture: `build/cron-20261022-frontier-reprobe/probe.log`. + +Coding lane prerequisites: `codex-cli 0.153.4` is installed/authenticated (`codex login status`: “Logged in using ChatGPT”), but the checkout has substantial local modifications and untracked tests (136 outer status entries before this entry; nested CPython also dirty). The external VC6 bundle prerequisite is absent at `MSVC600/VC98/bin/VCVARS32.BAT`. An isolated clean worktree would not contain the live compatibility/test frontier, and shared-checkout autonomous edits cannot be safely isolated from the existing work. Therefore no coding agent was launched and no implementation or regression test was changed/run. This is diagnostics-only, not a claimed TDD cycle. + +Files changed this run: `PORT_STATUS.md` only. Compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier remains narrowly scoped: add a placement-focused RED regression for the `type_new_ctx ctx` declaration, then hoist only that declaration if a safe coding lane and usable compiler bundle are available; preserve initialization/field assignments at their execution point. No completed port is claimed. + +--- +## Diagnostics-only: current frontier still `type_new_ctx ctx`; VC6 toolchain absent + +Date: 2026-10-22 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile `python-3-win9x-msvc6.md` reference before work. Preserved all pre-existing modified and untracked paths; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The `_blake2/blake2s_impl.c` sequence is stale as a blocker: the forced-fresh probe compiled that source, then reproduced the current first stable compiler diagnostics at `cpython/Objects/typeobject.c(3365)`: C2275 for `type_new_ctx`, C2146 before `ctx`, C2065 undeclared `ctx`, and C2059 at `{`; subsequent field/type errors are cascades. Exact command: `mkdir -p build/cron-20261023-current-frontier-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261023-current-frontier-reprobe/probe.log 2>&1` — probe exit 2; `total=109 compiled=108 cached=0 skipped=0`. Capture: `build/cron-20261023-current-frontier-reprobe/probe.log`. + +No implementation/TDD lane was launched: required external compiler bundle path `MSVC600/VC98/bin/VCVARS32.BAT` is absent, so the requested focused VC6 verification cannot currently be run. This workspace already has extensive unrelated dirty/untracked state (137 outer status entries); all was preserved. No source or test files changed. `PORT_STATUS.md` is the only tracked file changed by this diagnostics run. Compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier remains investigate a C89-compatible `type_new_ctx ctx` declaration/initialization split only once the VC6 toolchain is restored, then run the focused probe and applicable regressions. No completed port is claimed. + +--- +## Diagnostics-only: `type_new_ctx` frontier reconfirmed; VC6 bundle unavailable + +Date: 2026-10-30 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `/home/ubuntu/.hermes/profiles/maxwell/skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all existing work; no reset, clean, stash, discard, commit, push, or publication. Nested CPython remains exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Re-probed the actual frontier using `XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261030-frontier-recheck/probe.log 2>&1` — exit 2. Forced-fresh source-list summary: `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics reconfirm `cpython/Objects/typeobject.c(3365)`: C2275 `type_new_ctx`, C2146 before `ctx`, C2065 `ctx`, C2059 at `{`; subsequent field/other C99 errors are cascading or later blockers. Full capture: `build/cron-20261030-frontier-recheck/probe.log`. + +The required local compiler launcher `MSVC600/VC98/bin/VCVARS32.BAT` is absent (file check exit 1), so this environment cannot run the required focused VC6 probe after an edit. No implementation or regression test was changed, no subagent was delegated, and no regression suite was run. Files changed by this run: `PORT_STATUS.md` only. This is compiler-probe progress only; no `pythoncore`/`python.exe` link, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: restore/provide the external MSVC600 bundle/launcher, then TDD the declaration-placement defect with a focused regression, run that test and applicable regressions, and verify using a forced-fresh VC6 probe. No completed port is claimed. + +--- + + +## 2026-10-24: `PyType_FromModuleAndSpec` `s` C89 declaration slice (compiler frontier advances) + +Worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. CPython baseline: exact tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`; outer HEAD `35caf1a558e6b2c5bf501894d8972f8b0dd828a6`. Fresh pre-change capture `build/cron-20261024-frontier-reprobe/probe.log`: exit 2, `total=109 compiled=108 cached=0 skipped=0`; first errors `(3493)` C2143 before `const`, then `(3494)` C2065 `s`. Earlier `memb` blocker cleared. + +Strict TDD: added `scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py` before production edits. RED command `python3 scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py` exited 1 at the expected opening-declaration assertion. Minimal production change in `cpython/Objects/typeobject.c`: declared `const char *s;` in the opening locals and changed the late initialized declaration to `s = strrchr(spec->name, '.');` at the original execution point. The initial GREEN attempt uncovered an over-broad test count (there are two `strrchr` uses elsewhere in the function); narrowed the assertion to the name-setup region. Corrected focused regression passed (exit 0), and all 70 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0 each). + +Compiler banner independently verified under Wine with `cl`: `Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86`; command exit 0. Forced-fresh post-change probe command: +```sh +mkdir -p build/cron-20261024-after-slice/runtime; XDG_RUNTIME_DIR="$PWD/build/cron-20261024-after-slice/runtime" WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-slice/probe.log 2>&1 +``` +Probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. Former line-3493/3494 errors cleared. First remaining stable errors: `typeobject.c(3517)` C2275 `Py_ssize_t`, C2146 before `name_buf_len`, C2065 `name_buf_len`; later `size_t len`/`tp_doc` diagnostics are separate and untouched. The first attempted post-change probe failed before compilation due Wine server lock setup; retry with the repo-local runtime directory above compiled 108 entries and established the source frontier. Captures: `build/cron-20261024-after-slice/probe.log`, `compiler-banner-plain.log`; initial failed attempt under `s-local/`. + +Scoped `git diff --check -- PORT_STATUS.md scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py` and `git -C cpython diff --check -- Objects/typeobject.c` passed (exit 0). Preservation snapshot check confirmed all unrelated existing dirty/untracked files byte-for-byte unchanged. Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py`, and `PORT_STATUS.md`; diagnostic outputs are under `build/cron-20261024-after-slice/`. No reset, clean, stash, discard, commit, push, or publication. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, no interpreter execution under Wine, and no Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `Py_ssize_t name_buf_len` declaration family at line 3517. No completed port is claimed. +## `PyType_FromModuleAndSpec()` `name_buf_len` C89 declaration slice (frontier advances) + +Date: 2026-10-24 UTC. The requested `/home/ubuntu/projects/python-win9x` checkout is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the active-profile `python-3-win9x-msvc6.md` reference before acting. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved existing work; no reset, clean, stash, discard, commit, push, or publication. + +Forced-fresh pre-change command: `mkdir -p /home/ubuntu/r; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-blake2-frontier/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. `_blake2/blake2s_impl.c` compiled. First stable diagnostic family: `cpython/Objects/typeobject.c(3517)` C2275 `Py_ssize_t`, C2146 before `name_buf_len`, and C2065 undeclared `name_buf_len`. Initial invocation using repository-local `XDG_RUNTIME_DIR` failed before compilation because the generated Unix socket path exceeded 108 bytes; rerun with `/home/ubuntu/r` succeeded. Full capture: `build/cron-20261024-blake2-frontier/probe.log`. + +One focused authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) used strict TDD, preserved unrelated changes, and did not edit this status. New `scripts/vc6-typeobject-from-module-and-spec-name-buf-len-c89.test.py` failed against unchanged production source (RED exit 1, expected opening-declaration assertion). The only production change hoists `Py_ssize_t name_buf_len;` into `PyType_FromModuleAndSpec()`'s opening declarations and replaces the initialized late declaration with an assignment at the same evaluation point. No existing fixture required changes. Focused regression passed; all 71 `scripts/vc6-typeobject-*.test.py` tests passed individually (0 failures). Outer and nested `git diff --check` both exited 0. Delegated snapshot verification reported 4,887 pre-existing files unchanged except the intended `cpython/Objects/typeobject.c` delta; independently verified focused/all tests and diff checks. + +Forced-fresh after-change command: `mkdir -p /home/ubuntu/r; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-name-buf-len.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. Former line-3517 diagnostics cleared. First remaining stable diagnostic is `typeobject.c(3605)` C2275 `size_t`, followed by C2146 before `len`, C2065 `len`, then C2143/C2065 involving `tp_doc`; this distinct next declaration family is untouched. Capture: `build/cron-20261024-after-name-buf-len.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c` (among pre-existing local edits), new `scripts/vc6-typeobject-from-module-and-spec-name-buf-len-c89.test.py`, and this status record. This is compile-frontier progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or Windows 98 SE execution. Next: force-fresh confirm and isolate only the `typeobject.c(3605)` `size_t len` declaration family. No completed port is claimed. + +--- +## `PyType_FromModuleAndSpec()` `Py_tp_doc` C89 declaration slice (frontier advances) + +Date: 2026-10-24 07:36 UTC. Requested checkout `/home/ubuntu/projects/python-win9x` is absent; worked in `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the CPython Win9x/MSVC6 reference first. Preserved all existing local changes and untracked paths; no reset, clean, stash, discard, commit, push, or publication. CPython baseline remains tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Fresh forced probe before edits: `mkdir -p /home/ubuntu/r build/cron-20260604-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20260604-reprobe/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable family was `typeobject.c(3605)` C2275 `size_t` / C2146 `len` / C2065 `len`, followed by line 3606 C2143/C2065 `tp_doc`. Capture: `build/cron-20260604-reprobe/probe.log`. + +One authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD. New `scripts/vc6-typeobject-from-module-and-spec-doc-c89.test.py` failed before production edit as expected (RED exit 1: `len and tp_doc must be declared at the start ... (C89)`). It hoisted only `size_t len;` and `char *tp_doc;` to the opening of the `Py_tp_doc` branch and converted the original initialized declarations to assignments at their original evaluation points. NULL guard, length/allocation order, failure handling, and copy remain unchanged. Focused GREEN passed (exit 0); all 72 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Preservation verification confirmed only `cpython/Objects/typeobject.c` changed among prior snapshotted files; only the focused test was added. Outer and nested `git diff --check` passed (exit 0). + +Forced-fresh after-change command: `mkdir -p /home/ubuntu/r build/cron-20260604-after-doc; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20260604-after-doc/probe.log 2>&1` — probe exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. Former diagnostics at lines 3605–3607 cleared. First stable blocker advances to `typeobject.c(3756)` C2275 `PyHeapTypeObject` / C2065 `et`, with later cascading member access; left untouched. Full capture: `build/cron-20260604-after-doc/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-from-module-and-spec-doc-c89.test.py`, and this status record. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only the `PyHeapTypeObject *et` declaration family at line 3756. No completed port is claimed. + +--- +## `PyType_GetModuleByDef()` `n` C89 declaration slice (frontier advances) + +Date: 2026-10-24 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and the CPython Win9x/MSVC6 reference before acting. Preserved all pre-existing modified and untracked work; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh pre-change probe: `mkdir -p build/cron-20261024-refresh-20261024; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-refresh-20261024/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First current stable diagnostic family in `PyType_GetModuleByDef()` was line 3797 C2275 `Py_ssize_t`, C2146 before `n`, and C2065 `n`; the following C99 loop initializer `i` was a separate blocker. Capture: `build/cron-20261024-refresh-20261024/probe.log`. + +One authenticated Codex CLI lane (`codex-cli 0.153.4`, workspace-write/ephemeral) followed strict TDD while preserving all pre-existing work. New `scripts/vc6-typeobject-get-module-by-def-n-c89.test.py` failed against unchanged production source (RED exit 1 at the expected opening-declaration assertion; `cmp` confirmed `typeobject.c` unchanged). The only production change hoists `Py_ssize_t n;` into the opening declaration block and changes the later initialized declaration to `n = PyTuple_GET_SIZE(mro);`, retaining evaluation timing. Directly coupled `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py` expectations were updated narrowly. Focused regression passed (exit 0); all 75 `scripts/vc6-typeobject-*.test.py` tests passed (exit 0). Snapshot verification confirmed only those two fixture/source paths changed during the lane and `PORT_STATUS.md` remained unchanged. No commit or publication. + +Forced-fresh after-change probe: `mkdir -p build/cron-20261024-after-n/runtime; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261024-after-n/probe.log 2>&1` — exit 2; summary remains `total=109 compiled=108 cached=0 skipped=0`. The `n` diagnostics cleared; first remaining blocker is the separate C99 loop index `i` at `typeobject.c(3799)`, C2143/C2065 and dependent syntax errors, left untouched. Capture: `build/cron-20261024-after-n/probe.log`. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-module-by-def-n-c89.test.py`, updated `scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: force-fresh confirm and isolate only `PyType_GetModuleByDef()`'s loop-index `i`. No completed port is claimed. + +--- +## Diagnostics-only: forced-fresh probe advances within `_PyType_GetSubclasses()` + +Date: 2026-10-25 UTC. The requested `/home/ubuntu/projects/python-win9x` path is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. Preserved all pre-existing modifications/untracked files; no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +Forced-fresh command: `mkdir -p /home/ubuntu/r build/cron-20261118-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261118-current-reprobe/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled. Former `subclasses` diagnostics are clear; the first stable errors now reach `_PyType_GetSubclasses()` `Py_ssize_t i` at `typeobject.c(4223)` (C2275/C2146/C2065). Later `ref`/`obj` declaration diagnostics remain distinct and untouched. Capture: `build/cron-20261118-current-reprobe/probe.log`. + +One focused coding delegation was attempted but could not start: configured Anthropic credentials are unavailable. No implementation or regression test was changed; no regression suite was run. The scoped source/test changes were not appropriate without a coding lane, and the existing `scripts/vc6-object-c89.test.py` change/untracked object tests are unrelated local work and remain untouched. Files changed by this diagnostic run: this `PORT_STATUS.md` entry only; compiler output is a build artifact. Compiler-probe progress only: no `pythoncore`/`python.exe` link, Wine interpreter execution, or Windows 98 SE execution. Next: use an available authenticated focused coding lane for strict-TDD isolation of only `_PyType_GetSubclasses()` loop-index `i`, then rerun applicable regressions and a forced-fresh VC6 probe. No completed port is claimed. + +--- + + + +--- + +## `_PyType_GetSubclasses()` `ref` C89 declaration slice + +Date: 2026-10-26 UTC. The requested checkout `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Before edits, read `PORT_STATUS.md`, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. CPython baseline verified as tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved pre-existing dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. Hermes delegation failed before launch due missing Anthropic credentials; used one authenticated Codex CLI 0.153.4 focused lane. + +Forced-fresh pre-change compiler probe: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-run/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled; first stable diagnostics at `typeobject.c(4225)` C2275 `PyObject` and C2065 `ref`, then `obj` at 4228. Capture: `build/cron-20261026-run/probe.log`. + +Strict TDD: new `scripts/vc6-typeobject-get-subclasses-ref-c89.test.py` failed against unchanged production source (RED exit 1, expected opening-declaration assertion). The only production change in this slice hoists `PyObject *ref; // borrowed ref` to `_PyType_GetSubclasses()`'s opening declarations and removes its former late declaration; it has no initializer, so no assignment was required. `PyDict_Next` and use timing remain unchanged. The existing coupled `get-subclasses-index` and `get-subclasses-subclasses` test expectations were narrowly updated. Focused test passed (exit 0); all 84 `scripts/vc6-typeobject-*.test.py` passed (exit 0). Nested source and outer affected-fixture `git diff --check` passed (exit 0). Snapshot verification confirmed all previously dirty/untracked paths unchanged during the delegated implementation. + +Forced-fresh post-change probe: `XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-after-ref/probe.log 2>&1` — exit 2; `_blake2/blake2s_impl.c` compiled. Former `ref` diagnostics cleared; first remaining blocker is the separate late `PyObject *obj` declaration at `typeobject.c(4228)` (C2143), followed by undeclared `obj` at 4229. Left untouched. + +Files changed by this slice: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-get-subclasses-ref-c89.test.py`, narrowly updated `scripts/vc6-typeobject-get-subclasses-index-c89.test.py` and `scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py`, and this status record. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: fresh-confirm and isolate only `_PyType_GetSubclasses()`'s `obj` declaration. No completed port is claimed. +## Diagnostics-only: `type_new_ctx` frontier stale; probe now fails later in `typeobject.c` + +Date: 2026-10-26 UTC. The requested `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read `PORT_STATUS.md`, `README.md`, and the legacy-toolchain CPython/MSVC6 reference. Preserved all existing work (extensive modified/untracked paths); no reset, clean, stash, discard, commit, push, or publication. CPython baseline verified: tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. + +The prior recorded `type_new_ctx` frontier at line 3365 is stale: forced-fresh probe `mkdir -p build/cron-20261026-current-reprobe; XDG_RUNTIME_DIR=/home/ubuntu/.hermes/profiles/maxwell/cache/scratch/wine-runtime WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-current-reprobe/probe.log 2>&1` returned probe exit 2 with `total=109 compiled=108 cached=0 skipped=0`; that line no longer appears as an error. `_blake2/blake2s_impl.c` is included among the successfully compiled entries. The first stable diagnostics currently reported by the project source-list probe are in `cpython/Objects/typeobject.c(4897)`: C2275 `PyTypeObject` and C2065 undeclared `newto`; later diagnostics include C89 mixed declarations throughout the file and the compiler's 100-error cutoff. Full capture: `build/cron-20261026-current-reprobe/probe.log`. + +The expected local launcher `MSVC600/VC98/bin/VCVARS32.BAT` is absent (test exit 1). No coding subagent was launched and no source/test implementation changes were made: post-edit focused VC6 validation cannot be established safely without the local toolchain prerequisite. This is diagnostics-only, not a TDD cycle. Files changed by this run: `PORT_STATUS.md` only; probe log is an untracked build artifact. No regression suite was run. + +Compiler-probe progress only; no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: restore the external MSVC600 bundle, then fresh-confirm and test-first address only the actual first blocker in `typeobject.c` (currently `newto` at 4897). No completed port is claimed. + +--- + +## `object_set_class()` `newto` C89 declaration slice (frontier advances) + +Date: 2026-10-26 16:07 UTC. User-requested `/home/ubuntu/projects/python-win9x` is absent; used `/home/ubuntu/Organized/Legacy-Ports/Projects/python-win9x`. Read this status, `README.md`, and `skills/software-development/legacy-toolchain-os-porting/references/python-3-win9x-msvc6.md`. CPython baseline verified at tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c8782608a4549`. Preserved the extensive existing dirty/untracked state; no reset, clean, stash, discard, commit, push, or publication. + +The requested `_blake2/blake2s_impl.c` condition is stale. Forced-fresh pre-change command: `mkdir -p /home/ubuntu/r build/cron-20261026-run; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-run/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`; `_blake2/blake2s_impl.c` compiled. First stable diagnostics were `cpython/Objects/typeobject.c(4897)` C2275 `PyTypeObject` and C2065 `newto`, followed by cascading `newto->tp_flags` errors. Full capture: `build/cron-20261026-run/probe.log`. + +Hermes coding delegation was attempted once and failed before launch because Anthropic credentials are unavailable. Following the coding-agent-delegation fallback, authenticated Codex CLI 0.153.4 ran one isolated-in-scope lane in the heavily modified working checkout; no destructive Git operations. Strict TDD RED: new `scripts/vc6-typeobject-object-set-class-newto-c89.test.py` failed before production edit (exit 1, expected assertion that `newto` must be in the C89 opening declaration block). GREEN: `cpython/Objects/typeobject.c` now declares `PyTypeObject *newto;` with the opening locals and assigns `(PyTypeObject *)value` at its prior point, after the same validation. The focused test passed (exit 0); all 88 applicable `scripts/vc6-typeobject-*.test.py` scripts passed individually (exit 0). Nested `git diff --check -- Objects/typeobject.c` and outer test diff check passed (exit 0); new-file no-index check emitted no whitespace diagnostics (exit 1 solely because files differ). The lane verified the exact two-location production delta and hashes for all 287 other prior dirty/untracked files unchanged, including this status file before this entry. Lane logs: `build/cron-20261026-run/codex.log` and `codex-last.txt`. + +Forced-fresh post-change command: `mkdir -p build/cron-20261026-after-newto; XDG_RUNTIME_DIR=/home/ubuntu/r WINEPREFIX=/home/ubuntu/.wine-win9xport WINEDEBUG=-all VC6_FRONTIER_FORCE=1 bash scripts/vc6-probe-pythoncore-frontier.sh > build/cron-20261026-after-newto/probe.log 2>&1` — exit 2; summary `total=109 compiled=108 cached=0 skipped=0`. The `newto` errors at line 4897 cleared; `_blake2/blake2s_impl.c` still compiled. First stable diagnostics advance to `typeobject.c(5789)`: C2275 `PyObject` and C2065 `name`; later diagnostics in `set_names()` and subsequent functions are separate/later blockers, left untouched. Full capture: `build/cron-20261026-after-newto/probe.log`. + +Files changed: `cpython/Objects/typeobject.c`, new `scripts/vc6-typeobject-object-set-class-newto-c89.test.py`, and this status entry. Compiler-probe progress only: no linked `pythoncore`/`python.exe`, Wine interpreter execution, or real Windows 98 SE execution. Next frontier: force-fresh confirm and isolate only the actual `typeobject.c(5789)` `name` declaration family. No completed port is claimed. + +--- diff --git a/compat/msvc600/cpython-3.11.16-vc6-headers.patch b/compat/msvc600/cpython-3.11.16-vc6-headers.patch index 8790364..12938f2 100644 --- a/compat/msvc600/cpython-3.11.16-vc6-headers.patch +++ b/compat/msvc600/cpython-3.11.16-vc6-headers.patch @@ -536,6 +536,41 @@ index 13eae1e..91faff4 100644 // global objects +diff --git a/Include/internal/pycore_win9x_loadlibrary.h b/Include/internal/pycore_win9x_loadlibrary.h +new file mode 100644 +index 0000000..47fd5c3 +--- /dev/null ++++ b/Include/internal/pycore_win9x_loadlibrary.h +@@ -0,0 +1,29 @@ ++#ifndef PyCORE_WIN9X_LOADLIBRARY_H ++#define PyCORE_WIN9X_LOADLIBRARY_H ++ ++/* ++ * The VC98 SDK predates the restricted DLL-search flags introduced by newer ++ * Windows SDKs. Define their documented bit values so Windows sources can be ++ * compiled with MSVC 6.0. This is compile-time compatibility only: Windows 9x ++ * does not implement these LoadLibraryEx search semantics, so runtime loader ++ * call sites still require a legacy-compatible path. ++ */ ++#if defined(_MSC_VER) && _MSC_VER < 1300 ++# ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR ++# define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100 ++# endif ++# ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR ++# define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200 ++# endif ++# ifndef LOAD_LIBRARY_SEARCH_USER_DIRS ++# define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400 ++# endif ++# ifndef LOAD_LIBRARY_SEARCH_SYSTEM32 ++# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 ++# endif ++# ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS ++# define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 ++# endif ++#endif ++ ++#endif /* PyCORE_WIN9X_LOADLIBRARY_H */ diff --git a/Include/longobject.h b/Include/longobject.h index 778cb62..d25edf7 100644 --- a/Include/longobject.h @@ -21184,7 +21219,7 @@ index d18f206..1104e46 100644 if (result) { Py_CLEAR(annotations); diff --git a/Objects/object.c b/Objects/object.c -index c4f2786..8e2a684 100644 +index c4f2786..d6290c3 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -30,6 +30,14 @@ extern "C" { @@ -21284,7 +21319,7 @@ index c4f2786..8e2a684 100644 #ifdef Py_DEBUG /* PyObject_Str() must not be called with an exception set, because it can clear it (directly or indirectly) and so the -@@ -589,9 +604,13 @@ def _PyObject_FunctionStr(x): +@@ -589,17 +604,20 @@ def _PyObject_FunctionStr(x): PyObject * _PyObject_FunctionStr(PyObject *x) { @@ -21300,7 +21335,227 @@ index c4f2786..8e2a684 100644 if (qualname == NULL) { if (ret < 0) { return NULL; -@@ -1980,6 +1999,14 @@ _PyTypes_InitTypes(PyInterpreterState *interp) + } + return PyObject_Str(x); + } +- PyObject *module; +- PyObject *result = NULL; ++ result = NULL; + ret = _PyObject_LookupAttr(x, &_Py_ID(__module__), &module); + if (module != NULL && module != Py_None) { + ret = PyObject_RichCompareBool(module, &_Py_ID(builtins), Py_NE); +@@ -715,6 +733,7 @@ PyObject * + PyObject_RichCompare(PyObject *v, PyObject *w, int op) + { + PyThreadState *tstate = _PyThreadState_GET(); ++ PyObject *res; + + assert(Py_LT <= op && op <= Py_GE); + if (v == NULL || w == NULL) { +@@ -726,7 +745,7 @@ PyObject_RichCompare(PyObject *v, PyObject *w, int op) + if (_Py_EnterRecursiveCallTstate(tstate, " in comparison")) { + return NULL; + } +- PyObject *res = do_richcompare(tstate, v, w, op); ++ res = do_richcompare(tstate, v, w, op); + _Py_LeaveRecursiveCallTstate(tstate); + return res; + } +@@ -873,19 +892,21 @@ _PyObject_SetAttrId(PyObject *v, _Py_Identifier *name, PyObject *w) + static inline int + set_attribute_error_context(PyObject* v, PyObject* name) + { ++ PyObject *type, *value, *traceback; ++ PyAttributeErrorObject *the_exc; ++ + assert(PyErr_Occurred()); + if (!PyErr_ExceptionMatches(PyExc_AttributeError)){ + return 0; + } + // Intercept AttributeError exceptions and augment them to offer suggestions later. +- PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + // Check if the normalized exception is indeed an AttributeError + if (!PyErr_GivenExceptionMatches(value, PyExc_AttributeError)) { + goto restore; + } +- PyAttributeErrorObject* the_exc = (PyAttributeErrorObject*) value; ++ the_exc = (PyAttributeErrorObject*) value; + // Check if this exception was already augmented + if (the_exc->name || the_exc->obj) { + goto restore; +@@ -904,6 +925,7 @@ PyObject * + PyObject_GetAttr(PyObject *v, PyObject *name) + { + PyTypeObject *tp = Py_TYPE(v); ++ PyObject *result; + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", +@@ -911,7 +933,7 @@ PyObject_GetAttr(PyObject *v, PyObject *name) + return NULL; + } + +- PyObject* result = NULL; ++ result = NULL; + if (tp->tp_getattro != NULL) { + result = (*tp->tp_getattro)(v, name); + } +@@ -1072,10 +1094,11 @@ _PyObject_DictPointer(PyObject *obj) + return NULL; + if (dictoffset < 0) { + Py_ssize_t tsize = Py_SIZE(obj); ++ size_t size; + if (tsize < 0) { + tsize = -tsize; + } +- size_t size = _PyObject_VAR_SIZE(tp, tsize); ++ size = _PyObject_VAR_SIZE(tp, tsize); + assert(size <= (size_t)PY_SSIZE_T_MAX); + dictoffset += (Py_ssize_t)size; + +@@ -1095,16 +1118,20 @@ _PyObject_DictPointer(PyObject *obj) + PyObject ** + _PyObject_GetDictPtr(PyObject *obj) + { ++ PyObject **dict_ptr; ++ PyDictValues **values_ptr; ++ PyObject *dict; ++ + if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { + return _PyObject_DictPointer(obj); + } +- PyObject **dict_ptr = _PyObject_ManagedDictPointer(obj); +- PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); ++ dict_ptr = _PyObject_ManagedDictPointer(obj); ++ values_ptr = _PyObject_ValuesPointer(obj); + if (*values_ptr == NULL) { + return dict_ptr; + } + assert(*dict_ptr == NULL); +- PyObject *dict = _PyObject_MakeDictFromInstanceAttributes(obj, *values_ptr); ++ dict = _PyObject_MakeDictFromInstanceAttributes(obj, *values_ptr); + if (dict == NULL) { + PyErr_Clear(); + return NULL; +@@ -1150,10 +1177,15 @@ int + _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) + { + int meth_found = 0; ++ PyTypeObject *tp; ++ PyObject *descr; ++ descrgetfunc f; ++ PyDictValues *values; ++ PyObject *attr; + + assert(*method == NULL); + +- PyTypeObject *tp = Py_TYPE(obj); ++ tp = Py_TYPE(obj); + if (!_PyType_IsReady(tp)) { + if (PyType_Ready(tp) < 0) { + return 0; +@@ -1165,8 +1197,8 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) + return 0; + } + +- PyObject *descr = _PyType_Lookup(tp, name); +- descrgetfunc f = NULL; ++ descr = _PyType_Lookup(tp, name); ++ f = NULL; + if (descr != NULL) { + Py_INCREF(descr); + if (_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) { +@@ -1180,12 +1212,11 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) + } + } + } +- PyDictValues *values; + if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) && + (values = *_PyObject_ValuesPointer(obj))) + { + assert(*_PyObject_DictPointer(obj) == NULL); +- PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name); ++ attr = _PyObject_GetInstanceAttribute(obj, values, name); + if (attr != NULL) { + *method = attr; + Py_XDECREF(descr); +@@ -1197,7 +1228,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) + PyObject *dict; + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); +- PyObject *attr = PyDict_GetItemWithError(dict, name); ++ attr = PyDict_GetItemWithError(dict, name); + if (attr != NULL) { + *method = Py_NewRef(attr); + Py_DECREF(dict); +@@ -1781,7 +1812,42 @@ notimplemented_bool(PyObject *v) + } + + static PyNumberMethods notimplemented_as_number = { +- .nb_bool = notimplemented_bool, ++ 0, /* nb_add */ ++ 0, /* nb_subtract */ ++ 0, /* nb_multiply */ ++ 0, /* nb_remainder */ ++ 0, /* nb_divmod */ ++ 0, /* nb_power */ ++ 0, /* nb_negative */ ++ 0, /* nb_positive */ ++ 0, /* nb_absolute */ ++ notimplemented_bool, /* nb_bool */ ++ 0, /* nb_invert */ ++ 0, /* nb_lshift */ ++ 0, /* nb_rshift */ ++ 0, /* nb_and */ ++ 0, /* nb_xor */ ++ 0, /* nb_or */ ++ 0, /* nb_int */ ++ 0, /* nb_reserved */ ++ 0, /* nb_float */ ++ 0, /* nb_inplace_add */ ++ 0, /* nb_inplace_subtract */ ++ 0, /* nb_inplace_multiply */ ++ 0, /* nb_inplace_remainder */ ++ 0, /* nb_inplace_power */ ++ 0, /* nb_inplace_lshift */ ++ 0, /* nb_inplace_rshift */ ++ 0, /* nb_inplace_and */ ++ 0, /* nb_inplace_xor */ ++ 0, /* nb_inplace_or */ ++ 0, /* nb_floor_divide */ ++ 0, /* nb_true_divide */ ++ 0, /* nb_inplace_floor_divide */ ++ 0, /* nb_inplace_true_divide */ ++ 0, /* nb_index */ ++ 0, /* nb_matrix_multiply */ ++ 0, /* nb_inplace_matrix_multiply */ + }; + + PyTypeObject _PyNotImplemented_Type = { +@@ -1833,11 +1899,13 @@ PyObject _Py_NotImplementedStruct = { + PyStatus + _PyTypes_InitState(PyInterpreterState *interp) + { ++ PyStatus status; ++ + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + +- PyStatus status = _PyTypes_InitSlotDefs(); ++ status = _PyTypes_InitSlotDefs(); + if (_PyStatus_EXCEPTION(status)) { + return status; + } +@@ -1976,12 +2044,22 @@ static PyTypeObject* static_types[] = { + PyStatus + _PyTypes_InitTypes(PyInterpreterState *interp) + { ++ size_t i; ++ + if (!_Py_IsMainInterpreter(interp)) { return _PyStatus_OK(); } @@ -21313,8 +21568,1094 @@ index c4f2786..8e2a684 100644 +#endif + // All other static types (unless initialized elsewhere) - for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { +- for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { ++ for (i=0; i < Py_ARRAY_LENGTH(static_types); i++) { PyTypeObject *type = static_types[i]; + if (PyType_Ready(type) < 0) { + return _PyStatus_ERR("Can't initialize types"); +@@ -2006,13 +2084,15 @@ _PyTypes_InitTypes(PyInterpreterState *interp) + void + _PyTypes_FiniTypes(PyInterpreterState *interp) + { ++ Py_ssize_t i; ++ + if (!_Py_IsMainInterpreter(interp)) { + return; + } + + // Deallocate types in the reverse order to deallocate subclasses before + // their base classes. +- for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) { ++ for (i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) { + PyTypeObject *type = static_types[i]; + _PyStaticType_Dealloc(type); + } +diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c +index b9529e4..3030ff0 100644 +--- a/Objects/obmalloc.c ++++ b/Objects/obmalloc.c +@@ -86,7 +86,11 @@ static void* _PyObject_Realloc(void *ctx, void *ptr, size_t size); + /* bpo-35053: Declare tracemalloc configuration here rather than + Modules/_tracemalloc.c because _tracemalloc can be compiled as dynamic + library, whereas _Py_NewReference() requires it. */ +-struct _PyTraceMalloc_Config _Py_tracemalloc_config = _PyTraceMalloc_Config_INIT; ++struct _PyTraceMalloc_Config _Py_tracemalloc_config = { ++ TRACEMALLOC_NOT_INITIALIZED, /* initialized */ ++ 0, /* tracing */ ++ 1 /* max_nframe */ ++}; + + + static void * +@@ -227,23 +231,33 @@ static int + pymem_set_default_allocator(PyMemAllocatorDomain domain, int debug, + PyMemAllocatorEx *old_alloc) + { ++ PyMemAllocatorEx new_alloc; ++ + if (old_alloc != NULL) { + PyMem_GetAllocator(domain, old_alloc); + } + + +- PyMemAllocatorEx new_alloc; + switch(domain) + { + case PYMEM_DOMAIN_RAW: +- new_alloc = (PyMemAllocatorEx)PYRAW_ALLOC; ++ { ++ PyMemAllocatorEx alloc = PYRAW_ALLOC; ++ new_alloc = alloc; + break; ++ } + case PYMEM_DOMAIN_MEM: +- new_alloc = (PyMemAllocatorEx)PYMEM_ALLOC; ++ { ++ PyMemAllocatorEx alloc = PYMEM_ALLOC; ++ new_alloc = alloc; + break; ++ } + case PYMEM_DOMAIN_OBJ: +- new_alloc = (PyMemAllocatorEx)PYOBJ_ALLOC; ++ { ++ PyMemAllocatorEx alloc = PYOBJ_ALLOC; ++ new_alloc = alloc; + break; ++ } + default: + /* unknown domain */ + return -1; +@@ -330,9 +344,9 @@ _PyMem_SetupAllocators(PyMemAllocatorName allocator) + case PYMEM_ALLOCATOR_PYMALLOC_DEBUG: + { + PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC; ++ PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC; + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &malloc_alloc); + +- PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC; + PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &pymalloc); + PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &pymalloc); + +@@ -379,6 +393,9 @@ _PyMem_GetCurrentAllocatorName(void) + #ifdef WITH_PYMALLOC + PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC; + #endif ++ PyMemAllocatorEx dbg_raw = PYDBGRAW_ALLOC; ++ PyMemAllocatorEx dbg_mem = PYDBGMEM_ALLOC; ++ PyMemAllocatorEx dbg_obj = PYDBGOBJ_ALLOC; + + if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) && + pymemallocator_eq(&_PyMem, &malloc_alloc) && +@@ -395,10 +412,6 @@ _PyMem_GetCurrentAllocatorName(void) + } + #endif + +- PyMemAllocatorEx dbg_raw = PYDBGRAW_ALLOC; +- PyMemAllocatorEx dbg_mem = PYDBGMEM_ALLOC; +- PyMemAllocatorEx dbg_obj = PYDBGOBJ_ALLOC; +- + if (pymemallocator_eq(&_PyMem_Raw, &dbg_raw) && + pymemallocator_eq(&_PyMem, &dbg_mem) && + pymemallocator_eq(&_PyObject, &dbg_obj)) +@@ -656,15 +669,19 @@ PyMem_Free(void *ptr) + wchar_t* + _PyMem_RawWcsdup(const wchar_t *str) + { ++ size_t len; ++ size_t size; ++ wchar_t *str2; ++ + assert(str != NULL); + +- size_t len = wcslen(str); ++ len = wcslen(str); + if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) { + return NULL; + } + +- size_t size = (len + 1) * sizeof(wchar_t); +- wchar_t *str2 = PyMem_RawMalloc(size); ++ size = (len + 1) * sizeof(wchar_t); ++ str2 = PyMem_RawMalloc(size); + if (str2 == NULL) { + return NULL; + } +@@ -676,9 +693,12 @@ _PyMem_RawWcsdup(const wchar_t *str) + char * + _PyMem_RawStrdup(const char *str) + { ++ size_t size; ++ char *copy; ++ + assert(str != NULL); +- size_t size = strlen(str) + 1; +- char *copy = PyMem_RawMalloc(size); ++ size = strlen(str) + 1; ++ copy = PyMem_RawMalloc(size); + if (copy == NULL) { + return NULL; + } +@@ -689,9 +709,12 @@ _PyMem_RawStrdup(const char *str) + char * + _PyMem_Strdup(const char *str) + { ++ size_t size; ++ char *copy; ++ + assert(str != NULL); +- size_t size = strlen(str) + 1; +- char *copy = PyMem_Malloc(size); ++ size = strlen(str) + 1; ++ copy = PyMem_Malloc(size); + if (copy == NULL) { + return NULL; + } +@@ -1277,14 +1300,16 @@ Py_ssize_t + _Py_GetAllocatedBlocks(void) + { + Py_ssize_t n = raw_allocated_blocks; ++ uint i; ++ uintptr_t base; + /* add up allocated blocks for used pools */ +- for (uint i = 0; i < maxarenas; ++i) { ++ for (i = 0; i < maxarenas; ++i) { + /* Skip arenas which are not allocated. */ + if (arenas[i].address == 0) { + continue; + } + +- uintptr_t base = (uintptr_t)_Py_ALIGN_UP(arenas[i].address, POOL_SIZE); ++ base = (uintptr_t)_Py_ALIGN_UP(arenas[i].address, POOL_SIZE); + + /* visit every pool in the arena */ + assert(base <= (uintptr_t) arenas[i].pool_address); +@@ -1509,15 +1534,22 @@ arena_map_get(block *p, int create) + static int + arena_map_mark_used(uintptr_t arena_base, int is_used) + { ++ arena_map_bot_t *n_hi; ++ int i3; ++ int32_t tail; ++ uintptr_t arena_base_next; ++ arena_map_bot_t *n_lo; ++ int i3_next; ++ + /* sanity check that IGNORE_BITS is correct */ + assert(HIGH_BITS(arena_base) == HIGH_BITS(&arena_map_root)); +- arena_map_bot_t *n_hi = arena_map_get((block *)arena_base, is_used); ++ n_hi = arena_map_get((block *)arena_base, is_used); + if (n_hi == NULL) { + assert(is_used); /* otherwise node should already exist */ + return 0; /* failed to allocate space for node */ + } +- int i3 = MAP_BOT_INDEX((block *)arena_base); +- int32_t tail = (int32_t)(arena_base & ARENA_SIZE_MASK); ++ i3 = MAP_BOT_INDEX((block *)arena_base); ++ tail = (int32_t)(arena_base & ARENA_SIZE_MASK); + if (tail == 0) { + /* is ideal arena address */ + n_hi->arenas[i3].tail_hi = is_used ? -1 : 0; +@@ -1530,19 +1562,19 @@ arena_map_mark_used(uintptr_t arena_base, int is_used) + * again (do the full tree traversal). + */ + n_hi->arenas[i3].tail_hi = is_used ? tail : 0; +- uintptr_t arena_base_next = arena_base + ARENA_SIZE; ++ arena_base_next = arena_base + ARENA_SIZE; + /* If arena_base is a legit arena address, so is arena_base_next - 1 + * (last address in arena). If arena_base_next overflows then it + * must overflow to 0. However, that would mean arena_base was + * "ideal" and we should not be in this case. */ + assert(arena_base < arena_base_next); +- arena_map_bot_t *n_lo = arena_map_get((block *)arena_base_next, is_used); ++ n_lo = arena_map_get((block *)arena_base_next, is_used); + if (n_lo == NULL) { + assert(is_used); /* otherwise should already exist */ + n_hi->arenas[i3].tail_hi = 0; + return 0; /* failed to allocate space for node */ + } +- int i3_next = MAP_BOT_INDEX(arena_base_next); ++ i3_next = MAP_BOT_INDEX(arena_base_next); + n_lo->arenas[i3_next].tail_lo = is_used ? tail : 0; + } + return 1; +@@ -1554,14 +1586,19 @@ static int + arena_map_is_used(block *p) + { + arena_map_bot_t *n = arena_map_get(p, 0); ++ int i3; ++ int32_t hi; ++ int32_t lo; ++ int32_t tail; ++ + if (n == NULL) { + return 0; + } +- int i3 = MAP_BOT_INDEX(p); ++ i3 = MAP_BOT_INDEX(p); + /* ARENA_BITS must be < 32 so that the tail is a non-negative int32_t. */ +- int32_t hi = n->arenas[i3].tail_hi; +- int32_t lo = n->arenas[i3].tail_lo; +- int32_t tail = (int32_t)(AS_UINT(p) & ARENA_SIZE_MASK); ++ hi = n->arenas[i3].tail_hi; ++ lo = n->arenas[i3].tail_lo; ++ tail = (int32_t)(AS_UINT(p) & ARENA_SIZE_MASK); + return (tail < lo) || (tail >= hi && hi != 0); + } + +@@ -1789,6 +1826,8 @@ address_in_range(void *p, poolp pool) + static void + pymalloc_pool_extend(poolp pool, uint size) + { ++ poolp next; ++ + if (UNLIKELY(pool->nextoffset <= pool->maxnextoffset)) { + /* There is room for another block. */ + pool->freeblock = (block*)pool + pool->nextoffset; +@@ -1798,7 +1837,6 @@ pymalloc_pool_extend(poolp pool, uint size) + } + + /* Pool is full, unlink from used pools. */ +- poolp next; + next = pool->nextpool; + pool = pool->prevpool; + next->prevpool = pool; +@@ -1811,6 +1849,10 @@ pymalloc_pool_extend(poolp pool, uint size) + static void* + allocate_from_new_pool(uint size) + { ++ poolp pool; ++ block *bp; ++ poolp next; ++ + /* There isn't a pool of the right size class immediately + * available: use a free pool. + */ +@@ -1848,7 +1890,7 @@ allocate_from_new_pool(uint size) + } + + /* Try to get a cached free pool. */ +- poolp pool = usable_arenas->freepools; ++ pool = usable_arenas->freepools; + if (LIKELY(pool != NULL)) { + /* Unlink from cached pools. */ + usable_arenas->freepools = pool->nextpool; +@@ -1904,8 +1946,7 @@ allocate_from_new_pool(uint size) + } + + /* Frontlink to used pools. */ +- block *bp; +- poolp next = usedpools[size + size]; /* == prev */ ++ next = usedpools[size + size]; /* == prev */ + pool->nextpool = next; + pool->prevpool = next; + next->nextpool = pool; +@@ -1947,6 +1988,10 @@ allocate_from_new_pool(uint size) + static inline void* + pymalloc_alloc(void *ctx, size_t nbytes) + { ++ uint size; ++ poolp pool; ++ block *bp; ++ + #ifdef WITH_VALGRIND + if (UNLIKELY(running_on_valgrind == -1)) { + running_on_valgrind = RUNNING_ON_VALGRIND; +@@ -1963,9 +2008,8 @@ pymalloc_alloc(void *ctx, size_t nbytes) + return NULL; + } + +- uint size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT; +- poolp pool = usedpools[size + size]; +- block *bp; ++ size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT; ++ pool = usedpools[size + size]; + + if (LIKELY(pool != pool->nextpool)) { + /* +@@ -2011,10 +2055,13 @@ _PyObject_Malloc(void *ctx, size_t nbytes) + static void * + _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize) + { ++ size_t nbytes; ++ void* ptr; ++ + assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize); +- size_t nbytes = nelem * elsize; ++ nbytes = nelem * elsize; + +- void* ptr = pymalloc_alloc(ctx, nbytes); ++ ptr = pymalloc_alloc(ctx, nbytes); + if (LIKELY(ptr != NULL)) { + memset(ptr, 0, nbytes); + return ptr; +@@ -2031,11 +2078,15 @@ _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize) + static void + insert_to_usedpool(poolp pool) + { ++ uint size; ++ poolp next; ++ poolp prev; ++ + assert(pool->ref.count > 0); /* else the pool is empty */ + +- uint size = pool->szidx; +- poolp next = usedpools[size + size]; +- poolp prev = next->prevpool; ++ size = pool->szidx; ++ next = usedpools[size + size]; ++ prev = next->prevpool; + + /* insert pool before next: prev <-> pool <-> next */ + pool->nextpool = next; +@@ -2047,23 +2098,30 @@ insert_to_usedpool(poolp pool) + static void + insert_to_freepool(poolp pool) + { +- poolp next = pool->nextpool; +- poolp prev = pool->prevpool; ++ poolp next; ++ poolp prev; ++ struct arena_object *ao; ++ uint nf; ++ struct arena_object* lastnf; ++ struct arena_object* p; ++ ++ next = pool->nextpool; ++ prev = pool->prevpool; + next->prevpool = prev; + prev->nextpool = next; + + /* Link the pool to freepools. This is a singly-linked + * list, and pool->prevpool isn't used there. + */ +- struct arena_object *ao = &arenas[pool->arenaindex]; ++ ao = &arenas[pool->arenaindex]; + pool->nextpool = ao->freepools; + ao->freepools = pool; +- uint nf = ao->nfreepools; ++ nf = ao->nfreepools; + /* If this is the rightmost arena with this number of free pools, + * nfp2lasta[nf] needs to change. Caution: if nf is 0, there + * are no arenas in usable_arenas with that value. + */ +- struct arena_object* lastnf = nfp2lasta[nf]; ++ lastnf = nfp2lasta[nf]; + assert((nf == 0 && lastnf == NULL) || + (nf > 0 && + lastnf != NULL && +@@ -2071,7 +2129,7 @@ insert_to_freepool(poolp pool) + (lastnf->nextarena == NULL || + nf < lastnf->nextarena->nfreepools))); + if (lastnf == ao) { /* it is the rightmost */ +- struct arena_object* p = ao->prevarena; ++ p = ao->prevarena; + nfp2lasta[nf] = (p != NULL && p->nfreepools == nf) ? p : NULL; + } + ao->nfreepools = ++nf; +@@ -2217,6 +2275,9 @@ insert_to_freepool(poolp pool) + static inline int + pymalloc_free(void *ctx, void *p) + { ++ poolp pool; ++ block *lastfree; ++ + assert(p != NULL); + + #ifdef WITH_VALGRIND +@@ -2225,7 +2286,7 @@ pymalloc_free(void *ctx, void *p) + } + #endif + +- poolp pool = POOL_ADDR(p); ++ pool = POOL_ADDR(p); + if (UNLIKELY(!address_in_range(p, pool))) { + return 0; + } +@@ -2238,7 +2299,7 @@ pymalloc_free(void *ctx, void *p) + * list in any case). + */ + assert(pool->ref.count > 0); /* else it was empty */ +- block *lastfree = pool->freeblock; ++ lastfree = pool->freeblock; + *(block **)p = lastfree; + pool->freeblock = (block *)p; + pool->ref.count--; +@@ -2559,14 +2620,17 @@ _PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize) + static void + _PyMem_DebugRawFree(void *ctx, void *p) + { ++ debug_alloc_api_t *api; ++ uint8_t *q; ++ size_t nbytes; ++ + /* PyMem_Free(NULL) has no effect */ + if (p == NULL) { + return; + } + +- debug_alloc_api_t *api = (debug_alloc_api_t *)ctx; +- uint8_t *q = (uint8_t *)p - 2*SST; /* address returned from malloc */ +- size_t nbytes; ++ api = (debug_alloc_api_t *)ctx; ++ q = (uint8_t *)p - 2*SST; /* address returned from malloc */ + + _PyMem_DebugCheckAddress(__func__, api->api_id, p); + nbytes = read_size_t(q); +@@ -2579,11 +2643,7 @@ _PyMem_DebugRawFree(void *ctx, void *p) + static void * + _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) + { +- if (p == NULL) { +- return _PyMem_DebugRawAlloc(0, ctx, nbytes); +- } +- +- debug_alloc_api_t *api = (debug_alloc_api_t *)ctx; ++ debug_alloc_api_t *api; + uint8_t *head; /* base address of malloc'ed pad block */ + uint8_t *data; /* pointer to data bytes */ + uint8_t *r; +@@ -2592,6 +2652,15 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) + size_t original_nbytes; + #define ERASED_SIZE 64 + uint8_t save[2*ERASED_SIZE]; /* A copy of erased bytes. */ ++#ifdef PYMEM_DEBUG_SERIALNO ++ size_t block_serialno; ++#endif ++ ++ if (p == NULL) { ++ return _PyMem_DebugRawAlloc(0, ctx, nbytes); ++ } ++ ++ api = (debug_alloc_api_t *)ctx; + + _PyMem_DebugCheckAddress(__func__, api->api_id, p); + +@@ -2606,7 +2675,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) + + tail = data + original_nbytes; + #ifdef PYMEM_DEBUG_SERIALNO +- size_t block_serialno = read_size_t(tail + SST); ++ block_serialno = read_size_t(tail + SST); + #endif + /* Mark the header, the trailer, ERASED_SIZE bytes at the begin and + ERASED_SIZE bytes at the end as dead and save the copy of erased bytes. +@@ -2724,14 +2793,16 @@ _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes) + static void + _PyMem_DebugCheckAddress(const char *func, char api, const void *p) + { +- assert(p != NULL); +- +- const uint8_t *q = (const uint8_t *)p; ++ const uint8_t *q; + size_t nbytes; + const uint8_t *tail; + int i; + char id; + ++ assert(p != NULL); ++ ++ q = (const uint8_t *)p; ++ + /* Check the API id */ + id = (char)q[-SST]; + if (id != api) { +@@ -2957,37 +3028,46 @@ pool_is_in_list(const poolp target, poolp list) + int + _PyObject_DebugMallocStats(FILE *out) + { +- if (!_PyMem_PymallocEnabled()) { +- return 0; +- } +- + uint i; +- const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT; ++ uint numclasses; + /* # of pools, allocated blocks, and free blocks per class index */ + size_t numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT]; + size_t numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT]; + size_t numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT]; + /* total # of allocated bytes in used and full pools */ +- size_t allocated_bytes = 0; ++ size_t allocated_bytes; + /* total # of available bytes in used pools */ +- size_t available_bytes = 0; ++ size_t available_bytes; + /* # of free pools + pools not yet carved out of current arena */ +- uint numfreepools = 0; ++ uint numfreepools; + /* # of bytes for arena alignment padding */ +- size_t arena_alignment = 0; ++ size_t arena_alignment; + /* # of bytes in used and full pools used for pool_headers */ +- size_t pool_header_bytes = 0; ++ size_t pool_header_bytes; + /* # of bytes in used and full pools wasted due to quantization, + * i.e. the necessarily leftover space at the ends of used and + * full pools. + */ +- size_t quantization = 0; ++ size_t quantization; + /* # of arenas actually allocated. */ +- size_t narenas = 0; ++ size_t narenas; + /* running total -- should equal narenas * ARENA_SIZE */ + size_t total; + char buf[128]; + ++ if (!_PyMem_PymallocEnabled()) { ++ return 0; ++ } ++ ++ numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT; ++ allocated_bytes = 0; ++ available_bytes = 0; ++ numfreepools = 0; ++ arena_alignment = 0; ++ pool_header_bytes = 0; ++ quantization = 0; ++ narenas = 0; ++ + fprintf(out, "Small block threshold = %d, in %u size classes.\n", + SMALL_REQUEST_THRESHOLD, numclasses); + +diff --git a/Objects/odictobject.c b/Objects/odictobject.c +index bd2a767..6a92f19 100644 +--- a/Objects/odictobject.c ++++ b/Objects/odictobject.c +@@ -861,6 +861,7 @@ odict_or(PyObject *left, PyObject *right) + { + PyTypeObject *type; + PyObject *other; ++ PyObject *new; + if (PyODict_Check(left)) { + type = Py_TYPE(left); + other = right; +@@ -872,7 +873,7 @@ odict_or(PyObject *left, PyObject *right) + if (!PyDict_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; + } +- PyObject *new = PyObject_CallOneArg((PyObject*)type, left); ++ new = PyObject_CallOneArg((PyObject*)type, left); + if (!new) { + return NULL; + } +@@ -896,8 +897,42 @@ odict_inplace_or(PyObject *self, PyObject *other) + /* tp_as_number */ + + static PyNumberMethods odict_as_number = { +- .nb_or = odict_or, +- .nb_inplace_or = odict_inplace_or, ++ 0, /* nb_add */ ++ 0, /* nb_subtract */ ++ 0, /* nb_multiply */ ++ 0, /* nb_remainder */ ++ 0, /* nb_divmod */ ++ 0, /* nb_power */ ++ 0, /* nb_negative */ ++ 0, /* nb_positive */ ++ 0, /* nb_absolute */ ++ 0, /* nb_bool */ ++ 0, /* nb_invert */ ++ 0, /* nb_lshift */ ++ 0, /* nb_rshift */ ++ 0, /* nb_and */ ++ 0, /* nb_xor */ ++ odict_or, /* nb_or */ ++ 0, /* nb_int */ ++ 0, /* nb_reserved */ ++ 0, /* nb_float */ ++ 0, /* nb_inplace_add */ ++ 0, /* nb_inplace_subtract */ ++ 0, /* nb_inplace_multiply */ ++ 0, /* nb_inplace_remainder */ ++ 0, /* nb_inplace_power */ ++ 0, /* nb_inplace_lshift */ ++ 0, /* nb_inplace_rshift */ ++ 0, /* nb_inplace_and */ ++ 0, /* nb_inplace_xor */ ++ odict_inplace_or, /* nb_inplace_or */ ++ 0, /* nb_floor_divide */ ++ 0, /* nb_true_divide */ ++ 0, /* nb_inplace_floor_divide */ ++ 0, /* nb_inplace_true_divide */ ++ 0, /* nb_index */ ++ 0, /* nb_matrix_multiply */ ++ 0, /* nb_inplace_matrix_multiply */ + }; + + +@@ -1797,11 +1832,12 @@ odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored)) + { + /* copy the iterator state */ + odictiterobject tmp = *di; ++ PyObject *list; + Py_XINCREF(tmp.di_odict); + Py_XINCREF(tmp.di_current); + + /* iterate the temporary into a list */ +- PyObject *list = PySequence_List((PyObject*)&tmp); ++ list = PySequence_List((PyObject*)&tmp); + Py_XDECREF(tmp.di_odict); + Py_XDECREF(tmp.di_current); + if (list == NULL) { +@@ -2194,6 +2230,7 @@ static int + mutablemapping_update_arg(PyObject *self, PyObject *arg) + { + int res = 0; ++ PyObject *func; + if (PyDict_CheckExact(arg)) { + PyObject *items = PyDict_Items(arg); + if (items == NULL) { +@@ -2203,22 +2240,22 @@ mutablemapping_update_arg(PyObject *self, PyObject *arg) + Py_DECREF(items); + return res; + } +- PyObject *func; + if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) { + return -1; + } + if (func != NULL) { + PyObject *keys = _PyObject_CallNoArgs(func); ++ PyObject *iterator; ++ PyObject *key; + Py_DECREF(func); + if (keys == NULL) { + return -1; + } +- PyObject *iterator = PyObject_GetIter(keys); ++ iterator = PyObject_GetIter(keys); + Py_DECREF(keys); + if (iterator == NULL) { + return -1; + } +- PyObject *key; + while (res == 0 && (key = PyIter_Next(iterator))) { + PyObject *value = PyObject_GetItem(arg, key); + if (value != NULL) { +@@ -2257,9 +2294,10 @@ static PyObject * + mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs) + { + int res; ++ Py_ssize_t len; + /* first handle args, if any */ + assert(args == NULL || PyTuple_Check(args)); +- Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0; ++ len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0; + if (len > 1) { + const char *msg = "update() takes at most 1 positional argument (%zd given)"; + PyErr_Format(PyExc_TypeError, msg, len); +diff --git a/Objects/picklebufobject.c b/Objects/picklebufobject.c +index aaa852c..2fd4c2b 100644 +--- a/Objects/picklebufobject.c ++++ b/Objects/picklebufobject.c +@@ -139,8 +139,8 @@ picklebuf_releasebuf(PyPickleBufferObject *self, Py_buffer *view) + } + + static PyBufferProcs picklebuf_as_buffer = { +- .bf_getbuffer = (getbufferproc) picklebuf_getbuf, +- .bf_releasebuffer = (releasebufferproc) picklebuf_releasebuf, ++ (getbufferproc) picklebuf_getbuf, /* bf_getbuffer */ ++ (releasebufferproc) picklebuf_releasebuf, /* bf_releasebuffer */ + }; + + /* Methods */ +@@ -148,6 +148,9 @@ static PyBufferProcs picklebuf_as_buffer = { + static PyObject * + picklebuf_raw(PyPickleBufferObject *self, PyObject *Py_UNUSED(ignored)) + { ++ PyObject *m; ++ PyMemoryViewObject *mv; ++ + if (self->view.obj == NULL) { + PyErr_SetString(PyExc_ValueError, + "operation forbidden on released PickleBuffer object"); +@@ -159,11 +162,11 @@ picklebuf_raw(PyPickleBufferObject *self, PyObject *Py_UNUSED(ignored)) + "cannot extract raw buffer from non-contiguous buffer"); + return NULL; + } +- PyObject *m = PyMemoryView_FromObject((PyObject *) self); ++ m = PyMemoryView_FromObject((PyObject *) self); + if (m == NULL) { + return NULL; + } +- PyMemoryViewObject *mv = (PyMemoryViewObject *) m; ++ mv = (PyMemoryViewObject *) m; + assert(mv->view.suboffsets == NULL); + /* Mutate memoryview instance to make it a "raw" memoryview */ + mv->view.format = "B"; +@@ -205,15 +208,52 @@ static PyMethodDef picklebuf_methods[] = { + + PyTypeObject PyPickleBuffer_Type = { + PyVarObject_HEAD_INIT(NULL, 0) +- .tp_name = "pickle.PickleBuffer", +- .tp_doc = PyDoc_STR("Wrapper for potentially out-of-band buffers"), +- .tp_basicsize = sizeof(PyPickleBufferObject), +- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, +- .tp_new = picklebuf_new, +- .tp_dealloc = (destructor) picklebuf_dealloc, +- .tp_traverse = (traverseproc) picklebuf_traverse, +- .tp_clear = (inquiry) picklebuf_clear, +- .tp_weaklistoffset = offsetof(PyPickleBufferObject, weakreflist), +- .tp_as_buffer = &picklebuf_as_buffer, +- .tp_methods = picklebuf_methods, ++ "pickle.PickleBuffer", /* tp_name */ ++ sizeof(PyPickleBufferObject), /* tp_basicsize */ ++ 0, /* tp_itemsize */ ++ (destructor) picklebuf_dealloc, /* tp_dealloc */ ++ 0, /* tp_vectorcall_offset */ ++ 0, /* tp_getattr */ ++ 0, /* tp_setattr */ ++ 0, /* tp_as_async */ ++ 0, /* tp_repr */ ++ 0, /* tp_as_number */ ++ 0, /* tp_as_sequence */ ++ 0, /* tp_as_mapping */ ++ 0, /* tp_hash */ ++ 0, /* tp_call */ ++ 0, /* tp_str */ ++ 0, /* tp_getattro */ ++ 0, /* tp_setattro */ ++ &picklebuf_as_buffer, /* tp_as_buffer */ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ ++ PyDoc_STR("Wrapper for potentially out-of-band buffers"),/* tp_doc */ ++ (traverseproc) picklebuf_traverse, /* tp_traverse */ ++ (inquiry) picklebuf_clear, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ offsetof(PyPickleBufferObject, weakreflist), /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ picklebuf_methods, /* tp_methods */ ++ 0, /* tp_members */ ++ 0, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ 0, /* tp_init */ ++ 0, /* tp_alloc */ ++ picklebuf_new, /* tp_new */ ++ 0, /* tp_free */ ++ 0, /* tp_is_gc */ ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ 0, /* tp_vectorcall */ + }; +diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c +index 5d583b2..6b968d3 100644 +--- a/Objects/rangeobject.c ++++ b/Objects/rangeobject.c +@@ -588,6 +588,7 @@ range_index(rangeobject *r, PyObject *ob) + return NULL; + + if (contains) { ++ PyObject *sidx; + PyObject *idx = PyNumber_Subtract(ob, r->start); + if (idx == NULL) { + return NULL; +@@ -598,7 +599,7 @@ range_index(rangeobject *r, PyObject *ob) + } + + /* idx = (ob - r.start) // r.step */ +- PyObject *sidx = PyNumber_FloorDivide(idx, r->step); ++ sidx = PyNumber_FloorDivide(idx, r->step); + Py_DECREF(idx); + return sidx; + } +@@ -682,7 +683,42 @@ range_bool(rangeobject* self) + } + + static PyNumberMethods range_as_number = { +- .nb_bool = (inquiry)range_bool, ++ 0, /* nb_add */ ++ 0, /* nb_subtract */ ++ 0, /* nb_multiply */ ++ 0, /* nb_remainder */ ++ 0, /* nb_divmod */ ++ 0, /* nb_power */ ++ 0, /* nb_negative */ ++ 0, /* nb_positive */ ++ 0, /* nb_absolute */ ++ (inquiry)range_bool, /* nb_bool */ ++ 0, /* nb_invert */ ++ 0, /* nb_lshift */ ++ 0, /* nb_rshift */ ++ 0, /* nb_and */ ++ 0, /* nb_xor */ ++ 0, /* nb_or */ ++ 0, /* nb_int */ ++ 0, /* nb_reserved */ ++ 0, /* nb_float */ ++ 0, /* nb_inplace_add */ ++ 0, /* nb_inplace_subtract */ ++ 0, /* nb_inplace_multiply */ ++ 0, /* nb_inplace_remainder */ ++ 0, /* nb_inplace_power */ ++ 0, /* nb_inplace_lshift */ ++ 0, /* nb_inplace_rshift */ ++ 0, /* nb_inplace_and */ ++ 0, /* nb_inplace_xor */ ++ 0, /* nb_inplace_or */ ++ 0, /* nb_floor_divide */ ++ 0, /* nb_true_divide */ ++ 0, /* nb_inplace_floor_divide */ ++ 0, /* nb_inplace_true_divide */ ++ 0, /* nb_index */ ++ 0, /* nb_matrix_multiply */ ++ 0, /* nb_inplace_matrix_multiply */ + }; + + static PyObject * range_iter(PyObject *seq); +@@ -752,7 +788,17 @@ PyTypeObject PyRange_Type = { + 0, /* tp_init */ + 0, /* tp_alloc */ + range_new, /* tp_new */ +- .tp_vectorcall = (vectorcallfunc)range_vectorcall ++ 0, /* tp_free */ ++ 0, /* tp_is_gc */ ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ (vectorcallfunc)range_vectorcall /* tp_vectorcall */ + }; + + /*********************** range Iterator **************************/ +diff --git a/Objects/setobject.c b/Objects/setobject.c +index 5fcc957..cd51cc1 100644 +--- a/Objects/setobject.c ++++ b/Objects/setobject.c +@@ -234,6 +234,7 @@ set_table_resize(PySetObject *so, Py_ssize_t minused) + setentry *oldtable, *newtable, *entry; + Py_ssize_t oldmask = so->mask; + size_t newmask; ++ size_t newsize; + int is_oldtable_malloced; + setentry small_copy[PySet_MINSIZE]; + +@@ -241,7 +242,7 @@ set_table_resize(PySetObject *so, Py_ssize_t minused) + + /* Find the smallest table size > minused. */ + /* XXX speed-up with intrinsics */ +- size_t newsize = PySet_MINSIZE; ++ newsize = PySet_MINSIZE; + while (newsize <= (size_t)minused) { + newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1. + } +@@ -770,12 +771,13 @@ static PyObject *setiter_iternext(setiterobject *si); + static PyObject * + setiter_reduce(setiterobject *si, PyObject *Py_UNUSED(ignored)) + { ++ PyObject *list; + /* copy the iterator state */ + setiterobject tmp = *si; + Py_XINCREF(tmp.si_set); + + /* iterate the temporary into a list */ +- PyObject *list = PySequence_List((PyObject*)&tmp); ++ list = PySequence_List((PyObject*)&tmp); + Py_XDECREF(tmp.si_set); + if (list == NULL) { + return NULL; +@@ -951,9 +953,9 @@ PyDoc_STRVAR(update_doc, + static PyObject * + make_new_set(PyTypeObject *type, PyObject *iterable) + { +- assert(PyType_Check(type)); + PySetObject *so; + ++ assert(PyType_Check(type)); + so = (PySetObject *)type->tp_alloc(type, 0); + if (so == NULL) + return NULL; +@@ -1025,16 +1027,19 @@ static PyObject * + frozenset_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) + { ++ Py_ssize_t nargs; ++ PyObject *iterable; ++ + if (!_PyArg_NoKwnames("frozenset", kwnames)) { + return NULL; + } + +- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) { + return NULL; + } + +- PyObject *iterable = (nargs ? args[0] : NULL); ++ iterable = (nargs ? args[0] : NULL); + return make_new_frozenset(_PyType_CAST(type), iterable); + } + +@@ -1770,11 +1775,14 @@ Test whether every element in the set is in other."); + static PyObject * + set_issuperset(PySetObject *so, PyObject *other) + { ++ PyObject *key; ++ PyObject *it; ++ + if (PyAnySet_Check(other)) { + return set_issubset((PySetObject *)other, (PyObject *)so); + } + +- PyObject *key, *it = PyObject_GetIter(other); ++ it = PyObject_GetIter(other); + if (it == NULL) { + return NULL; + } +@@ -2007,13 +2015,15 @@ static PyObject* + set_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) + { ++ Py_ssize_t nargs; ++ + assert(PyType_Check(type)); + + if (!_PyArg_NoKwnames("set", kwnames)) { + return NULL; + } + +- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("set", nargs, 0, 1)) { + return NULL; + } +@@ -2175,7 +2185,16 @@ PyTypeObject PySet_Type = { + PyType_GenericAlloc, /* tp_alloc */ + set_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +- .tp_vectorcall = set_vectorcall, ++ 0, /* tp_is_gc */ ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ set_vectorcall, /* tp_vectorcall */ + }; + + /* frozenset object ********************************************************/ +@@ -2276,7 +2295,16 @@ PyTypeObject PyFrozenSet_Type = { + PyType_GenericAlloc, /* tp_alloc */ + frozenset_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +- .tp_vectorcall = frozenset_vectorcall, ++ 0, /* tp_is_gc */ ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ frozenset_vectorcall, /* tp_vectorcall */ + }; + + +diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c +index 713829d..0beb452 100644 +--- a/Objects/sliceobject.c ++++ b/Objects/sliceobject.c +@@ -113,6 +113,9 @@ void _PySlice_Fini(PyInterpreterState *interp) + PyObject * + PySlice_New(PyObject *start, PyObject *stop, PyObject *step) + { ++ PyInterpreterState *interp; ++ PySliceObject *obj; ++ + if (step == NULL) { + step = Py_None; + } +@@ -123,8 +126,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step) + stop = Py_None; + } + +- PyInterpreterState *interp = _PyInterpreterState_GET(); +- PySliceObject *obj; ++ interp = _PyInterpreterState_GET(); + if (interp->slice_cache != NULL) { + obj = interp->slice_cache; + interp->slice_cache = NULL; +@@ -575,11 +577,14 @@ static PyMethodDef slice_methods[] = { + static PyObject * + slice_richcompare(PyObject *v, PyObject *w, int op) + { ++ PyObject *t1; ++ PyObject *t2; ++ PyObject *res; ++ + if (!PySlice_Check(v) || !PySlice_Check(w)) + Py_RETURN_NOTIMPLEMENTED; + + if (v == w) { +- PyObject *res; + /* XXX Do we really need this shortcut? + There's a unit test for it, but is that fair? */ + switch (op) { +@@ -597,7 +602,7 @@ slice_richcompare(PyObject *v, PyObject *w, int op) + } + + +- PyObject *t1 = PyTuple_Pack(3, ++ t1 = PyTuple_Pack(3, + ((PySliceObject *)v)->start, + ((PySliceObject *)v)->stop, + ((PySliceObject *)v)->step); +@@ -605,7 +610,7 @@ slice_richcompare(PyObject *v, PyObject *w, int op) + return NULL; + } + +- PyObject *t2 = PyTuple_Pack(3, ++ t2 = PyTuple_Pack(3, + ((PySliceObject *)w)->start, + ((PySliceObject *)w)->stop, + ((PySliceObject *)w)->step); +@@ -614,7 +619,7 @@ slice_richcompare(PyObject *v, PyObject *w, int op) + return NULL; + } + +- PyObject *res = PyObject_RichCompare(t1, t2, op); ++ res = PyObject_RichCompare(t1, t2, op); + Py_DECREF(t1); + Py_DECREF(t2); + return res; diff --git a/Objects/stringlib/eq.h b/Objects/stringlib/eq.h index 9c1058b..11ea17d 100644 --- a/Objects/stringlib/eq.h @@ -21676,6 +23017,1595 @@ index bcc2176..d4ff95a 100644 assert(empty != NULL); Py_INCREF(empty); PyTuple_SET_ITEM(out, 0, empty); +diff --git a/Objects/structseq.c b/Objects/structseq.c +index 229e3d8..f763b16 100644 +--- a/Objects/structseq.c ++++ b/Objects/structseq.c +@@ -52,10 +52,11 @@ PyStructSequence_New(PyTypeObject *type) + { + PyStructSequence *obj; + Py_ssize_t size = REAL_SIZE_TP(type), i; ++ Py_ssize_t vsize; + if (size < 0) { + return NULL; + } +- Py_ssize_t vsize = VISIBLE_SIZE_TP(type); ++ vsize = VISIBLE_SIZE_TP(type); + if (vsize < 0) { + return NULL; + } +@@ -88,10 +89,10 @@ PyStructSequence_GetItem(PyObject* op, Py_ssize_t i) + static int + structseq_traverse(PyStructSequence *obj, visitproc visit, void *arg) + { ++ Py_ssize_t i, size; + if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HEAPTYPE) { + Py_VISIT(Py_TYPE(obj)); + } +- Py_ssize_t i, size; + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_VISIT(obj->ob_item[i]); +@@ -103,9 +104,10 @@ static void + structseq_dealloc(PyStructSequence *obj) + { + Py_ssize_t i, size; ++ PyTypeObject *tp; + PyObject_GC_UnTrack(obj); + +- PyTypeObject *tp = Py_TYPE(obj); ++ tp = Py_TYPE(obj); + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_XDECREF(obj->ob_item[i]); +@@ -233,6 +235,9 @@ structseq_repr(PyStructSequence *obj) + { + PyTypeObject *typ = Py_TYPE(obj); + _PyUnicodeWriter writer; ++ Py_ssize_t i; ++ PyObject *value; ++ PyObject *repr; + + /* Write "typename(" */ + PyObject *type_name = PyUnicode_DecodeUTF8(typ->tp_name, +@@ -258,7 +263,9 @@ structseq_repr(PyStructSequence *obj) + goto error; + } + +- for (Py_ssize_t i=0; i < VISIBLE_SIZE(obj); i++) { ++ for (i=0; i < VISIBLE_SIZE(obj); i++) { ++ const char *name_utf8; ++ PyObject *name; + if (i > 0) { + /* Write ", " */ + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { +@@ -267,14 +274,14 @@ structseq_repr(PyStructSequence *obj) + } + + /* Write "name=repr" */ +- const char *name_utf8 = typ->tp_members[i].name; ++ name_utf8 = typ->tp_members[i].name; + if (name_utf8 == NULL) { + PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %zd name is NULL" + " for type %.500s", i, typ->tp_name); + goto error; + } + +- PyObject *name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL); ++ name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL); + if (name == NULL) { + goto error; + } +@@ -288,9 +295,9 @@ structseq_repr(PyStructSequence *obj) + goto error; + } + +- PyObject *value = PyStructSequence_GET_ITEM(obj, i); ++ value = PyStructSequence_GET_ITEM(obj, i); + assert(value != NULL); +- PyObject *repr = PyObject_Repr(value); ++ repr = PyObject_Repr(value); + if (repr == NULL) { + goto error; + } +@@ -379,6 +386,8 @@ static int + initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict, + Py_ssize_t n_members, Py_ssize_t n_unnamed_members) { + PyObject *v; ++ Py_ssize_t i, k; ++ PyObject* keys; + + #define SET_DICT_FROM_SIZE(key, value) \ + do { \ +@@ -398,17 +407,17 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict, + SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members); + + // Prepare and set __match_args__ +- Py_ssize_t i, k; +- PyObject* keys = PyTuple_New(desc->n_in_sequence); ++ keys = PyTuple_New(desc->n_in_sequence); + if (keys == NULL) { + return -1; + } + + for (i = k = 0; i < desc->n_in_sequence; ++i) { ++ PyObject* new_member; + if (desc->fields[i].name == PyStructSequence_UnnamedField) { + continue; + } +- PyObject* new_member = PyUnicode_FromString(desc->fields[i].name); ++ new_member = PyUnicode_FromString(desc->fields[i].name); + if (new_member == NULL) { + goto error; + } +@@ -578,14 +587,22 @@ _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags) + initialize_members(desc, members, n_members); + + /* Initialize Slots */ +- slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc}; +- slots[1] = (PyType_Slot){Py_tp_repr, (reprfunc)structseq_repr}; +- slots[2] = (PyType_Slot){Py_tp_doc, (void *)desc->doc}; +- slots[3] = (PyType_Slot){Py_tp_methods, structseq_methods}; +- slots[4] = (PyType_Slot){Py_tp_new, structseq_new}; +- slots[5] = (PyType_Slot){Py_tp_members, members}; +- slots[6] = (PyType_Slot){Py_tp_traverse, (traverseproc)structseq_traverse}; +- slots[7] = (PyType_Slot){0, 0}; ++ slots[0].slot = Py_tp_dealloc; ++ slots[0].pfunc = (destructor)structseq_dealloc; ++ slots[1].slot = Py_tp_repr; ++ slots[1].pfunc = (reprfunc)structseq_repr; ++ slots[2].slot = Py_tp_doc; ++ slots[2].pfunc = (void *)desc->doc; ++ slots[3].slot = Py_tp_methods; ++ slots[3].pfunc = structseq_methods; ++ slots[4].slot = Py_tp_new; ++ slots[4].pfunc = structseq_new; ++ slots[5].slot = Py_tp_members; ++ slots[5].pfunc = members; ++ slots[6].slot = Py_tp_traverse; ++ slots[6].pfunc = (traverseproc)structseq_traverse; ++ slots[7].slot = 0; ++ slots[7].pfunc = 0; + + /* Initialize Spec */ + /* The name in this PyType_Spec is statically allocated so it is */ +diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c +index 1e82a5b..04a25f7 100644 +--- a/Objects/tupleobject.c ++++ b/Objects/tupleobject.c +@@ -32,6 +32,7 @@ static inline int maybe_freelist_push(PyTupleObject *); + static PyTupleObject * + tuple_alloc(Py_ssize_t size) + { ++ PyTupleObject *op; + if (size < 0) { + PyErr_BadInternalCall(); + return NULL; +@@ -40,7 +41,7 @@ tuple_alloc(Py_ssize_t size) + assert(size != 0); // The empty tuple is statically allocated. + #endif + +- PyTupleObject *op = maybe_freelist_pop(size); ++ op = maybe_freelist_pop(size); + if (op == NULL) { + /* Check for overflow */ + if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) - +@@ -69,6 +70,7 @@ PyObject * + PyTuple_New(Py_ssize_t size) + { + PyTupleObject *op; ++ Py_ssize_t i; + if (size == 0) { + return tuple_get_empty(); + } +@@ -76,7 +78,7 @@ PyTuple_New(Py_ssize_t size) + if (op == NULL) { + return NULL; + } +- for (Py_ssize_t i = 0; i < size; i++) { ++ for (i = 0; i < size; i++) { + op->ob_item[i] = NULL; + } + _PyObject_GC_TRACK(op); +@@ -157,13 +159,14 @@ PyTuple_Pack(Py_ssize_t n, ...) + PyObject *o; + PyObject **items; + va_list vargs; ++ PyTupleObject *result; + + if (n == 0) { + return tuple_get_empty(); + } + + va_start(vargs, n); +- PyTupleObject *result = tuple_alloc(n); ++ result = tuple_alloc(n); + if (result == NULL) { + va_end(vargs); + return NULL; +@@ -185,6 +188,7 @@ PyTuple_Pack(Py_ssize_t n, ...) + static void + tupledealloc(PyTupleObject *op) + { ++ Py_ssize_t i; + if (Py_SIZE(op) == 0) { + /* The empty tuple is statically allocated. */ + if (op == &_Py_SINGLETON(tuple_empty)) { +@@ -203,7 +207,7 @@ tupledealloc(PyTupleObject *op) + PyObject_GC_UnTrack(op); + Py_TRASHCAN_BEGIN(op, tupledealloc) + +- Py_ssize_t i = Py_SIZE(op); ++ i = Py_SIZE(op); + while (--i >= 0) { + Py_XDECREF(op->ob_item[i]); + } +@@ -374,16 +378,19 @@ tupleitem(PyTupleObject *a, Py_ssize_t i) + PyObject * + _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) + { ++ PyTupleObject *tuple; ++ PyObject **dst; ++ Py_ssize_t i; + if (n == 0) { + return tuple_get_empty(); + } + +- PyTupleObject *tuple = tuple_alloc(n); ++ tuple = tuple_alloc(n); + if (tuple == NULL) { + return NULL; + } +- PyObject **dst = tuple->ob_item; +- for (Py_ssize_t i = 0; i < n; i++) { ++ dst = tuple->ob_item; ++ for (i = 0; i < n; i++) { + PyObject *item = src[i]; + Py_INCREF(item); + dst[i] = item; +@@ -395,18 +402,21 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) + PyObject * + _PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n) + { ++ PyTupleObject *tuple; ++ Py_ssize_t i; ++ PyObject **dst; + if (n == 0) { + return tuple_get_empty(); + } +- PyTupleObject *tuple = tuple_alloc(n); ++ tuple = tuple_alloc(n); + if (tuple == NULL) { +- for (Py_ssize_t i = 0; i < n; i++) { ++ for (i = 0; i < n; i++) { + Py_DECREF(src[i]); + } + return NULL; + } +- PyObject **dst = tuple->ob_item; +- for (Py_ssize_t i = 0; i < n; i++) { ++ dst = tuple->ob_item; ++ for (i = 0; i < n; i++) { + PyObject *item = src[i]; + dst[i] = item; + } +@@ -448,6 +458,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb) + Py_ssize_t i; + PyObject **src, **dest; + PyTupleObject *np; ++ PyTupleObject *b; + if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) { + Py_INCREF(bb); + return bb; +@@ -458,7 +469,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb) + Py_TYPE(bb)->tp_name); + return NULL; + } +- PyTupleObject *b = (PyTupleObject *)bb; ++ b = (PyTupleObject *)bb; + + if (Py_SIZE(b) == 0 && PyTuple_CheckExact(a)) { + Py_INCREF(a); +@@ -497,6 +508,8 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) + { + Py_ssize_t size; + PyTupleObject *np; ++ PyObject **dest; ++ PyObject **dest_end; + if (Py_SIZE(a) == 0 || n == 1) { + if (PyTuple_CheckExact(a)) { + /* Since tuples are immutable, we can return a shared +@@ -514,8 +527,8 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) + np = tuple_alloc(size); + if (np == NULL) + return NULL; +- PyObject **dest = np->ob_item; +- PyObject **dest_end = dest + size; ++ dest = np->ob_item; ++ dest_end = dest + size; + if (Py_SIZE(a) == 1) { + PyObject *elem = a->ob_item[0]; + Py_SET_REFCNT(elem, Py_REFCNT(elem) + n); +@@ -713,11 +726,13 @@ static PyObject * + tuple_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) + { ++ Py_ssize_t nargs; ++ + if (!_PyArg_NoKwnames("tuple", kwnames)) { + return NULL; + } + +- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("tuple", nargs, 0, 1)) { + return NULL; + } +@@ -901,7 +916,16 @@ PyTypeObject PyTuple_Type = { + 0, /* tp_alloc */ + tuple_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +- .tp_vectorcall = tuple_vectorcall, ++ 0, /* tp_is_gc */ ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ tuple_vectorcall, /* tp_vectorcall */ + }; + + /* The following function breaks the notion that tuples are immutable: +@@ -1213,6 +1237,7 @@ maybe_freelist_push(PyTupleObject *op) + { + #if PyTuple_NFREELISTS > 0 + PyInterpreterState *interp = _PyInterpreterState_GET(); ++ Py_ssize_t index; + #ifdef Py_DEBUG + /* maybe_freelist_push() must not be called after maybe_freelist_fini(). */ + assert(!FREELIST_FINALIZED); +@@ -1220,7 +1245,7 @@ maybe_freelist_push(PyTupleObject *op) + if (Py_SIZE(op) == 0) { + return 0; + } +- Py_ssize_t index = Py_SIZE(op) - 1; ++ index = Py_SIZE(op) - 1; + if (index < PyTuple_NFREELISTS + && STATE.numfree[index] < PyTuple_MAXFREELIST + && Py_IS_TYPE(op, &PyTuple_Type)) +@@ -1241,7 +1266,8 @@ static void + maybe_freelist_clear(PyInterpreterState *interp, int fini) + { + #if PyTuple_NFREELISTS > 0 +- for (Py_ssize_t i = 0; i < PyTuple_NFREELISTS; i++) { ++ Py_ssize_t i; ++ for (i = 0; i < PyTuple_NFREELISTS; i++) { + PyTupleObject *p = STATE.free_list[i]; + STATE.free_list[i] = NULL; + STATE.numfree[i] = fini ? -1 : 0; +@@ -1260,7 +1286,8 @@ _PyTuple_DebugMallocStats(FILE *out) + { + #if PyTuple_NFREELISTS > 0 + PyInterpreterState *interp = _PyInterpreterState_GET(); +- for (int i = 0; i < PyTuple_NFREELISTS; i++) { ++ int i; ++ for (i = 0; i < PyTuple_NFREELISTS; i++) { + int len = i + 1; + char buf[128]; + PyOS_snprintf(buf, sizeof(buf), +diff --git a/Objects/typeobject.c b/Objects/typeobject.c +index 9dfad5f..11c682f 100644 +--- a/Objects/typeobject.c ++++ b/Objects/typeobject.c +@@ -211,7 +211,8 @@ get_type_cache(void) + static void + type_cache_clear(struct type_cache *cache, PyObject *value) + { +- for (Py_ssize_t i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { ++ Py_ssize_t i; ++ for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { + struct type_cache_entry *entry = &cache->hashtable[i]; + entry->version = 0; + Py_XSETREF(entry->name, _Py_XNewRef(value)); +@@ -224,7 +225,8 @@ void + _PyType_InitCache(PyInterpreterState *interp) + { + struct type_cache *cache = &interp->type_cache; +- for (Py_ssize_t i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { ++ Py_ssize_t i; ++ for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { + struct type_cache_entry *entry = &cache->hashtable[i]; + assert(entry->name == NULL); + +@@ -283,6 +285,11 @@ _PyTypes_Fini(PyInterpreterState *interp) + void + PyType_Modified(PyTypeObject *type) + { ++ PyObject *subclasses; ++ Py_ssize_t i; ++ PyObject *ref; ++ PyObject *obj; ++ + /* Invalidate any cached data for the specified type and all + subclasses. This function is called after the base + classes, mro, or attributes of the type are altered. +@@ -302,15 +309,14 @@ PyType_Modified(PyTypeObject *type) + return; + } + +- PyObject *subclasses = type->tp_subclasses; ++ subclasses = type->tp_subclasses; + if (subclasses != NULL) { + assert(PyDict_CheckExact(subclasses)); + +- Py_ssize_t i = 0; +- PyObject *ref; ++ i = 0; + while (PyDict_Next(subclasses, &i, NULL, &ref)) { + assert(PyWeakref_CheckRef(ref)); +- PyObject *obj = PyWeakref_GET_OBJECT(ref); ++ obj = PyWeakref_GET_OBJECT(ref); + if (obj == Py_None) { + continue; + } +@@ -342,6 +348,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { + + if (custom) { + PyObject *mro_meth, *type_mro_meth; ++ int custom_mro; + mro_meth = lookup_maybe_method( + (PyObject *)type, &_Py_ID(mro), &unbound); + if (mro_meth == NULL) { +@@ -353,7 +360,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { + Py_DECREF(mro_meth); + goto clear; + } +- int custom_mro = (mro_meth != type_mro_meth); ++ custom_mro = (mro_meth != type_mro_meth); + Py_DECREF(mro_meth); + Py_DECREF(type_mro_meth); + if (custom_mro) { +@@ -378,6 +385,9 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { + static int + assign_version_tag(struct type_cache *cache, PyTypeObject *type) + { ++ PyObject *bases; ++ Py_ssize_t n; ++ Py_ssize_t i; + /* Ensure that the tp_version_tag is valid and set + Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this + must first be done on all super classes. Return 0 if this +@@ -397,9 +407,9 @@ assign_version_tag(struct type_cache *cache, PyTypeObject *type) + type->tp_version_tag = next_version_tag++; + assert (type->tp_version_tag != 0); + +- PyObject *bases = type->tp_bases; +- Py_ssize_t n = PyTuple_GET_SIZE(bases); +- for (Py_ssize_t i = 0; i < n; i++) { ++ bases = type->tp_bases; ++ n = PyTuple_GET_SIZE(bases); ++ for (i = 0; i < n; i++) { + PyObject *b = PyTuple_GET_ITEM(bases, i); + if (!assign_version_tag(cache, _PyType_CAST(b))) + return 0; +@@ -449,8 +459,9 @@ check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *nam + const char * + _PyType_Name(PyTypeObject *type) + { ++ const char *s; + assert(type->tp_name != NULL); +- const char *s = strrchr(type->tp_name, '.'); ++ s = strrchr(type->tp_name, '.'); + if (s == NULL) { + s = type->tp_name; + } +@@ -658,14 +669,17 @@ static int + mro_hierarchy(PyTypeObject *type, PyObject *temp) + { + PyObject *old_mro; ++ PyObject *new_mro; ++ PyObject *tuple; ++ Py_ssize_t n; ++ Py_ssize_t i; + int res = mro_internal(type, &old_mro); + if (res <= 0) { + /* error / reentrance */ + return res; + } +- PyObject *new_mro = type->tp_mro; ++ new_mro = type->tp_mro; + +- PyObject *tuple; + if (old_mro != NULL) { + tuple = PyTuple_Pack(3, type, new_mro, old_mro); + } +@@ -705,8 +719,8 @@ mro_hierarchy(PyTypeObject *type, PyObject *temp) + return -1; + } + +- Py_ssize_t n = PyList_GET_SIZE(subclasses); +- for (Py_ssize_t i = 0; i < n; i++) { ++ n = PyList_GET_SIZE(subclasses); ++ for (i = 0; i < n; i++) { + PyTypeObject *subclass = _PyType_CAST(PyList_GET_ITEM(subclasses, i)); + res = mro_hierarchy(subclass, temp); + if (res < 0) { +@@ -722,6 +736,14 @@ mro_hierarchy(PyTypeObject *type, PyObject *temp) + static int + type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) + { ++ Py_ssize_t n; ++ Py_ssize_t i; ++ PyTypeObject *new_base; ++ PyObject *old_bases; ++ PyTypeObject *old_base; ++ PyObject *temp; ++ int res; ++ + // Check arguments + if (!check_set_special_type_attr(type, new_bases, "__bases__")) { + return -1; +@@ -740,16 +762,17 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) + type->tp_name); + return -1; + } +- Py_ssize_t n = PyTuple_GET_SIZE(new_bases); +- for (Py_ssize_t i = 0; i < n; i++) { ++ n = PyTuple_GET_SIZE(new_bases); ++ for (i = 0; i < n; i++) { + PyObject *ob = PyTuple_GET_ITEM(new_bases, i); ++ PyTypeObject *base; + if (!PyType_Check(ob)) { + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; + } +- PyTypeObject *base = (PyTypeObject*)ob; ++ base = (PyTypeObject*)ob; + + if (PyType_IsSubtype(base, type) || + /* In case of reentering here again through a custom mro() +@@ -770,7 +793,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) + } + + // Compute the new MRO and the new base class +- PyTypeObject *new_base = best_base(new_bases); ++ new_base = best_base(new_bases); + if (new_base == NULL) + return -1; + +@@ -778,14 +801,14 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) + return -1; + } + +- PyObject *old_bases = type->tp_bases; ++ old_bases = type->tp_bases; + assert(old_bases != NULL); +- PyTypeObject *old_base = type->tp_base; ++ old_base = type->tp_base; + + type->tp_bases = Py_NewRef(new_bases); + type->tp_base = (PyTypeObject *)Py_NewRef(new_base); + +- PyObject *temp = PyList_New(0); ++ temp = PyList_New(0); + if (temp == NULL) { + goto bail; + } +@@ -796,7 +819,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) + + /* Take no action in case if type->tp_bases has been replaced + through reentrance. */ +- int res; ++ res = 0; + if (type->tp_bases == new_bases) { + /* any base that was in __bases__ but now isn't, we + need to remove |type| from its tp_subclasses. +@@ -821,7 +844,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) + + undo: + n = PyList_GET_SIZE(temp); +- for (Py_ssize_t i = n - 1; i >= 0; i--) { ++ for (i = n - 1; i >= 0; i--) { + PyTypeObject *cls; + PyObject *new_mro, *old_mro = NULL; + +@@ -906,12 +929,12 @@ type_set_doc(PyTypeObject *type, PyObject *value, void *context) + static PyObject * + type_get_annotations(PyTypeObject *type, void *context) + { ++ PyObject *annotations; + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '__annotations__'", type->tp_name); + return NULL; + } + +- PyObject *annotations; + annotations = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__annotations__)); + if (annotations) { + if (Py_TYPE(annotations)->tp_descr_get) { +@@ -939,6 +962,7 @@ type_get_annotations(PyTypeObject *type, void *context) + static int + type_set_annotations(PyTypeObject *type, PyObject *value, void *context) + { ++ int result; + if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) { + PyErr_Format(PyExc_TypeError, + "cannot set '__annotations__' attribute of immutable type '%s'", +@@ -946,7 +970,6 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context) + return -1; + } + +- int result; + if (value != NULL) { + /* set */ + result = PyDict_SetItem(type->tp_dict, &_Py_ID(__annotations__), value); +@@ -1015,14 +1038,14 @@ static PyGetSetDef type_getsets[] = { + static PyObject * + type_repr(PyTypeObject *type) + { ++ PyObject *mod, *name, *rtn; ++ + if (type->tp_name == NULL) { + // type_repr() called before the type is fully initialized + // by PyType_Ready(). + return PyUnicode_FromFormat("", type); + } + +- PyObject *mod, *name, *rtn; +- + mod = type_module(type, NULL); + if (mod == NULL) + PyErr_Clear(); +@@ -1062,9 +1085,10 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) + /* Special case: type(x) should return Py_TYPE(x) */ + /* We only want type itself to accept the one-argument form (#27157) */ + if (type == &PyType_Type) { ++ Py_ssize_t nargs; + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); +- Py_ssize_t nargs = PyTuple_GET_SIZE(args); ++ nargs = PyTuple_GET_SIZE(args); + + if (nargs == 1 && (kwds == NULL || !PyDict_GET_SIZE(kwds))) { + obj = (PyObject *) Py_TYPE(PyTuple_GET_ITEM(args, 0)); +@@ -1191,6 +1215,7 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg) + { + PyTypeObject *type, *base; + traverseproc basetraverse; ++ int err; + + /* Find the nearest base with a different tp_traverse, + and traverse slots while we're at it */ +@@ -1208,7 +1233,7 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg) + + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + assert(type->tp_dictoffset); +- int err = _PyObject_VisitInstanceAttributes(self, visit, arg); ++ err = _PyObject_VisitInstanceAttributes(self, visit, arg); + if (err) { + return err; + } +@@ -1295,6 +1320,7 @@ subtype_dealloc(PyObject *self) + PyTypeObject *type, *base; + destructor basedealloc; + int has_finalizer; ++ int type_needs_decref; + + /* Extract the type; we expect it to be a heap type */ + type = Py_TYPE(self); +@@ -1303,6 +1329,8 @@ subtype_dealloc(PyObject *self) + /* Test whether the type has GC exactly once */ + + if (!_PyType_IS_GC(type)) { ++ int type_needs_decref; ++ + /* A non GC dynamic type allows certain simplifications: + there's no need to call clear_slots(), or DECREF the dict, + or clear weakrefs. */ +@@ -1331,7 +1359,7 @@ subtype_dealloc(PyObject *self) + + // Don't read type memory after calling basedealloc() since basedealloc() + // can deallocate the type and free its memory. +- int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE ++ type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE + && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + + assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); +@@ -1456,7 +1484,7 @@ subtype_dealloc(PyObject *self) + + // Don't read type memory after calling basedealloc() since basedealloc() + // can deallocate the type and free its memory. +- int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE ++ type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE + && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + + assert(basedealloc); +@@ -1594,6 +1622,7 @@ static PyObject * + lookup_maybe_method(PyObject *self, PyObject *attr, int *unbound) + { + PyObject *res = _PyType_Lookup(Py_TYPE(self), attr); ++ descrgetfunc f; + if (res == NULL) { + return NULL; + } +@@ -1605,7 +1634,7 @@ lookup_maybe_method(PyObject *self, PyObject *attr, int *unbound) + } + else { + *unbound = 0; +- descrgetfunc f = Py_TYPE(res)->tp_descr_get; ++ f = Py_TYPE(res)->tp_descr_get; + if (f == NULL) { + Py_INCREF(res); + } +@@ -1660,16 +1689,21 @@ call_unbound_noarg(int unbound, PyObject *func, PyObject *self) + static PyObject * + vectorcall_method(PyObject *name, PyObject *const *args, Py_ssize_t nargs) + { ++ PyThreadState *tstate; ++ int unbound; ++ PyObject *self; ++ PyObject *func; ++ PyObject *retval; ++ + assert(nargs >= 1); + +- PyThreadState *tstate = _PyThreadState_GET(); +- int unbound; +- PyObject *self = args[0]; +- PyObject *func = lookup_method(self, name, &unbound); ++ tstate = _PyThreadState_GET(); ++ self = args[0]; ++ func = lookup_method(self, name, &unbound); + if (func == NULL) { + return NULL; + } +- PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs); ++ retval = vectorcall_unbound(tstate, unbound, func, args, nargs); + Py_DECREF(func); + return retval; + } +@@ -1680,17 +1714,21 @@ static PyObject * + vectorcall_maybe(PyThreadState *tstate, PyObject *name, + PyObject *const *args, Py_ssize_t nargs) + { ++ int unbound; ++ PyObject *self; ++ PyObject *func; ++ PyObject *retval; ++ + assert(nargs >= 1); + +- int unbound; +- PyObject *self = args[0]; +- PyObject *func = lookup_maybe_method(self, name, &unbound); ++ self = args[0]; ++ func = lookup_maybe_method(self, name, &unbound); + if (func == NULL) { + if (!PyErr_Occurred()) + Py_RETURN_NOTIMPLEMENTED; + return NULL; + } +- PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs); ++ retval = vectorcall_unbound(tstate, unbound, func, args, nargs); + Py_DECREF(func); + return retval; + } +@@ -1910,14 +1948,19 @@ pmerge(PyObject *acc, PyObject **to_merge, Py_ssize_t to_merge_size) + static PyObject * + mro_implementation(PyTypeObject *type) + { ++ PyObject *bases; ++ Py_ssize_t n; ++ Py_ssize_t i; ++ PyObject **to_merge; ++ PyObject *result; + if (!_PyType_IsReady(type)) { + if (PyType_Ready(type) < 0) + return NULL; + } + +- PyObject *bases = type->tp_bases; +- Py_ssize_t n = PyTuple_GET_SIZE(bases); +- for (Py_ssize_t i = 0; i < n; i++) { ++ bases = type->tp_bases; ++ n = PyTuple_GET_SIZE(bases); ++ for (i = 0; i < n; i++) { + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); + if (base->tp_mro == NULL) { + PyErr_Format(PyExc_TypeError, +@@ -1941,7 +1984,7 @@ mro_implementation(PyTypeObject *type) + + Py_INCREF(type); + PyTuple_SET_ITEM(result, 0, (PyObject *) type); +- for (Py_ssize_t i = 0; i < k; i++) { ++ for (i = 0; i < k; i++) { + PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i); + Py_INCREF(cls); + PyTuple_SET_ITEM(result, i + 1, cls); +@@ -1962,19 +2005,19 @@ mro_implementation(PyTypeObject *type) + linearization implied by a base class. The last element of + to_merge is the declared tuple of bases. + */ +- PyObject **to_merge = PyMem_New(PyObject *, n + 1); ++ to_merge = PyMem_New(PyObject *, n + 1); + if (to_merge == NULL) { + PyErr_NoMemory(); + return NULL; + } + +- for (Py_ssize_t i = 0; i < n; i++) { ++ for (i = 0; i < n; i++) { + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); + to_merge[i] = base->tp_mro; + } + to_merge[n] = bases; + +- PyObject *result = PyList_New(1); ++ result = PyList_New(1); + if (result == NULL) { + PyMem_Free(to_merge); + return NULL; +@@ -2019,6 +2062,7 @@ mro_check(PyTypeObject *type, PyObject *mro) + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *obj = PyTuple_GET_ITEM(mro, i); ++ PyTypeObject *base; + if (!PyType_Check(obj)) { + PyErr_Format( + PyExc_TypeError, +@@ -2026,7 +2070,7 @@ mro_check(PyTypeObject *type, PyObject *mro) + Py_TYPE(obj)->tp_name); + return -1; + } +- PyTypeObject *base = (PyTypeObject*)obj; ++ base = (PyTypeObject*)obj; + + if (!PyType_IsSubtype(solid, solid_base(base))) { + PyErr_Format( +@@ -2173,13 +2217,14 @@ best_base(PyObject *bases) + winner = NULL; + for (i = 0; i < n; i++) { + PyObject *base_proto = PyTuple_GET_ITEM(bases, i); ++ PyTypeObject *base_i; + if (!PyType_Check(base_proto)) { + PyErr_SetString( + PyExc_TypeError, + "bases must be types"); + return NULL; + } +- PyTypeObject *base_i = (PyTypeObject *)base_proto; ++ base_i = (PyTypeObject *)base_proto; + + if (!_PyType_IsReady(base_i)) { + if (PyType_Ready(base_i) < 0) +@@ -2535,7 +2580,8 @@ type_new_visit_slots(type_new_ctx *ctx) + { + PyObject *slots = ctx->slots; + Py_ssize_t nslot = ctx->nslot; +- for (Py_ssize_t i = 0; i < nslot; i++) { ++ Py_ssize_t i; ++ for (i = 0; i < nslot; i++) { + PyObject *name = PyTuple_GET_ITEM(slots, i); + if (!valid_identifier(name)) { + return -1; +@@ -2577,13 +2623,17 @@ type_new_copy_slots(type_new_ctx *ctx, PyObject *dict) + + Py_ssize_t new_nslot = nslot - ctx->add_dict - ctx->add_weak; + PyObject *new_slots = PyList_New(new_nslot); ++ Py_ssize_t j; ++ Py_ssize_t i; ++ PyObject *tuple; + if (new_slots == NULL) { + return NULL; + } + +- Py_ssize_t j = 0; +- for (Py_ssize_t i = 0; i < nslot; i++) { ++ j = 0; ++ for (i = 0; i < nslot; i++) { + PyObject *slot = PyTuple_GET_ITEM(slots, i); ++ int r; + if ((ctx->add_dict && _PyUnicode_Equal(slot, &_Py_ID(__dict__))) || + (ctx->add_weak && _PyUnicode_Equal(slot, &_Py_ID(__weakref__)))) + { +@@ -2596,7 +2646,7 @@ type_new_copy_slots(type_new_ctx *ctx, PyObject *dict) + } + PyList_SET_ITEM(new_slots, j, slot); + +- int r = PyDict_Contains(dict, slot); ++ r = PyDict_Contains(dict, slot); + if (r < 0) { + goto error; + } +@@ -2622,7 +2672,7 @@ type_new_copy_slots(type_new_ctx *ctx, PyObject *dict) + goto error; + } + +- PyObject *tuple = PyList_AsTuple(new_slots); ++ tuple = PyList_AsTuple(new_slots); + Py_DECREF(new_slots); + if (tuple == NULL) { + return NULL; +@@ -2641,17 +2691,19 @@ static void + type_new_slots_bases(type_new_ctx *ctx) + { + Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases); ++ Py_ssize_t i; + if (nbases > 1 && + ((ctx->may_add_dict && ctx->add_dict == 0) || + (ctx->may_add_weak && ctx->add_weak == 0))) + { +- for (Py_ssize_t i = 0; i < nbases; i++) { ++ for (i = 0; i < nbases; i++) { + PyObject *obj = PyTuple_GET_ITEM(ctx->bases, i); ++ PyTypeObject *base; + if (obj == (PyObject *)ctx->base) { + /* Skip primary base */ + continue; + } +- PyTypeObject *base = _PyType_CAST(obj); ++ base = _PyType_CAST(obj); + + if (ctx->may_add_dict && ctx->add_dict == 0 && + base->tp_dictoffset != 0) +@@ -2679,6 +2731,8 @@ type_new_slots_bases(type_new_ctx *ctx) + static int + type_new_slots_impl(type_new_ctx *ctx, PyObject *dict) + { ++ PyObject *new_slots; ++ + /* Are slots allowed? */ + if (ctx->nslot > 0 && ctx->base->tp_itemsize != 0) { + PyErr_Format(PyExc_TypeError, +@@ -2691,7 +2745,7 @@ type_new_slots_impl(type_new_ctx *ctx, PyObject *dict) + return -1; + } + +- PyObject *new_slots = type_new_copy_slots(ctx, dict); ++ new_slots = type_new_copy_slots(ctx, dict); + if (new_slots == NULL) { + return -1; + } +@@ -2739,13 +2793,14 @@ type_new_alloc(type_new_ctx *ctx) + { + PyTypeObject *metatype = ctx->metatype; + PyTypeObject *type; ++ PyHeapTypeObject *et; + + // Allocate the type object + type = (PyTypeObject *)metatype->tp_alloc(metatype, ctx->nslot); + if (type == NULL) { + return NULL; + } +- PyHeapTypeObject *et = (PyHeapTypeObject *)type; ++ et = (PyHeapTypeObject *)type; + + // Initialize tp_flags. + // All heap types need GC, since we can create a reference cycle by storing +@@ -2800,6 +2855,8 @@ type_new_set_name(const type_new_ctx *ctx, PyTypeObject *type) + static int + type_new_set_module(PyTypeObject *type) + { ++ PyObject *globals; ++ PyObject *module; + int r = PyDict_Contains(type->tp_dict, &_Py_ID(__module__)); + if (r < 0) { + return -1; +@@ -2808,12 +2865,12 @@ type_new_set_module(PyTypeObject *type) + return 0; + } + +- PyObject *globals = PyEval_GetGlobals(); ++ globals = PyEval_GetGlobals(); + if (globals == NULL) { + return 0; + } + +- PyObject *module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); ++ module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + if (module == NULL) { + if (PyErr_Occurred()) { + return -1; +@@ -2864,6 +2921,9 @@ type_new_set_ht_name(PyTypeObject *type) + static int + type_new_set_doc(PyTypeObject *type) + { ++ const char *doc_str; ++ Py_ssize_t size; ++ char *tp_doc; + PyObject *doc = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__doc__)); + if (doc == NULL) { + if (PyErr_Occurred()) { +@@ -2877,14 +2937,14 @@ type_new_set_doc(PyTypeObject *type) + return 0; + } + +- const char *doc_str = PyUnicode_AsUTF8(doc); ++ doc_str = PyUnicode_AsUTF8(doc); + if (doc_str == NULL) { + return -1; + } + + // Silently truncate the docstring if it contains a null byte +- Py_ssize_t size = strlen(doc_str) + 1; +- char *tp_doc = (char *)PyObject_Malloc(size); ++ size = strlen(doc_str) + 1; ++ tp_doc = (char *)PyObject_Malloc(size); + if (tp_doc == NULL) { + PyErr_NoMemory(); + return -1; +@@ -2899,6 +2959,7 @@ type_new_set_doc(PyTypeObject *type) + static int + type_new_staticmethod(PyTypeObject *type, PyObject *attr) + { ++ PyObject *static_func; + PyObject *func = PyDict_GetItemWithError(type->tp_dict, attr); + if (func == NULL) { + if (PyErr_Occurred()) { +@@ -2910,7 +2971,7 @@ type_new_staticmethod(PyTypeObject *type, PyObject *attr) + return 0; + } + +- PyObject *static_func = PyStaticMethod_New(func); ++ static_func = PyStaticMethod_New(func); + if (static_func == NULL) { + return -1; + } +@@ -2926,6 +2987,7 @@ type_new_staticmethod(PyTypeObject *type, PyObject *attr) + static int + type_new_classmethod(PyTypeObject *type, PyObject *attr) + { ++ PyObject *method; + PyObject *func = PyDict_GetItemWithError(type->tp_dict, attr); + if (func == NULL) { + if (PyErr_Occurred()) { +@@ -2937,7 +2999,7 @@ type_new_classmethod(PyTypeObject *type, PyObject *attr) + return 0; + } + +- PyObject *method = PyClassMethod_New(func); ++ method = PyClassMethod_New(func); + if (method == NULL) { + return -1; + } +@@ -2955,12 +3017,13 @@ type_new_classmethod(PyTypeObject *type, PyObject *attr) + static int + type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) + { ++ Py_ssize_t i; + PyHeapTypeObject *et = (PyHeapTypeObject *)type; + Py_ssize_t slotoffset = ctx->base->tp_basicsize; + if (et->ht_slots != NULL) { + PyMemberDef *mp = _PyHeapType_GET_MEMBERS(et); + Py_ssize_t nslot = PyTuple_GET_SIZE(et->ht_slots); +- for (Py_ssize_t i = 0; i < nslot; i++, mp++) { ++ for (i = 0; i < nslot; i++, mp++) { + mp->name = PyUnicode_AsUTF8( + PyTuple_GET_ITEM(et->ht_slots, i)); + if (mp->name == NULL) { +@@ -3108,6 +3171,7 @@ type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type) + static int + type_new_get_slots(type_new_ctx *ctx, PyObject *dict) + { ++ PyObject *new_slots; + PyObject *slots = PyDict_GetItemWithError(dict, &_Py_ID(__slots__)); + if (slots == NULL) { + if (PyErr_Occurred()) { +@@ -3119,7 +3183,6 @@ type_new_get_slots(type_new_ctx *ctx, PyObject *dict) + } + + // Make it into a tuple +- PyObject *new_slots; + if (PyUnicode_Check(slots)) { + new_slots = PyTuple_Pack(1, slots); + } +@@ -3140,6 +3203,8 @@ static PyTypeObject* + type_new_init(type_new_ctx *ctx) + { + PyObject *dict = PyDict_Copy(ctx->orig_dict); ++ PyTypeObject *type; ++ PyHeapTypeObject *et; + if (dict == NULL) { + goto error; + } +@@ -3153,14 +3218,14 @@ type_new_init(type_new_ctx *ctx) + goto error; + } + +- PyTypeObject *type = type_new_alloc(ctx); ++ type = type_new_alloc(ctx); + if (type == NULL) { + goto error; + } + + type->tp_dict = dict; + +- PyHeapTypeObject *et = (PyHeapTypeObject*)type; ++ et = (PyHeapTypeObject*)type; + et->ht_slots = ctx->slots; + ctx->slots = NULL; + +@@ -3215,10 +3280,14 @@ static int + type_new_get_bases(type_new_ctx *ctx, PyObject **type) + { + Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases); ++ Py_ssize_t i; ++ PyTypeObject *winner; ++ PyTypeObject *base; + if (nbases == 0) { ++ PyObject *new_bases; + // Adjust for empty tuple bases + ctx->base = &PyBaseObject_Type; +- PyObject *new_bases = PyTuple_Pack(1, ctx->base); ++ new_bases = PyTuple_Pack(1, ctx->base); + if (new_bases == NULL) { + return -1; + } +@@ -3226,12 +3295,12 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) + return 0; + } + +- for (Py_ssize_t i = 0; i < nbases; i++) { ++ for (i = 0; i < nbases; i++) { + PyObject *base = PyTuple_GET_ITEM(ctx->bases, i); ++ PyObject *mro_entries; + if (PyType_Check(base)) { + continue; + } +- PyObject *mro_entries; + if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__), + &mro_entries) < 0) { + return -1; +@@ -3246,7 +3315,6 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) + } + + // Search the bases for the proper metatype to deal with this +- PyTypeObject *winner; + winner = _PyType_CalculateMetaclass(ctx->metatype, ctx->bases); + if (winner == NULL) { + return -1; +@@ -3266,7 +3334,7 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) + } + + /* Calculate best base, and check that all bases are type objects */ +- PyTypeObject *base = best_base(ctx->bases); ++ base = best_base(ctx->bases); + if (base == NULL) { + return -1; + } +@@ -3280,11 +3348,15 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) + static PyObject * + type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) + { ++ PyObject *name, *bases, *orig_dict; ++ type_new_ctx ctx; ++ PyObject *type; ++ int res; ++ + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); + + /* Parse arguments: (name, bases, dict) */ +- PyObject *name, *bases, *orig_dict; + if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", + &name, + &PyTuple_Type, &bases, +@@ -3293,22 +3365,15 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) + return NULL; + } + +- type_new_ctx ctx = { +- .metatype = metatype, +- .args = args, +- .kwds = kwds, +- .orig_dict = orig_dict, +- .name = name, +- .bases = bases, +- .base = NULL, +- .slots = NULL, +- .nslot = 0, +- .add_dict = 0, +- .add_weak = 0, +- .may_add_dict = 0, +- .may_add_weak = 0}; +- PyObject *type = NULL; +- int res = type_new_get_bases(&ctx, &type); ++ memset(&ctx, 0, sizeof(ctx)); ++ ctx.metatype = metatype; ++ ctx.args = args; ++ ctx.kwds = kwds; ++ ctx.orig_dict = orig_dict; ++ ctx.name = name; ++ ctx.bases = bases; ++ type = NULL; ++ res = type_new_get_bases(&ctx, &type); + if (res < 0) { + assert(PyErr_Occurred()); + return NULL; +@@ -3330,7 +3395,10 @@ static PyObject * + type_vectorcall(PyObject *metatype, PyObject *const *args, + size_t nargsf, PyObject *kwnames) + { +- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ Py_ssize_t nargs; ++ PyThreadState *tstate; ++ ++ nargs = PyVectorcall_NARGS(nargsf); + if (nargs == 1 && metatype == (PyObject *)&PyType_Type){ + if (!_PyArg_NoKwnames("type", kwnames)) { + return NULL; +@@ -3339,7 +3407,7 @@ type_vectorcall(PyObject *metatype, PyObject *const *args, + } + /* In other (much less common) cases, fall back to + more flexible calling conventions. */ +- PyThreadState *tstate = _PyThreadState_GET(); ++ tstate = _PyThreadState_GET(); + return _PyObject_MakeTpCall(tstate, metatype, args, nargs, kwnames); + } + +@@ -3376,12 +3444,15 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) + Py_ssize_t nmembers, weaklistoffset, dictoffset, vectorcalloffset; + char *res_start; + short slot_offset, subslot_offset; ++ const char *s; ++ Py_ssize_t name_buf_len; + + nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0; + for (slot = spec->slots; slot->slot; slot++) { + if (slot->slot == Py_tp_members) { ++ const PyMemberDef *memb; + nmembers = 0; +- for (const PyMemberDef *memb = slot->pfunc; memb->name != NULL; memb++) { ++ for (memb = slot->pfunc; memb->name != NULL; memb++) { + nmembers++; + if (strcmp(memb->name, "__weaklistoffset__") == 0) { + // The PyMemberDef must be a Py_ssize_t and readonly +@@ -3421,7 +3492,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) + type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; + + /* Set the type name and qualname */ +- const char *s = strrchr(spec->name, '.'); ++ s = strrchr(spec->name, '.'); + if (s == NULL) { + s = spec->name; + } +@@ -3444,7 +3515,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) + * So, we use a separate buffer, _ht_tpname, that's always + * deallocated with the type (if it's non-NULL). + */ +- Py_ssize_t name_buf_len = strlen(spec->name) + 1; ++ name_buf_len = strlen(spec->name) + 1; + res->_ht_tpname = PyMem_Malloc(name_buf_len); + if (res->_ht_tpname == NULL) { + goto fail; +@@ -3525,14 +3596,16 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) + continue; + } + else if (slot->slot == Py_tp_doc) { ++ size_t len; ++ char *tp_doc; + /* For the docstring slot, which usually points to a static string + literal, we need to make a copy */ + if (slot->pfunc == NULL) { + type->tp_doc = NULL; + continue; + } +- size_t len = strlen(slot->pfunc)+1; +- char *tp_doc = PyObject_Malloc(len); ++ len = strlen(slot->pfunc)+1; ++ tp_doc = PyObject_Malloc(len); + if (tp_doc == NULL) { + type->tp_doc = NULL; + PyErr_NoMemory(); +@@ -3671,6 +3744,7 @@ PyType_GetSlot(PyTypeObject *type, int slot) + PyObject * + PyType_GetModule(PyTypeObject *type) + { ++ PyHeapTypeObject *et; + assert(PyType_Check(type)); + if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { + PyErr_Format( +@@ -3680,7 +3754,7 @@ PyType_GetModule(PyTypeObject *type) + return NULL; + } + +- PyHeapTypeObject* et = (PyHeapTypeObject*)type; ++ et = (PyHeapTypeObject*)type; + if (!et->ht_module) { + PyErr_Format( + PyExc_TypeError, +@@ -3709,9 +3783,14 @@ PyType_GetModuleState(PyTypeObject *type) + PyObject * + PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) + { ++ PyObject *mro; ++ Py_ssize_t n; ++ Py_ssize_t i; ++ PyHeapTypeObject *ht; ++ PyObject *module; + assert(PyType_Check(type)); + +- PyObject *mro = type->tp_mro; ++ mro = type->tp_mro; + // The type must be ready + assert(mro != NULL); + assert(PyTuple_Check(mro)); +@@ -3719,16 +3798,16 @@ PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) + // to check i < PyTuple_GET_SIZE(mro) at the first loop iteration. + assert(PyTuple_GET_SIZE(mro) >= 1); + +- Py_ssize_t n = PyTuple_GET_SIZE(mro); +- for (Py_ssize_t i = 0; i < n; i++) { ++ n = PyTuple_GET_SIZE(mro); ++ for (i = 0; i < n; i++) { + PyObject *super = PyTuple_GET_ITEM(mro, i); + if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) { + // Static types in the MRO need to be skipped + continue; + } + +- PyHeapTypeObject *ht = (PyHeapTypeObject*)super; +- PyObject *module = ht->ht_module; ++ ht = (PyHeapTypeObject*)super; ++ module = ht->ht_module; + if (module && _PyModule_GetDef(module) == def) { + return module; + } +@@ -3749,6 +3828,10 @@ static PyObject * + find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) + { + Py_hash_t hash; ++ PyObject *mro; ++ PyObject *res; ++ Py_ssize_t n; ++ Py_ssize_t i; + if (!PyUnicode_CheckExact(name) || + (hash = _PyASCIIObject_CAST(name)->hash) == -1) + { +@@ -3760,7 +3843,7 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) + } + + /* Look in tp_dict of types in MRO */ +- PyObject *mro = type->tp_mro; ++ mro = type->tp_mro; + if (mro == NULL) { + if ((type->tp_flags & Py_TPFLAGS_READYING) == 0) { + if (PyType_Ready(type) < 0) { +@@ -3775,12 +3858,12 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) + } + } + +- PyObject *res = NULL; ++ res = NULL; + /* Keep a strong reference to mro because type->tp_mro can be replaced + during dict lookup, e.g. when comparing to non-string keys. */ + Py_INCREF(mro); +- Py_ssize_t n = PyTuple_GET_SIZE(mro); +- for (Py_ssize_t i = 0; i < n; i++) { ++ n = PyTuple_GET_SIZE(mro); ++ for (i = 0; i < n; i++) { + PyObject *base = PyTuple_GET_ITEM(mro, i); + PyObject *dict = _PyType_CAST(base)->tp_dict; + assert(dict && PyDict_Check(dict)); +@@ -3840,8 +3923,9 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) + } + + if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(cache, type)) { ++ struct type_cache_entry *entry; + h = MCACHE_HASH_METHOD(type, name); +- struct type_cache_entry *entry = &cache->hashtable[h]; ++ entry = &cache->hashtable[h]; + entry->version = type->tp_version_tag; + entry->value = res; /* borrowed */ + assert(_PyASCIIObject_CAST(name)->hash != -1); +@@ -3936,9 +4020,11 @@ type_getattro(PyTypeObject *type, PyObject *name) + * type and its bases */ + attribute = _PyType_Lookup(type, name); + if (attribute != NULL) { ++ descrgetfunc local_get; ++ + /* Implement descriptor functionality, if any */ + Py_INCREF(attribute); +- descrgetfunc local_get = Py_TYPE(attribute)->tp_descr_get; ++ local_get = Py_TYPE(attribute)->tp_descr_get; + + Py_XDECREF(meta_attribute); + +@@ -4079,6 +4165,8 @@ _PyStaticType_Dealloc(PyTypeObject *type) + static void + type_dealloc(PyTypeObject *type) + { ++ PyHeapTypeObject *et; ++ + // Assert this is a heap-allocated type object + _PyObject_ASSERT((PyObject *)type, type->tp_flags & Py_TPFLAGS_HEAPTYPE); + +@@ -4102,7 +4190,7 @@ type_dealloc(PyTypeObject *type) + */ + PyObject_Free((char *)type->tp_doc); + +- PyHeapTypeObject *et = (PyHeapTypeObject *)type; ++ et = (PyHeapTypeObject *)type; + Py_XDECREF(et->ht_name); + Py_XDECREF(et->ht_qualname); + Py_XDECREF(et->ht_slots); +@@ -4118,12 +4206,16 @@ type_dealloc(PyTypeObject *type) + PyObject* + _PyType_GetSubclasses(PyTypeObject *self) + { ++ PyObject *subclasses; ++ Py_ssize_t i; + PyObject *list = PyList_New(0); ++ PyObject *ref; // borrowed ref ++ PyObject *obj; + if (list == NULL) { + return NULL; + } + +- PyObject *subclasses = self->tp_subclasses; // borrowed ref ++ subclasses = self->tp_subclasses; // borrowed ref + if (subclasses == NULL) { + return list; + } +@@ -4131,11 +4223,10 @@ _PyType_GetSubclasses(PyTypeObject *self) + // The loop cannot modify tp_subclasses, there is no need + // to hold a strong reference (use a borrowed reference). + +- Py_ssize_t i = 0; +- PyObject *ref; // borrowed ref ++ i = 0; + while (PyDict_Next(subclasses, &i, NULL, &ref)) { + assert(PyWeakref_CheckRef(ref)); +- PyObject *obj = PyWeakref_GET_OBJECT(ref); // borrowed ref ++ obj = PyWeakref_GET_OBJECT(ref); // borrowed ref + if (obj == Py_None) { + continue; + } +@@ -4380,7 +4471,22 @@ type_is_gc(PyTypeObject *type) + + + static PyNumberMethods type_as_number = { +- .nb_or = _Py_union_type_or, // Add __or__ function ++ 0, /* nb_add */ ++ 0, /* nb_subtract */ ++ 0, /* nb_multiply */ ++ 0, /* nb_remainder */ ++ 0, /* nb_divmod */ ++ 0, /* nb_power */ ++ 0, /* nb_negative */ ++ 0, /* nb_positive */ ++ 0, /* nb_absolute */ ++ 0, /* nb_bool */ ++ 0, /* nb_invert */ ++ 0, /* nb_lshift */ ++ 0, /* nb_rshift */ ++ 0, /* nb_and */ ++ 0, /* nb_xor */ ++ _Py_union_type_or, /* nb_or */ + }; + + PyTypeObject PyType_Type = { +@@ -4426,7 +4532,15 @@ PyTypeObject PyType_Type = { + type_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ + (inquiry)type_is_gc, /* tp_is_gc */ +- .tp_vectorcall = type_vectorcall, ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ type_vectorcall, /* tp_vectorcall */ + }; + + +@@ -4506,6 +4620,7 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds) + static PyObject * + object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { ++ PyObject *obj; + if (excess_args(args, kwds)) { + if (type->tp_new != object_new) { + PyErr_SetString(PyExc_TypeError, +@@ -4556,7 +4671,7 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + Py_DECREF(joined); + return NULL; + } +- PyObject *obj = type->tp_alloc(type, 0); ++ obj = type->tp_alloc(type, 0); + if (obj == NULL) { + return NULL; + } +@@ -4767,6 +4882,7 @@ static int + object_set_class(PyObject *self, PyObject *value, void *closure) + { + PyTypeObject *oldto = Py_TYPE(self); ++ PyTypeObject *newto; + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, +@@ -4779,7 +4895,7 @@ object_set_class(PyObject *self, PyObject *value, void *closure) + Py_TYPE(value)->tp_name); + return -1; + } +- PyTypeObject *newto = (PyTypeObject *)value; ++ newto = (PyTypeObject *)value; + + if (PySys_Audit("object.__setattr__", "OsO", + self, "__class__", value) < 0) { +@@ -5645,6 +5761,8 @@ static int + type_add_method(PyTypeObject *type, PyMethodDef *meth) + { + PyObject *descr; ++ PyObject *name; ++ int err; + int isdescr = 1; + if (meth->ml_flags & METH_CLASS) { + if (meth->ml_flags & METH_STATIC) { +@@ -5670,7 +5788,6 @@ type_add_method(PyTypeObject *type, PyMethodDef *meth) + return -1; + } + +- PyObject *name; + if (isdescr) { + name = PyDescr_NAME(descr); + } +@@ -5682,7 +5799,6 @@ type_add_method(PyTypeObject *type, PyMethodDef *meth) + } + } + +- int err; + if (!(meth->ml_flags & METH_COEXIST)) { + err = PyDict_SetDefault(type->tp_dict, name, descr) == NULL; + } +@@ -5722,11 +5838,12 @@ static int + type_add_members(PyTypeObject *type) + { + PyMemberDef *memb = type->tp_members; ++ PyObject *dict; + if (memb == NULL) { + return 0; + } + +- PyObject *dict = type->tp_dict; ++ dict = type->tp_dict; + for (; memb->name != NULL; memb++) { + PyObject *descr = PyDescr_NewMember(type, memb); + if (descr == NULL) +@@ -5746,11 +5863,12 @@ static int + type_add_getset(PyTypeObject *type) + { + PyGetSetDef *gsp = type->tp_getset; ++ PyObject *dict; + if (gsp == NULL) { + return 0; + } + +- PyObject *dict = type->tp_dict; ++ dict = type->tp_dict; + for (; gsp->name != NULL; gsp++) { + PyObject *descr = PyDescr_NewGetSet(type, gsp); + if (descr == NULL) { +@@ -5829,9 +5947,10 @@ static int + overrides_hash(PyTypeObject *type) + { + PyObject *dict = type->tp_dict; ++ int r; + + assert(dict != NULL); +- int r = PyDict_Contains(dict, &_Py_ID(__eq__)); ++ r = PyDict_Contains(dict, &_Py_ID(__eq__)); + if (r == 0) { + r = PyDict_Contains(dict, &_Py_ID(__hash__)); + } diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 959b851..6d8ce84 100644 --- a/PC/pyconfig.h @@ -24549,38 +27479,3 @@ index a451166..f26d2c2 100644 if (base == &tstate->datastack_chunk->data[0]) { _PyStackChunk *chunk = tstate->datastack_chunk; _PyStackChunk *previous = chunk->previous; -diff --git a/Include/internal/pycore_win9x_loadlibrary.h b/Include/internal/pycore_win9x_loadlibrary.h -new file mode 100644 -index 0000000..47fd5c3 ---- /dev/null -+++ b/Include/internal/pycore_win9x_loadlibrary.h -@@ -0,0 +1,29 @@ -+#ifndef PyCORE_WIN9X_LOADLIBRARY_H -+#define PyCORE_WIN9X_LOADLIBRARY_H -+ -+/* -+ * The VC98 SDK predates the restricted DLL-search flags introduced by newer -+ * Windows SDKs. Define their documented bit values so Windows sources can be -+ * compiled with MSVC 6.0. This is compile-time compatibility only: Windows 9x -+ * does not implement these LoadLibraryEx search semantics, so runtime loader -+ * call sites still require a legacy-compatible path. -+ */ -+#if defined(_MSC_VER) && _MSC_VER < 1300 -+# ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR -+# define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100 -+# endif -+# ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR -+# define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200 -+# endif -+# ifndef LOAD_LIBRARY_SEARCH_USER_DIRS -+# define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400 -+# endif -+# ifndef LOAD_LIBRARY_SEARCH_SYSTEM32 -+# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 -+# endif -+# ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS -+# define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 -+# endif -+#endif -+ -+#endif /* PyCORE_WIN9X_LOADLIBRARY_H */ diff --git a/scripts/vc6-descrobject-classmethod-c89.test.py b/scripts/vc6-descrobject-classmethod-c89.test.py index bd87531..48648a5 100644 --- a/scripts/vc6-descrobject-classmethod-c89.test.py +++ b/scripts/vc6-descrobject-classmethod-c89.test.py @@ -73,10 +73,12 @@ number_init = body_for("_PyDesc_InitTypes(void)") if "mappingproxy_as_number.nb_or = mappingproxy_or;" not in number_init or "mappingproxy_as_number.nb_inplace_or = mappingproxy_ior;" not in number_init: raise SystemExit("VC6 mappingproxy slots must be assigned before type readiness") init_body = body_for("_PyTypes_InitTypes(PyInterpreterState *interp)", object_source) -order = ("_PyClassObject_InitTypes();", "_PyDesc_InitTypes();", "for (size_t i=0;", "PyType_Ready(type)") +order = ("_PyClassObject_InitTypes();", "_PyDesc_InitTypes();", "for (i=0;", "PyType_Ready(type)") positions = [init_body.index(item) for item in order] if positions != sorted(positions): raise SystemExit("legacy static type slots must be initialized before PyType_Ready") +if "size_t i;" not in init_body or "for (size_t i=0;" in init_body: + raise SystemExit("static type initialization loop must use its C89 entry declaration") body = body_for("PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)") for declaration in ("PyMethodDescrObject *descr;", "vectorcallfunc vectorcall;"): diff --git a/scripts/vc6-object-c89.test.py b/scripts/vc6-object-c89.test.py index 7b646f6..79dfe76 100644 --- a/scripts/vc6-object-c89.test.py +++ b/scripts/vc6-object-c89.test.py @@ -51,3 +51,35 @@ text = check("PyObject_Repr", ( ), "PyObject_Repr must hoist tstate while preserving signal-check order") assert "PyThreadState *tstate =" not in text print("object PyObject_Repr C89 local and signal-check order: PASS") + +text = body("_PyObject_DictPointer") +expected = ''' + Py_ssize_t dictoffset; + PyTypeObject *tp = Py_TYPE(obj); + + if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + return _PyObject_ManagedDictPointer(obj); + } + dictoffset = tp->tp_dictoffset; + if (dictoffset == 0) + return NULL; + if (dictoffset < 0) { + Py_ssize_t tsize = Py_SIZE(obj); + size_t size; + if (tsize < 0) { + tsize = -tsize; + } + size = _PyObject_VAR_SIZE(tp, tsize); + assert(size <= (size_t)PY_SSIZE_T_MAX); + dictoffset += (Py_ssize_t)size; + + _PyObject_ASSERT(obj, dictoffset > 0); + _PyObject_ASSERT(obj, dictoffset % SIZEOF_VOID_P == 0); + } + return (PyObject **) ((char *)obj + dictoffset); +''' +assert text.split() == expected.split(), ( + "_PyObject_DictPointer must hoist only size to the block's opening declarations " + "and preserve the size expression and statement order" +) +print("object _PyObject_DictPointer C89 size declaration and offset calculation order: PASS") diff --git a/scripts/vc6-object-functionstr-c89.test.py b/scripts/vc6-object-functionstr-c89.test.py new file mode 100644 index 0000000..8482793 --- /dev/null +++ b/scripts/vc6-object-functionstr-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Guard the entry locals and evaluation order in _PyObject_FunctionStr.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +found = re.search( + r"\n_PyObject_FunctionStr\(PyObject \*x\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +assert found, "_PyObject_FunctionStr definition not found" +body = found.group("body") +for name in ("module", "result"): + declarations = re.findall(r"\bPyObject\s*\*\s*" + name + r"\b", body) + assert len(declarations) == 1, ( + f"_PyObject_FunctionStr must declare {name} exactly once at entry; " + f"found {len(declarations)} declarations" + ) + +tokens = ( + "PyObject *module;", + "PyObject *result;", + "int ret;", + "assert(!PyErr_Occurred());", + "ret = _PyObject_LookupAttr(x, &_Py_ID(__qualname__), &qualname);", + "if (qualname == NULL)", + "return PyObject_Str(x);", + "result = NULL;", + "ret = _PyObject_LookupAttr(x, &_Py_ID(__module__), &module);", + "ret = PyObject_RichCompareBool(module, &_Py_ID(builtins), Py_NE);", + 'result = PyUnicode_FromFormat("%S.%S()", module, qualname);', + 'result = PyUnicode_FromFormat("%S()", qualname);', + "Py_DECREF(qualname);", + "Py_XDECREF(module);", + "return result;", +) +positions = [body.find(token) for token in tokens] +assert all(position >= 0 for position in positions) and positions == sorted(positions), ( + "_PyObject_FunctionStr must keep locals at entry and preserve evaluation/statement order" +) +print("object _PyObject_FunctionStr unique C89 locals and evaluation order: PASS") diff --git a/scripts/vc6-object-initstate-c89.test.py b/scripts/vc6-object-initstate-c89.test.py new file mode 100644 index 0000000..162bf7f --- /dev/null +++ b/scripts/vc6-object-initstate-c89.test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Guard _PyTypes_InitState's C89 declaration and initialization order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +found = re.search( + r"\n_PyTypes_InitState\(PyInterpreterState \*interp\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +assert found, "_PyTypes_InitState definition not found" +body = found.group("body") +declaration = re.match(r"\s*PyStatus status;", body) +assert declaration and len(re.findall(r"\bPyStatus\s+status\b", body)) == 1, ( + "_PyTypes_InitState must declare status exactly once without initializer at entry" +) +expected_statements = ''' + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + + status = _PyTypes_InitSlotDefs(); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + return _PyStatus_OK(); +''' +assert body[declaration.end():].split() == expected_statements.split(), ( + "_PyTypes_InitState must preserve the interpreter guard, slot initialization, " + "exception propagation, and success return order" +) +print("object _PyTypes_InitState C89 status declaration and initialization/return order: PASS") diff --git a/scripts/vc6-object-notimplemented-c89.test.py b/scripts/vc6-object-notimplemented-c89.test.py new file mode 100644 index 0000000..17f56ed --- /dev/null +++ b/scripts/vc6-object-notimplemented-c89.test.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +"""Check NotImplemented's positional number slots against the CPython header.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +header = Path(sys.argv[2]).read_text() +layout = re.search(r"typedef struct \{([^{}]*)\} PyNumberMethods;", header, re.S) +assert layout, "PyNumberMethods definition not found" +fields = re.findall(r"\b(nb_\w+)\s*;", layout.group(1)) +assert len(fields) == 36 and fields.index("nb_bool") == 9, ( + "expected 36 PyNumberMethods slots with nb_bool in slot 10" +) +initializer = re.search( + r"static PyNumberMethods notimplemented_as_number\s*=\s*\{([^{}]*)\};", + source, + re.S, +) +assert initializer, "notimplemented_as_number initializer not found" +body = re.sub(r"/\*.*?\*/", "", initializer.group(1), flags=re.S) +assert not re.search(r"\.\s*\w+\s*=", body), ( + "notimplemented_as_number must use a VC6-compatible positional initializer" +) +slots = [value.strip() for value in body.strip().rstrip(",").split(",")] +assert len(slots) == len(fields), "every PyNumberMethods slot must be explicit" +for field, value in zip(fields, slots): + expected = "notimplemented_bool" if field == "nb_bool" else "0" + assert value == expected, f"{field}: expected {expected}, got {value}" +print("object NotImplemented C89 positional initializer: PASS (36 slots; nb_bool slot 10)") + +start = source.index("_PyTypes_InitTypes(PyInterpreterState *interp)\n{") +opening = source.index("{", start) +end = source.index("\n}\n", opening) +init_types = source[opening:end] +assert re.match(r"\{\s*size_t i;\s*if \(!_Py_IsMainInterpreter\(interp\)\)", init_types), ( + "_PyTypes_InitTypes must declare size_t i before the interpreter guard" +) +assert len(re.findall(r"\bsize_t\s+i\b", init_types)) == 1, ( + "_PyTypes_InitTypes must declare its loop counter exactly once" +) +assert "for (i=0; i < Py_ARRAY_LENGTH(static_types); i++) {" in init_types, ( + "_PyTypes_InitTypes must use the C89 counter with unchanged loop bounds/traversal" +) +assert init_types.index("_Py_GenericAlias_InitTypes();") < init_types.index("for (i=0;"), ( + "_PyTypes_InitTypes loop initialization must remain after VC6 type initialization" +) +print("object _PyTypes_InitTypes C89 loop counter declaration and initialization order: PASS") + +start = source.index("_PyTypes_FiniTypes(PyInterpreterState *interp)\n{") +opening = source.index("{", start) +end = source.index("\n}\n", opening) +fini_types = source[opening:end] +assert re.match(r"\{\s*Py_ssize_t i;\s*if \(!_Py_IsMainInterpreter\(interp\)\)", fini_types), ( + "_PyTypes_FiniTypes must declare Py_ssize_t i before the interpreter guard" +) +assert len(re.findall(r"\bPy_ssize_t\s+i\b", fini_types)) == 1, ( + "_PyTypes_FiniTypes must declare its signed loop counter exactly once" +) +expected = '''{ + Py_ssize_t i; + if (!_Py_IsMainInterpreter(interp)) { + return; + } + for (i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) { + PyTypeObject *type = static_types[i]; + _PyStaticType_Dealloc(type); + } +''' +assert re.sub(r"//[^\n]*", "", fini_types).split() == expected.split(), ( + "_PyTypes_FiniTypes must preserve the interpreter guard, reverse loop bounds/traversal, " + "and block-opening type lookup before each deallocation" +) +print("object _PyTypes_FiniTypes C89 loop counter and reverse per-item deallocation order: PASS") diff --git a/scripts/vc6-object-richcompare-c89.test.py b/scripts/vc6-object-richcompare-c89.test.py new file mode 100644 index 0000000..9e2f084 --- /dev/null +++ b/scripts/vc6-object-richcompare-c89.test.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python3 +"""Guard C89 locals and statement order in rich comparison and attribute access.""" + +import re +import sys +from pathlib import Path + + +def fail(message): + print(message, file=sys.stderr) + raise SystemExit(1) + + +source = Path(sys.argv[1]).read_text(encoding="utf-8") +found = re.search( + r"\nPyObject_RichCompare\(PyObject \*v, PyObject \*w, int op\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("PyObject_RichCompare definition not found") +body = found.group("body") +if len(re.findall(r"\bPyObject\s*\*\s*res\b", body)) != 1 or not re.match( + r"\s*PyThreadState \*tstate = _PyThreadState_GET\(\);\s*PyObject \*res;", + body, +): + fail("PyObject_RichCompare must declare res exactly once without initializer at entry") + +expected_statements = ''' + assert(Py_LT <= op && op <= Py_GE); + if (v == NULL || w == NULL) { + if (!_PyErr_Occurred(tstate)) { + PyErr_BadInternalCall(); + } + return NULL; + } + if (_Py_EnterRecursiveCallTstate(tstate, " in comparison")) { + return NULL; + } + res = do_richcompare(tstate, v, w, op); + _Py_LeaveRecursiveCallTstate(tstate); + return res; +''' +statements = body[body.index("PyObject *res;") + len("PyObject *res;"):] +if statements.split() != expected_statements.split(): + fail("PyObject_RichCompare must preserve validation, recursive-call, leave, and result order") +print("object PyObject_RichCompare C89 res declaration and recursive-call/result order: PASS") + +found = re.search( + r"\nset_attribute_error_context\(PyObject\* v, PyObject\* name\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("set_attribute_error_context definition not found") +body = found.group("body") +declarations = re.match( + r"\s*PyObject \*type, \*value, \*traceback;\s*" + r"PyAttributeErrorObject\s*\*\s*the_exc;", + body, +) +if not declarations: + fail("set_attribute_error_context must declare type/value/traceback and the_exc without initializers at entry") + +expected_statements = ''' + assert(PyErr_Occurred()); + if (!PyErr_ExceptionMatches(PyExc_AttributeError)){ + return 0; + } + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + if (!PyErr_GivenExceptionMatches(value, PyExc_AttributeError)) { + goto restore; + } + the_exc = (PyAttributeErrorObject*) value; + if (the_exc->name || the_exc->obj) { + goto restore; + } + if (PyObject_SetAttr(value, &_Py_ID(name), name) || + PyObject_SetAttr(value, &_Py_ID(obj), v)) { + return 1; + } +restore: + PyErr_Restore(type, value, traceback); + return 0; +''' +statements = re.sub(r"//[^\n]*", "", body[declarations.end():]) +if statements.split() != expected_statements.split(): + fail("set_attribute_error_context must preserve exception check/fetch/normalize/augment/restore order with no late declarations") +print("object set_attribute_error_context C89 locals and exception check/fetch/normalize/augment/restore order: PASS") + +found = re.search( + r"\nPyObject_GetAttr\(PyObject \*v, PyObject \*name\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("PyObject_GetAttr definition not found") +body = found.group("body") +declarations = re.match( + r"\s*PyTypeObject \*tp = Py_TYPE\(v\);\s*PyObject \*result;", + body, +) +if not declarations or len(re.findall(r"\bPyObject\s*\*\s*result\b", body)) != 1: + fail("PyObject_GetAttr must declare result exactly once without initializer at entry") + +expected_statements = ''' + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + Py_TYPE(name)->tp_name); + return NULL; + } + + result = NULL; + if (tp->tp_getattro != NULL) { + result = (*tp->tp_getattro)(v, name); + } + else if (tp->tp_getattr != NULL) { + const char *name_str = PyUnicode_AsUTF8(name); + if (name_str == NULL) { + return NULL; + } + result = (*tp->tp_getattr)(v, (char *)name_str); + } + else { + PyErr_Format(PyExc_AttributeError, + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); + } + + if (result == NULL) { + set_attribute_error_context(v, name); + } + return result; +''' +if body[declarations.end():].split() != expected_statements.split(): + fail("PyObject_GetAttr must preserve name validation, result initialization, dispatch, and error-context order") +print("object PyObject_GetAttr C89 result declaration and validation/dispatch/error-context order: PASS") + +found = re.search( + r"\n_PyObject_GetDictPtr\(PyObject \*obj\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("_PyObject_GetDictPtr definition not found") +body = found.group("body") +declarations = re.match( + r"\s*PyObject \*\*dict_ptr;\s*PyDictValues \*\*values_ptr;\s*PyObject \*dict;", + body, +) +if not declarations: + fail("_PyObject_GetDictPtr must declare dict_ptr, values_ptr, and dict without initializers at entry") + +expected_statements = ''' + if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { + return _PyObject_DictPointer(obj); + } + dict_ptr = _PyObject_ManagedDictPointer(obj); + values_ptr = _PyObject_ValuesPointer(obj); + if (*values_ptr == NULL) { + return dict_ptr; + } + assert(*dict_ptr == NULL); + dict = _PyObject_MakeDictFromInstanceAttributes(obj, *values_ptr); + if (dict == NULL) { + PyErr_Clear(); + return NULL; + } + *values_ptr = NULL; + *dict_ptr = dict; + return dict_ptr; +''' +if body[declarations.end():].split() != expected_statements.split(): + fail("_PyObject_GetDictPtr must preserve branch, pointer initialization, conversion, error-clear, and values_ptr/dict_ptr store order with no late declarations") +print("object _PyObject_GetDictPtr C89 locals and branch/initialization/conversion/error-clear/store order: PASS") + +found = re.search( + r"\n_PyObject_GetMethod\(PyObject \*obj, PyObject \*name, PyObject \*\*method\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("_PyObject_GetMethod definition not found") +body = found.group("body") +declarations = re.match( + r"\s*int meth_found = 0;\s*PyTypeObject \*tp;\s*PyObject \*descr;\s*descrgetfunc f;\s*PyDictValues \*values;(?:\s*PyObject \*attr;)?", + body, +) +if not declarations or len(re.findall(r"\bPyTypeObject\s*\*\s*tp\b", body)) != 1: + fail("_PyObject_GetMethod must declare tp exactly once without initializer at entry") +expected_statements = ''' + + assert(*method == NULL); + + tp = Py_TYPE(obj); + if (!_PyType_IsReady(tp)) { + if (PyType_Ready(tp) < 0) { + return 0; + } + } +''' +statements = body[declarations.end():] +if not statements.startswith(expected_statements): + fail("_PyObject_GetMethod must preserve assertion, type assignment, readiness check, and early-return order") +print("object _PyObject_GetMethod C89 tp declaration and readiness order: PASS") + +found = re.search( + r"\n_PyObject_GetMethod\(PyObject \*obj, PyObject \*name, PyObject \*\*method\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("_PyObject_GetMethod definition not found") +body = found.group("body") +declarations = re.match( + r"\s*int meth_found = 0;\s*PyTypeObject \*tp;\s*PyObject \*descr;\s*descrgetfunc f;\s*PyDictValues \*values;(?:\s*PyObject \*attr;)?", + body, +) +if not declarations or len(re.findall(r"\bPyObject\s*\*\s*descr\b", body)) != 1 or len(re.findall(r"\bdescrgetfunc\s+f\b", body)) != 1: + fail("_PyObject_GetMethod must declare descr and f exactly once without initializers at entry") +expected_statements = ''' + + assert(*method == NULL); + + tp = Py_TYPE(obj); + if (!_PyType_IsReady(tp)) { + if (PyType_Ready(tp) < 0) { + return 0; + } + } + + if (tp->tp_getattro != PyObject_GenericGetAttr || !PyUnicode_CheckExact(name)) { + *method = PyObject_GetAttr(obj, name); + return 0; + } + + descr = _PyType_Lookup(tp, name); + f = NULL; +''' +if not body[declarations.end():].startswith(expected_statements): + fail("_PyObject_GetMethod must preserve lookup and descrgetfunc initialization order") +print("object _PyObject_GetMethod C89 descr/f declarations and lookup order: PASS") + +found = re.search( + r"\n_PyObject_GetMethod\(PyObject \*obj, PyObject \*name, PyObject \*\*method\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +if not found: + fail("_PyObject_GetMethod definition not found") +body = found.group("body") +if len(re.findall(r"\bPyDictValues\s*\*\s*values\b", body)) != 1 or not re.match( + r"\s*int meth_found = 0;\s*PyTypeObject \*tp;\s*PyObject \*descr;\s*descrgetfunc f;\s*PyDictValues \*values;(?:\s*PyObject \*attr;)?", + body, +): + fail("_PyObject_GetMethod must declare values exactly once at function entry") +if not re.search(r"descr = _PyType_Lookup\(tp, name\);\s*f = NULL;", body) or "values = *_PyObject_ValuesPointer(obj)" not in body: + fail("_PyObject_GetMethod must preserve values lookup at its original managed-dict check point") +print("object _PyObject_GetMethod C89 values declaration and initialization order: PASS") + +# Both mutually exclusive dictionary branches reuse the entry attr local. +declarations = re.match( + r"\s*int meth_found = 0;\s*PyTypeObject \*tp;\s*PyObject \*descr;" + r"\s*descrgetfunc f;\s*PyDictValues \*values;\s*PyObject \*attr;", + body, +) +if not declarations or len(re.findall(r"\bPyObject\s*\*\s*attr\s*;", body)) != 1: + fail("_PyObject_GetMethod must declare attr exactly once without initializer at function entry") +if len(re.findall(r"\bPyObject\s*\*\s*attr\b", body)) != 1: + fail("_PyObject_GetMethod ordinary-dict attr must reuse the entry local, with assignment after Py_INCREF(dict)") + +expected_statements = ''' + + assert(*method == NULL); + + tp = Py_TYPE(obj); + if (!_PyType_IsReady(tp)) { + if (PyType_Ready(tp) < 0) { + return 0; + } + } + + if (tp->tp_getattro != PyObject_GenericGetAttr || !PyUnicode_CheckExact(name)) { + *method = PyObject_GetAttr(obj, name); + return 0; + } + + descr = _PyType_Lookup(tp, name); + f = NULL; + if (descr != NULL) { + Py_INCREF(descr); + if (_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) { + meth_found = 1; + } else { + f = Py_TYPE(descr)->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + *method = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + return 0; + } + } + } + if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) && + (values = *_PyObject_ValuesPointer(obj))) + { + assert(*_PyObject_DictPointer(obj) == NULL); + attr = _PyObject_GetInstanceAttribute(obj, values, name); + if (attr != NULL) { + *method = attr; + Py_XDECREF(descr); + return 0; + } + } + else { + PyObject **dictptr = _PyObject_DictPointer(obj); + PyObject *dict; + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = PyDict_GetItemWithError(dict, name); + if (attr != NULL) { + *method = Py_NewRef(attr); + Py_DECREF(dict); + Py_XDECREF(descr); + return 0; + } + Py_DECREF(dict); + + if (PyErr_Occurred()) { + Py_XDECREF(descr); + return 0; + } + } + } + + if (meth_found) { + *method = descr; + return 1; + } + + if (f != NULL) { + *method = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + return 0; + } + + if (descr != NULL) { + *method = descr; + return 0; + } + + PyErr_Format(PyExc_AttributeError, + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); + + set_attribute_error_context(obj, name); + return 0;''' +if body[declarations.end():].split() != expected_statements.split(): + fail("_PyObject_GetMethod must reuse attr in managed/ordinary-dict branches and preserve lookup/branch/assignment/error/cleanup order") +print("object _PyObject_GetMethod C89 managed/ordinary-dict attr declaration and lookup/branch/assignment/error/cleanup order: PASS") diff --git a/scripts/vc6-obmalloc-allocator-name-c89.test.py b/scripts/vc6-obmalloc-allocator-name-c89.test.py new file mode 100644 index 0000000..9aaa0a9 --- /dev/null +++ b/scripts/vc6-obmalloc-allocator-name-c89.test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Guard _PyMem_GetCurrentAllocatorName C89 local placement and comparisons.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"_PyMem_GetCurrentAllocatorName\s*\([^)]*\)\s*\{(?P.*?)\n\}", + source, + re.S, +) +assert match, "_PyMem_GetCurrentAllocatorName definition not found" +body = match.group("body") + +expected_declarations = [ + "PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC;", + "PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC;", + "PyMemAllocatorEx dbg_raw = PYDBGRAW_ALLOC;", + "PyMemAllocatorEx dbg_mem = PYDBGMEM_ALLOC;", + "PyMemAllocatorEx dbg_obj = PYDBGOBJ_ALLOC;", +] +positions = [body.find(declaration) for declaration in expected_declarations] +assert all(position >= 0 for position in positions), "allocator snapshot declarations must remain present" +first_check = body.find("if (pymemallocator_eq") +assert first_check >= 0 and positions == sorted(positions) and positions[-1] < first_check, ( + "all allocator snapshots must be initialized before the first statement for C89" +) +assert body.count("if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc)") == 2, ( + "preserve the malloc and pymalloc base-allocator comparisons" +) +assert body.count("if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &malloc_alloc) &&") == 2, ( + "preserve malloc_debug and pymalloc_debug allocator comparisons" +) +assert "pymemallocator_eq(&_PyMem_Raw, &dbg_raw)" in body +assert "pymemallocator_eq(&_PyMem, &dbg_mem)" in body +assert "pymemallocator_eq(&_PyObject, &dbg_obj)" in body +assert body.index("/* Debug hooks installed */") < body.index('return "malloc_debug";') +assert body.index('return "malloc_debug";') < body.index('return "pymalloc_debug";') +assert body.index('return "pymalloc_debug";') < body.index("return NULL;") +print("obmalloc allocator-name C89 declarations and allocator classification order: PASS") diff --git a/scripts/vc6-obmalloc-arena-map-is-used-c89.test.py b/scripts/vc6-obmalloc-arena-map-is-used-c89.test.py new file mode 100644 index 0000000..c479935 --- /dev/null +++ b/scripts/vc6-obmalloc-arena-map-is-used-c89.test.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Guard arena_map_is_used's C89 locals and original evaluation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search(r"\narena_map_is_used\(block \*p\)\s*\{(.*?)\n\}", source, re.S) +assert match, "arena_map_is_used definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + arena_map_bot_t *n = arena_map_get(p, 0); + int i3; + int32_t hi; + int32_t lo; + int32_t tail; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "arena_map_is_used must declare i3, hi, lo, tail before the NULL guard" +) + +# Failed lookup must return before index evaluation or node dereferences. +# Preserve lookup count, assignment order, and the short-circuit predicate. +expected = declarations + """ + if (n == NULL) { + return 0; + } + i3 = MAP_BOT_INDEX(p); + hi = n->arenas[i3].tail_hi; + lo = n->arenas[i3].tail_lo; + tail = (int32_t)(AS_UINT(p) & ARENA_SIZE_MASK); + return (tail < lo) || (tail >= hi && hi != 0); +""" +assert body.split() == expected.split(), ( + "preserve arena_map_is_used lookup, NULL return, evaluation order and predicate" +) +print("obmalloc arena_map_is_used C89 declarations and original evaluation order: PASS") diff --git a/scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py b/scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py new file mode 100644 index 0000000..1092eb3 --- /dev/null +++ b/scripts/vc6-obmalloc-arena-map-mark-used-c89.test.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Guard only arena_map_mark_used's entry locals and original operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\narena_map_mark_used\(uintptr_t arena_base, int is_used\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "arena_map_mark_used definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + arena_map_bot_t *n_hi; + int i3; + int32_t tail; + uintptr_t arena_base_next; + arena_map_bot_t *n_lo; + int i3_next; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "n_hi, i3, tail, arena_base_next, n_lo, i3_next must be declared without initializers at function entry" +) + +# Keep evaluations at their original positions: the sanity assertion precedes +# lookup; failed lookup returns before index/tail evaluation. Lock both branches, +# including rollback and i3_next evaluation after the n_lo NULL return. +expected = declarations + """ + assert(HIGH_BITS(arena_base) == HIGH_BITS(&arena_map_root)); + n_hi = arena_map_get((block *)arena_base, is_used); + if (n_hi == NULL) { + assert(is_used); + return 0; + } + i3 = MAP_BOT_INDEX((block *)arena_base); + tail = (int32_t)(arena_base & ARENA_SIZE_MASK); + if (tail == 0) { + n_hi->arenas[i3].tail_hi = is_used ? -1 : 0; + } + else { + n_hi->arenas[i3].tail_hi = is_used ? tail : 0; + arena_base_next = arena_base + ARENA_SIZE; + assert(arena_base < arena_base_next); + n_lo = arena_map_get((block *)arena_base_next, is_used); + if (n_lo == NULL) { + assert(is_used); + n_hi->arenas[i3].tail_hi = 0; + return 0; + } + i3_next = MAP_BOT_INDEX(arena_base_next); + n_lo->arenas[i3_next].tail_lo = is_used ? tail : 0; + } + return 1; +""" +assert body.split() == expected.split(), ( + "preserve original initialization/evaluation/control-flow order" +) +print("obmalloc arena_map_mark_used entry declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-calloc-c89.test.py b/scripts/vc6-obmalloc-calloc-c89.test.py new file mode 100644 index 0000000..12c1468 --- /dev/null +++ b/scripts/vc6-obmalloc-calloc-c89.test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Guard _PyObject_Calloc's C89 declarations and original operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\n_PyObject_Calloc\(void \*ctx, size_t nelem, size_t elsize\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "_PyObject_Calloc definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert body.split()[:4] == ["size_t", "nbytes;", "void*", "ptr;"], ( + "_PyObject_Calloc must declare nbytes and ptr without initializers at function entry" +) + +# Keep multiplication after the overflow assertion, allocation after the size +# calculation, and zeroing, fallback allocation, and accounting in their order. +expected = """ + size_t nbytes; + void* ptr; + assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize); + nbytes = nelem * elsize; + ptr = pymalloc_alloc(ctx, nbytes); + if (LIKELY(ptr != NULL)) { + memset(ptr, 0, nbytes); + return ptr; + } + ptr = PyMem_RawCalloc(nelem, elsize); + if (ptr != NULL) { + raw_allocated_blocks++; + } + return ptr; +""" +assert body.split() == expected.split(), ( + "preserve _PyObject_Calloc assertion, evaluation, zeroing, fallback, and accounting order" +) +print("obmalloc _PyObject_Calloc nbytes/ptr entry declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-debugcheckaddress-c89.test.py b/scripts/vc6-obmalloc-debugcheckaddress-c89.test.py new file mode 100644 index 0000000..12fdc0d --- /dev/null +++ b/scripts/vc6-obmalloc-debugcheckaddress-c89.test.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Guard _PyMem_DebugCheckAddress's C89 locals and validation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\n_PyMem_DebugCheckAddress\(const char \*func, char api, const void \*p\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "_PyMem_DebugCheckAddress definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + const uint8_t *q; + size_t nbytes; + const uint8_t *tail; + int i; + char id; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "_PyMem_DebugCheckAddress must declare all locals without initializers at function entry" +) + +# Keep the pointer cast after the assertion, and validate the leading pad +# before reading the size or checking the tail of a possibly corrupt block. +expected = declarations + """ + assert(p != NULL); + q = (const uint8_t *)p; + id = (char)q[-SST]; + if (id != api) { + _PyObject_DebugDumpAddress(p); + _Py_FatalErrorFormat(func, + "bad ID: Allocated using API '%c', " + "verified using API '%c'", + id, api); + } + for (i = SST-1; i >= 1; --i) { + if (*(q-i) != PYMEM_FORBIDDENBYTE) { + _PyObject_DebugDumpAddress(p); + _Py_FatalErrorFunc(func, "bad leading pad byte"); + } + } + nbytes = read_size_t(q - 2*SST); + tail = q + nbytes; + for (i = 0; i < SST; ++i) { + if (tail[i] != PYMEM_FORBIDDENBYTE) { + _PyObject_DebugDumpAddress(p); + _Py_FatalErrorFunc(func, "bad trailing pad byte"); + } + } +""" +assert body.split() == expected.split(), ( + "preserve _PyMem_DebugCheckAddress assertion, cast evaluation point, " + "and complete validation/diagnostic order" +) +print("obmalloc _PyMem_DebugCheckAddress C89 declarations and original validation order: PASS") diff --git a/scripts/vc6-obmalloc-debugmallocstats-c89.test.py b/scripts/vc6-obmalloc-debugmallocstats-c89.test.py new file mode 100644 index 0000000..e1f5827 --- /dev/null +++ b/scripts/vc6-obmalloc-debugmallocstats-c89.test.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +"""Guard _PyObject_DebugMallocStats C89 declarations and evaluation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\n_PyObject_DebugMallocStats\(FILE \*out\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "_PyObject_DebugMallocStats definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = r""" + uint i; + uint numclasses; + size_t numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT]; + size_t numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT]; + size_t numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT]; + size_t allocated_bytes; + size_t available_bytes; + uint numfreepools; + size_t arena_alignment; + size_t pool_header_bytes; + size_t quantization; + size_t narenas; + size_t total; + char buf[128]; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "_PyObject_DebugMallocStats must hoist only uninitialized declarations " + "before the pymalloc guard, preserving array extents" +) + +# Freeze the guard before all scalar assignments, their original order, and +# the entire remaining body, including array zeroing and conditional paths. +expected = declarations + r""" + if (!_PyMem_PymallocEnabled()) { + return 0; + } + numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT; + allocated_bytes = 0; + available_bytes = 0; + numfreepools = 0; + arena_alignment = 0; + pool_header_bytes = 0; + quantization = 0; + narenas = 0; + fprintf(out, "Small block threshold = %d, in %u size classes.\n", + SMALL_REQUEST_THRESHOLD, numclasses); + + for (i = 0; i < numclasses; ++i) + numpools[i] = numblocks[i] = numfreeblocks[i] = 0; + + + for (i = 0; i < maxarenas; ++i) { + uintptr_t base = arenas[i].address; + + + if (arenas[i].address == (uintptr_t)NULL) + continue; + narenas += 1; + + numfreepools += arenas[i].nfreepools; + + + if (base & (uintptr_t)POOL_SIZE_MASK) { + arena_alignment += POOL_SIZE; + base &= ~(uintptr_t)POOL_SIZE_MASK; + base += POOL_SIZE; + } + + + assert(base <= (uintptr_t) arenas[i].pool_address); + for (; base < (uintptr_t) arenas[i].pool_address; base += POOL_SIZE) { + poolp p = (poolp)base; + const uint sz = p->szidx; + uint freeblocks; + + if (p->ref.count == 0) { + +#ifdef Py_DEBUG + assert(pool_is_in_list(p, arenas[i].freepools)); +#endif + continue; + } + ++numpools[sz]; + numblocks[sz] += p->ref.count; + freeblocks = NUMBLOCKS(sz) - p->ref.count; + numfreeblocks[sz] += freeblocks; +#ifdef Py_DEBUG + if (freeblocks > 0) + assert(pool_is_in_list(p, usedpools[sz + sz])); +#endif + } + } + assert(narenas == narenas_currently_allocated); + + fputc('\n', out); + fputs("class size num pools blocks in use avail blocks\n" + "----- ---- --------- ------------- ------------\n", + out); + + for (i = 0; i < numclasses; ++i) { + size_t p = numpools[i]; + size_t b = numblocks[i]; + size_t f = numfreeblocks[i]; + uint size = INDEX2SIZE(i); + if (p == 0) { + assert(b == 0 && f == 0); + continue; + } + fprintf(out, "%5u %6u %11zu %15zu %13zu\n", + i, size, p, b, f); + allocated_bytes += b * size; + available_bytes += f * size; + pool_header_bytes += p * POOL_OVERHEAD; + quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size); + } + fputc('\n', out); +#ifdef PYMEM_DEBUG_SERIALNO + if (_PyMem_DebugEnabled()) { + (void)printone(out, "# times object malloc called", serialno); + } +#endif + (void)printone(out, "# arenas allocated total", ntimes_arena_allocated); + (void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas); + (void)printone(out, "# arenas highwater mark", narenas_highwater); + (void)printone(out, "# arenas allocated current", narenas); + + PyOS_snprintf(buf, sizeof(buf), + "%zu arenas * %d bytes/arena", + narenas, ARENA_SIZE); + (void)printone(out, buf, narenas * ARENA_SIZE); + + fputc('\n', out); + + + total = printone(out, "# bytes in allocated blocks", allocated_bytes); + total += printone(out, "# bytes in available blocks", available_bytes); + + PyOS_snprintf(buf, sizeof(buf), + "%u unused pools * %d bytes", numfreepools, POOL_SIZE); + total += printone(out, buf, (size_t)numfreepools * POOL_SIZE); + + total += printone(out, "# bytes lost to pool headers", pool_header_bytes); + total += printone(out, "# bytes lost to quantization", quantization); + total += printone(out, "# bytes lost to arena alignment", arena_alignment); + (void)printone(out, "Total", total); + assert(narenas * ARENA_SIZE == total); + +#if WITH_PYMALLOC_RADIX_TREE + fputs("\narena map counts\n", out); +#ifdef USE_INTERIOR_NODES + (void)printone(out, "# arena map mid nodes", arena_map_mid_count); + (void)printone(out, "# arena map bot nodes", arena_map_bot_count); + fputc('\n', out); +#endif + total = printone(out, "# bytes lost to arena map root", sizeof(arena_map_root)); +#ifdef USE_INTERIOR_NODES + total += printone(out, "# bytes lost to arena map mid", + sizeof(arena_map_mid_t) * arena_map_mid_count); + total += printone(out, "# bytes lost to arena map bot", + sizeof(arena_map_bot_t) * arena_map_bot_count); + (void)printone(out, "Total", total); +#endif +#endif + + return 1;""" +assert body.split() == expected.split(), ( + "preserve _PyObject_DebugMallocStats early return, initialization/evaluation " + "points, array contents, and complete operation order" +) +print("obmalloc _PyObject_DebugMallocStats C89 declarations and operation order: PASS") diff --git a/scripts/vc6-obmalloc-debugrawfree-c89.test.py b/scripts/vc6-obmalloc-debugrawfree-c89.test.py new file mode 100644 index 0000000..194d6b2 --- /dev/null +++ b/scripts/vc6-obmalloc-debugrawfree-c89.test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Guard _PyMem_DebugRawFree's C89 locals and NULL-safe evaluation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\n_PyMem_DebugRawFree\(void \*ctx, void \*p\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "_PyMem_DebugRawFree definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + debug_alloc_api_t *api; + uint8_t *q; + size_t nbytes; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "_PyMem_DebugRawFree must declare api, q, and nbytes without initializers at function entry" +) + +# Preserve the NULL return before either initializer is evaluated, especially +# the pointer subtraction, and retain all subsequent operations in order. +expected = declarations + """ + if (p == NULL) { + return; + } + api = (debug_alloc_api_t *)ctx; + q = (uint8_t *)p - 2*SST; + _PyMem_DebugCheckAddress(__func__, api->api_id, p); + nbytes = read_size_t(q); + nbytes += PYMEM_DEBUG_EXTRA_BYTES; + memset(q, PYMEM_DEADBYTE, nbytes); + api->alloc.free(api->alloc.ctx, q); +""" +assert body.split() == expected.split(), ( + "preserve _PyMem_DebugRawFree assignments after the NULL return and original operation order" +) +print("obmalloc _PyMem_DebugRawFree entry declarations and NULL-safe operation order: PASS") diff --git a/scripts/vc6-obmalloc-debugrawrealloc-c89.test.py b/scripts/vc6-obmalloc-debugrawrealloc-c89.test.py new file mode 100644 index 0000000..5deb3e0 --- /dev/null +++ b/scripts/vc6-obmalloc-debugrawrealloc-c89.test.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +"""Guard _PyMem_DebugRawRealloc's C89 locals and complete operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\n_PyMem_DebugRawRealloc\(void \*ctx, void \*p, size_t nbytes\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "_PyMem_DebugRawRealloc definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + debug_alloc_api_t *api; + uint8_t *head; + uint8_t *data; + uint8_t *r; + uint8_t *tail; + size_t total; + size_t original_nbytes; +#define ERASED_SIZE 64 + uint8_t save[2*ERASED_SIZE]; +#ifdef PYMEM_DEBUG_SERIALNO + size_t block_serialno; +#endif +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "_PyMem_DebugRawRealloc must declare locals without initializers at function entry, " + "including block_serialno under PYMEM_DEBUG_SERIALNO" +) + +# Keep the ctx cast after the NULL return and the serial-number read after +# the overflow guard and tail calculation. Freeze both preprocessor paths, +# allocation failure recovery, saved-byte restoration, and growth filling. +expected = declarations + """ + + if (p == NULL) { + return _PyMem_DebugRawAlloc(0, ctx, nbytes); + } + + api = (debug_alloc_api_t *)ctx; + _PyMem_DebugCheckAddress(__func__, api->api_id, p); + + data = (uint8_t *)p; + head = data - 2*SST; + original_nbytes = read_size_t(head); + if (nbytes > (size_t)PY_SSIZE_T_MAX - PYMEM_DEBUG_EXTRA_BYTES) { + + return NULL; + } + total = nbytes + PYMEM_DEBUG_EXTRA_BYTES; + + tail = data + original_nbytes; +#ifdef PYMEM_DEBUG_SERIALNO + block_serialno = read_size_t(tail + SST); +#endif + + if (original_nbytes <= sizeof(save)) { + memcpy(save, data, original_nbytes); + memset(data - 2 * SST, PYMEM_DEADBYTE, + original_nbytes + PYMEM_DEBUG_EXTRA_BYTES); + } + else { + memcpy(save, data, ERASED_SIZE); + memset(head, PYMEM_DEADBYTE, ERASED_SIZE + 2 * SST); + memcpy(&save[ERASED_SIZE], tail - ERASED_SIZE, ERASED_SIZE); + memset(tail - ERASED_SIZE, PYMEM_DEADBYTE, + ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST); + } + + + r = (uint8_t *)api->alloc.realloc(api->alloc.ctx, head, total); + if (r == NULL) { + + nbytes = original_nbytes; + } + else { + head = r; +#ifdef PYMEM_DEBUG_SERIALNO + bumpserialno(); + block_serialno = serialno; +#endif + } + data = head + 2*SST; + + write_size_t(head, nbytes); + head[SST] = (uint8_t)api->api_id; + memset(head + SST + 1, PYMEM_FORBIDDENBYTE, SST-1); + + tail = data + nbytes; + memset(tail, PYMEM_FORBIDDENBYTE, SST); +#ifdef PYMEM_DEBUG_SERIALNO + write_size_t(tail + SST, block_serialno); +#endif + + + if (original_nbytes <= sizeof(save)) { + memcpy(data, save, Py_MIN(nbytes, original_nbytes)); + } + else { + size_t i = original_nbytes - ERASED_SIZE; + memcpy(data, save, Py_MIN(nbytes, ERASED_SIZE)); + if (nbytes > i) { + memcpy(data + i, &save[ERASED_SIZE], + Py_MIN(nbytes - i, ERASED_SIZE)); + } + } + + if (r == NULL) { + return NULL; + } + + if (nbytes > original_nbytes) { + + memset(data + original_nbytes, PYMEM_CLEANBYTE, + nbytes - original_nbytes); + } + + return data;""" +assert body.split() == expected.split(), ( + "preserve _PyMem_DebugRawRealloc initialization evaluation points, guards, " + "and complete operation/control-flow order" +) +print("obmalloc _PyMem_DebugRawRealloc C89 declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-default-allocator-c89.test.py b/scripts/vc6-obmalloc-default-allocator-c89.test.py new file mode 100644 index 0000000..6d3f581 --- /dev/null +++ b/scripts/vc6-obmalloc-default-allocator-c89.test.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Guard VC6-compatible default allocator copies, fields, and call order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +# Preserve ctx/malloc/calloc/realloc/free and WITH_PYMALLOC selection. +macros = source[source.index("#define MALLOC_ALLOC"):source.index("typedef struct {", source.index("#define MALLOC_ALLOC"))] +expected_macros = """ +#define MALLOC_ALLOC {NULL, _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree} +#ifdef WITH_PYMALLOC +# define PYMALLOC_ALLOC {NULL, _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free} +#endif +#define PYRAW_ALLOC MALLOC_ALLOC +#ifdef WITH_PYMALLOC +# define PYOBJ_ALLOC PYMALLOC_ALLOC +#else +# define PYOBJ_ALLOC MALLOC_ALLOC +#endif +#define PYMEM_ALLOC PYOBJ_ALLOC +""" +assert macros.split() == expected_macros.split(), ( + "default allocator fields or WITH_PYMALLOC selection changed" +) + +match = re.search( + r"\npymem_set_default_allocator\([^)]*\)\s*\{(.*?)\n\}", source, re.S +) +assert match, "pymem_set_default_allocator definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declaration = "PyMemAllocatorEx new_alloc;" +if body.count(declaration) != 1 or not body.lstrip().startswith(declaration): + sys.exit("new_alloc must be declared once without initializer at function entry") + +expected = """ + if (old_alloc != NULL) { + PyMem_GetAllocator(domain, old_alloc); + } + switch(domain) + { + case PYMEM_DOMAIN_RAW: + { + PyMemAllocatorEx alloc = PYRAW_ALLOC; + new_alloc = alloc; + break; + } + case PYMEM_DOMAIN_MEM: + { + PyMemAllocatorEx alloc = PYMEM_ALLOC; + new_alloc = alloc; + break; + } + case PYMEM_DOMAIN_OBJ: + { + PyMemAllocatorEx alloc = PYOBJ_ALLOC; + new_alloc = alloc; + break; + } + default: + return -1; + } + PyMem_SetAllocator(domain, &new_alloc); + if (debug) { + _PyMem_SetupDebugHooksDomain(domain); + } + return 0; +""" +if body.replace(declaration, "").split() != expected.split(): + sys.exit("default allocator switch, assignments, or call order changed") +print("obmalloc default allocator C89 assignments, allocator semantics, and execution order: PASS") diff --git a/scripts/vc6-obmalloc-insert-to-freepool-c89.test.py b/scripts/vc6-obmalloc-insert-to-freepool-c89.test.py new file mode 100644 index 0000000..7cb610f --- /dev/null +++ b/scripts/vc6-obmalloc-insert-to-freepool-c89.test.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +"""Guard insert_to_freepool's C89 locals and complete operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\ninsert_to_freepool\(poolp pool\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "insert_to_freepool definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + poolp next; + poolp prev; + struct arena_object *ao; + uint nf; + struct arena_object* lastnf; + struct arena_object* p; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "insert_to_freepool must declare all six locals without initializers at function entry" +) + +# Assignments stay at the original evaluation points, including p inside its +# branch. Preserve every assertion, branch, return, and pointer update, as well +# as the radix-tree conditional, throughout all four arena-management cases. +expected = declarations + """ + next = pool->nextpool; + prev = pool->prevpool; + next->prevpool = prev; + prev->nextpool = next; + ao = &arenas[pool->arenaindex]; + pool->nextpool = ao->freepools; + ao->freepools = pool; + nf = ao->nfreepools; + lastnf = nfp2lasta[nf]; + assert((nf == 0 && lastnf == NULL) || + (nf > 0 && + lastnf != NULL && + lastnf->nfreepools == nf && + (lastnf->nextarena == NULL || + nf < lastnf->nextarena->nfreepools))); + if (lastnf == ao) { + p = ao->prevarena; + nfp2lasta[nf] = (p != NULL && p->nfreepools == nf) ? p : NULL; + } + ao->nfreepools = ++nf; + if (nf == ao->ntotalpools && ao->nextarena != NULL) { + assert(ao->prevarena == NULL || + ao->prevarena->address != 0); + assert(ao ->nextarena == NULL || + ao->nextarena->address != 0); + if (ao->prevarena == NULL) { + usable_arenas = ao->nextarena; + assert(usable_arenas == NULL || + usable_arenas->address != 0); + } + else { + assert(ao->prevarena->nextarena == ao); + ao->prevarena->nextarena = + ao->nextarena; + } + if (ao->nextarena != NULL) { + assert(ao->nextarena->prevarena == ao); + ao->nextarena->prevarena = + ao->prevarena; + } + ao->nextarena = unused_arena_objects; + unused_arena_objects = ao; +#if WITH_PYMALLOC_RADIX_TREE + arena_map_mark_used(ao->address, 0); +#endif + _PyObject_Arena.free(_PyObject_Arena.ctx, + (void *)ao->address, ARENA_SIZE); + ao->address = 0; + --narenas_currently_allocated; + return; + } + if (nf == 1) { + ao->nextarena = usable_arenas; + ao->prevarena = NULL; + if (usable_arenas) + usable_arenas->prevarena = ao; + usable_arenas = ao; + assert(usable_arenas->address != 0); + if (nfp2lasta[1] == NULL) { + nfp2lasta[1] = ao; + } + return; + } + if (nfp2lasta[nf] == NULL) { + nfp2lasta[nf] = ao; + } + if (ao == lastnf) { + return; + } + assert(ao->nextarena != NULL); + if (ao->prevarena != NULL) { + assert(ao->prevarena->nextarena == ao); + ao->prevarena->nextarena = ao->nextarena; + } + else { + assert(usable_arenas == ao); + usable_arenas = ao->nextarena; + } + ao->nextarena->prevarena = ao->prevarena; + ao->prevarena = lastnf; + ao->nextarena = lastnf->nextarena; + if (ao->nextarena != NULL) { + ao->nextarena->prevarena = ao; + } + lastnf->nextarena = ao; + assert(ao->nextarena == NULL || nf <= ao->nextarena->nfreepools); + assert(ao->prevarena == NULL || nf > ao->prevarena->nfreepools); + assert(ao->nextarena == NULL || ao->nextarena->prevarena == ao); + assert((usable_arenas == ao && ao->prevarena == NULL) + || ao->prevarena->nextarena == ao); +""" +assert body.split() == expected.split(), ( + "preserve insert_to_freepool evaluation, assertion, control-flow, and pointer-update order" +) +print("obmalloc insert_to_freepool entry declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py b/scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py new file mode 100644 index 0000000..572cbf7 --- /dev/null +++ b/scripts/vc6-obmalloc-insert-to-usedpool-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Guard only insert_to_usedpool's entry locals and original operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\ninsert_to_usedpool\(poolp pool\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "insert_to_usedpool definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + uint size; + poolp next; + poolp prev; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "insert_to_usedpool must declare size, next, and prev without initializers at function entry" +) + +# Keep the assertion before size evaluation and both lookups, then preserve +# the four pointer-link writes in their original order. +expected = declarations + """ + assert(pool->ref.count > 0); + size = pool->szidx; + next = usedpools[size + size]; + prev = next->prevpool; + pool->nextpool = next; + pool->prevpool = prev; + next->prevpool = pool; + prev->nextpool = pool; +""" +assert body.split() == expected.split(), ( + "preserve insert_to_usedpool assertion, size/lookup evaluation, and pointer-link mutation order" +) +print("obmalloc insert_to_usedpool entry declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-pool-extend-c89.test.py b/scripts/vc6-obmalloc-pool-extend-c89.test.py new file mode 100644 index 0000000..7abcffd --- /dev/null +++ b/scripts/vc6-obmalloc-pool-extend-c89.test.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +"""Guard pymalloc_pool_extend's C89 declaration and operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\npymalloc_pool_extend\(poolp pool, uint size\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "pymalloc_pool_extend definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert body.split()[:2] == ["poolp", "next;"], ( + "pymalloc_pool_extend must declare next without an initializer at function entry" +) + +# The extension path returns before reading nextpool. Keep the full-pool +# unlink reads and writes in their original order. +expected = """ + poolp next; + if (UNLIKELY(pool->nextoffset <= pool->maxnextoffset)) { + pool->freeblock = (block*)pool + pool->nextoffset; + pool->nextoffset += INDEX2SIZE(size); + *(block **)(pool->freeblock) = NULL; + return; + } + next = pool->nextpool; + pool = pool->prevpool; + next->prevpool = pool; + pool->nextpool = next; +""" +assert body.split() == expected.split(), ( + "preserve pymalloc_pool_extend extension, early return, and unlink evaluation order" +) +print("obmalloc pymalloc_pool_extend C89 declaration and original operation order: PASS") + + +match = re.search( + r"\nallocate_from_new_pool\(uint size\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "allocate_from_new_pool definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert body.split()[:2] == ["poolp", "pool;"], ( + "allocate_from_new_pool must declare pool without an initializer at function entry" +) + +assert body.split()[:6] == ["poolp", "pool;", "block", "*bp;", "poolp", "next;"], ( + "allocate_from_new_pool must declare bp and next without initializers at function entry" +) +assert re.findall(r"\bblock\s+\*bp\s*;", body) == ["block *bp;"], ( + "allocate_from_new_pool must declare bp exactly once" +) +assert re.findall(r"\bpoolp\s+next\b", body) == ["poolp next"], ( + "allocate_from_new_pool must declare next exactly once" +) + +# Keep the freepools read after arena creation and arena-list updates, and +# preserve all subsequent cached-pool, new-pool, and initialization branches. +# Keep next's usedpools read immediately before the frontlink writes. +expected = """ + poolp pool; + block *bp; + poolp next; + if (UNLIKELY(usable_arenas == NULL)) { +#ifdef WITH_MEMORY_LIMITS + if (narenas_currently_allocated >= MAX_ARENAS) { + return NULL; + } +#endif + usable_arenas = new_arena(); + if (usable_arenas == NULL) { + return NULL; + } + usable_arenas->nextarena = usable_arenas->prevarena = NULL; + assert(nfp2lasta[usable_arenas->nfreepools] == NULL); + nfp2lasta[usable_arenas->nfreepools] = usable_arenas; + } + assert(usable_arenas->address != 0); + assert(usable_arenas->nfreepools > 0); + if (nfp2lasta[usable_arenas->nfreepools] == usable_arenas) { + nfp2lasta[usable_arenas->nfreepools] = NULL; + } + if (usable_arenas->nfreepools > 1) { + assert(nfp2lasta[usable_arenas->nfreepools - 1] == NULL); + nfp2lasta[usable_arenas->nfreepools - 1] = usable_arenas; + } + pool = usable_arenas->freepools; + if (LIKELY(pool != NULL)) { + usable_arenas->freepools = pool->nextpool; + usable_arenas->nfreepools--; + if (UNLIKELY(usable_arenas->nfreepools == 0)) { + assert(usable_arenas->freepools == NULL); + assert(usable_arenas->nextarena == NULL || + usable_arenas->nextarena->prevarena == + usable_arenas); + usable_arenas = usable_arenas->nextarena; + if (usable_arenas != NULL) { + usable_arenas->prevarena = NULL; + assert(usable_arenas->address != 0); + } + } + else { + assert(usable_arenas->freepools != NULL || + usable_arenas->pool_address <= + (block*)usable_arenas->address + + ARENA_SIZE - POOL_SIZE); + } + } + else { + assert(usable_arenas->nfreepools > 0); + assert(usable_arenas->freepools == NULL); + pool = (poolp)usable_arenas->pool_address; + assert((block*)pool <= (block*)usable_arenas->address + + ARENA_SIZE - POOL_SIZE); + pool->arenaindex = (uint)(usable_arenas - arenas); + assert(&arenas[pool->arenaindex] == usable_arenas); + pool->szidx = DUMMY_SIZE_IDX; + usable_arenas->pool_address += POOL_SIZE; + --usable_arenas->nfreepools; + if (usable_arenas->nfreepools == 0) { + assert(usable_arenas->nextarena == NULL || + usable_arenas->nextarena->prevarena == + usable_arenas); + usable_arenas = usable_arenas->nextarena; + if (usable_arenas != NULL) { + usable_arenas->prevarena = NULL; + assert(usable_arenas->address != 0); + } + } + } + next = usedpools[size + size]; + pool->nextpool = next; + pool->prevpool = next; + next->nextpool = pool; + next->prevpool = pool; + pool->ref.count = 1; + if (pool->szidx == size) { + bp = pool->freeblock; + assert(bp != NULL); + pool->freeblock = *(block **)bp; + return bp; + } + pool->szidx = size; + size = INDEX2SIZE(size); + bp = (block *)pool + POOL_OVERHEAD; + pool->nextoffset = POOL_OVERHEAD + (size << 1); + pool->maxnextoffset = POOL_SIZE - size; + pool->freeblock = bp + size; + *(block **)(pool->freeblock) = NULL; + return bp; +""" +assert body.split() == expected.split(), ( + "preserve allocate_from_new_pool arena updates, freepools assignment, and control-flow order" +) +print("obmalloc allocate_from_new_pool pool/bp/next declarations and original operation order: PASS") + + +match = re.search( + r"\npymalloc_alloc\(void \*ctx, size_t nbytes\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "pymalloc_alloc definition not found" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert body.split()[:6] == ["uint", "size;", "poolp", "pool;", "block", "*bp;"], ( + "pymalloc_alloc must declare size, pool, and bp without initializers at function entry" +) + +# Preserve the conditional Valgrind checks and request-size early returns before +# evaluating size and reading usedpools, plus the exact bp branch operations. +expected = """ + uint size; + poolp pool; + block *bp; +#ifdef WITH_VALGRIND + if (UNLIKELY(running_on_valgrind == -1)) { + running_on_valgrind = RUNNING_ON_VALGRIND; + } + if (UNLIKELY(running_on_valgrind)) { + return NULL; + } +#endif + if (UNLIKELY(nbytes == 0)) { + return NULL; + } + if (UNLIKELY(nbytes > SMALL_REQUEST_THRESHOLD)) { + return NULL; + } + size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT; + pool = usedpools[size + size]; + if (LIKELY(pool != pool->nextpool)) { + ++pool->ref.count; + bp = pool->freeblock; + assert(bp != NULL); + if (UNLIKELY((pool->freeblock = *(block **)bp) == NULL)) { + pymalloc_pool_extend(pool, size); + } + } + else { + bp = allocate_from_new_pool(size); + } + return (void *)bp; +""" +assert body.split() == expected.split(), ( + "preserve pymalloc_alloc early returns, size/pool evaluation, and bp control-flow order" +) +print("obmalloc pymalloc_alloc size/pool/bp declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-pymalloc-free-c89.test.py b/scripts/vc6-obmalloc-pymalloc-free-c89.test.py new file mode 100644 index 0000000..369966b --- /dev/null +++ b/scripts/vc6-obmalloc-pymalloc-free-c89.test.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Guard pymalloc_free's C89 locals and complete operation order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"\npymalloc_free\(void \*ctx, void \*p\)\s*\{(.*?)\n\}", + source, re.S, +) +assert match, "pymalloc_free definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = """ + poolp pool; + block *lastfree; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "pymalloc_free must declare pool and lastfree without initializers at function entry" +) + +# Evaluate POOL_ADDR only after the Valgrind early return, and read freeblock +# only after the address-range check and refcount assertion. Preserve all +# free-list writes, refcount updates, branches, helper calls, and returns. +expected = declarations + """ + assert(p != NULL); +#ifdef WITH_VALGRIND + if (UNLIKELY(running_on_valgrind > 0)) { + return 0; + } +#endif + pool = POOL_ADDR(p); + if (UNLIKELY(!address_in_range(p, pool))) { + return 0; + } + assert(pool->ref.count > 0); + lastfree = pool->freeblock; + *(block **)p = lastfree; + pool->freeblock = (block *)p; + pool->ref.count--; + if (UNLIKELY(lastfree == NULL)) { + insert_to_usedpool(pool); + return 1; + } + if (LIKELY(pool->ref.count != 0)) { + return 1; + } + insert_to_freepool(pool); + return 1; +""" +assert body.split() == expected.split(), ( + "preserve pymalloc_free initialization, evaluation, and control-flow order" +) +print("obmalloc pymalloc_free entry declarations and original operation order: PASS") diff --git a/scripts/vc6-obmalloc-rawwcsdup-c89.test.py b/scripts/vc6-obmalloc-rawwcsdup-c89.test.py new file mode 100644 index 0000000..91c7995 --- /dev/null +++ b/scripts/vc6-obmalloc-rawwcsdup-c89.test.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Compile the exact wide-string helper as C89 and check operation ordering.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +allocated = re.search( + r"\n_Py_GetAllocatedBlocks\(void\)\s*\{(.*?)\n\}", source, re.S, +) +assert allocated, "_Py_GetAllocatedBlocks definition not found" +body = re.sub(r"/\*.*?\*/", "", allocated.group(1), flags=re.S) +assert body.split() == """ + Py_ssize_t n = raw_allocated_blocks; + uint i; + uintptr_t base; + for (i = 0; i < maxarenas; ++i) { + if (arenas[i].address == 0) { + continue; + } + base = (uintptr_t)_Py_ALIGN_UP(arenas[i].address, POOL_SIZE); + assert(base <= (uintptr_t) arenas[i].pool_address); + for (; base < (uintptr_t) arenas[i].pool_address; base += POOL_SIZE) { + poolp p = (poolp)base; + n += p->ref.count; + } + } + return n; +""".split(), ( + "_Py_GetAllocatedBlocks must declare uint i and uintptr_t base at entry and preserve loop operations" +) +print("obmalloc allocated-blocks C89 loop declaration and operation order: PASS") +assert re.search( + r"_PyMem_Strdup\(const char \*str\)\s*\{\s*" + r"size_t size;\s*char \*copy;\s*" + r"assert\(str != NULL\);\s*size = strlen\(str\) \+ 1;\s*" + r"copy = PyMem_Malloc\(size\);\s*" + r"if \(copy == NULL\) \{\s*return NULL;\s*\}\s*" + r"memcpy\(copy, str, size\);\s*return copy;\s*\}", + source, +), "_PyMem_Strdup must use C89 entry declarations and preserve operation order" +assert re.search( + r"_PyMem_RawStrdup\(const char \*str\)\s*\{\s*" + r"size_t size;\s*char \*copy;\s*" + r"assert\(str != NULL\);\s*size = strlen\(str\) \+ 1;\s*" + r"copy = PyMem_RawMalloc\(size\);\s*" + r"if \(copy == NULL\) \{\s*return NULL;\s*\}\s*" + r"memcpy\(copy, str, size\);\s*return copy;\s*\}", + source, +), "_PyMem_RawStrdup must use C89 declarations and preserve operation order" +match = re.search( + r"wchar_t\*\s*\n_PyMem_RawWcsdup\s*\([^)]*\)\s*\{.*?\n\}", + source, re.S, +) +assert match, "_PyMem_RawWcsdup definition not found" +harness = r''' +#include +#include +#include +#include +#define PY_SSIZE_T_MAX 32767 +static size_t length_value, allocated_size; +static int stage, fail_alloc; +static wchar_t storage[8]; +static size_t checked_wcslen(const wchar_t *str) { + assert(str != NULL && stage == 0); + stage = 1; + return length_value; +} +static void *PyMem_RawMalloc(size_t size) { + assert(stage == 1); + stage = 2; + allocated_size = size; + return fail_alloc ? NULL : storage; +} +static void *checked_memcpy(void *dst, const void *src, size_t size) { + assert(stage == 2 && size == allocated_size); + stage = 3; + return memcpy(dst, src, size); +} +#define wcslen checked_wcslen +#define memcpy checked_memcpy +''' +harness += match.group(0) +harness += r''' +int main(void) { + const wchar_t input[] = L"abc"; + wchar_t *result; + length_value = 3; + result = _PyMem_RawWcsdup(input); + assert(result == storage && stage == 3); + assert(allocated_size == 4 * sizeof(wchar_t)); + assert(memcmp(result, input, allocated_size) == 0); + stage = 0; + length_value = 0; + result = _PyMem_RawWcsdup(L""); + assert(result == storage && stage == 3 && storage[0] == 0); + assert(allocated_size == sizeof(wchar_t)); + stage = 0; + fail_alloc = 1; + length_value = (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1; + assert(_PyMem_RawWcsdup(input) == NULL && stage == 2); + assert(allocated_size == (length_value + 1) * sizeof(wchar_t)); + stage = 0; + length_value++; + assert(_PyMem_RawWcsdup(input) == NULL && stage == 1); + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-rawwcsdup-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ], check=True) + subprocess.run([str(path / "test")], check=True) +print("obmalloc RawWcsdup C89 compile and copy/empty/allocation-failure/overflow order: PASS") diff --git a/scripts/vc6-obmalloc-setup-allocators-c89.test.py b/scripts/vc6-obmalloc-setup-allocators-c89.test.py new file mode 100644 index 0000000..2d4de05 --- /dev/null +++ b/scripts/vc6-obmalloc-setup-allocators-c89.test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Guard the pymalloc setup block's C89 declarations and allocator order.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +setup = source[source.index("\n_PyMem_SetupAllocators("):] +match = re.search( + r"case PYMEM_ALLOCATOR_PYMALLOC:\s*" + r"case PYMEM_ALLOCATOR_PYMALLOC_DEBUG:\s*\{(.*?)\n \}", + setup, + re.S, +) +assert match, "pymalloc setup block not found" +body = match.group(1) +declarations = """ + PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC; + PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC; +""" +assert body.split()[:len(declarations.split())] == declarations.split(), ( + "both allocator initializers must precede the first statement for C89" +) +expected = declarations + """ + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &malloc_alloc); + PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &pymalloc); + PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &pymalloc); + if (allocator == PYMEM_ALLOCATOR_PYMALLOC_DEBUG) { + PyMem_SetupDebugHooks(); + } + break; +""" +assert body.split() == expected.split(), ( + "preserve allocator initializers, RAW/MEM/OBJ registration order, and debug hooks" +) +for name, values in ( + ("MALLOC_ALLOC", "NULL, _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree"), + ("PYMALLOC_ALLOC", "NULL, _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free"), +): + macro = re.search(r"#\s*define\s+" + name + r"\s+\{([^}]+)\}", source) + assert macro and macro.group(1).split() == values.split(), ( + name + " must preserve ctx/malloc/calloc/realloc/free values and order" + ) +print("obmalloc setup allocators C89 declarations, field values, and RAW/MEM/OBJ/debug order: PASS") diff --git a/scripts/vc6-obmalloc-tracemalloc-init-c89.test.py b/scripts/vc6-obmalloc-tracemalloc-init-c89.test.py new file mode 100644 index 0000000..7e197a6 --- /dev/null +++ b/scripts/vc6-obmalloc-tracemalloc-init-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Check tracemalloc's positional initializer against its header definition.""" + +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +header = Path(sys.argv[2]).read_text() +header = re.sub(r"/\*.*?\*/", "", header, flags=re.S) +layout = re.search(r"struct _PyTraceMalloc_Config \{(.*?)\n\};", header, re.S) +assert layout, "_PyTraceMalloc_Config definition not found" +fields = re.findall(r"\b(\w+)\s*;", layout.group(1)) +assert fields == ["initialized", "tracing", "max_nframe"], ( + "expected initialized, tracing, max_nframe field order" +) +macro = re.search( + r"#define _PyTraceMalloc_Config_INIT\s*\\\s*\{(.*?)\}", header, re.S +) +assert macro, "_PyTraceMalloc_Config_INIT definition not found" +defaults = re.findall(r"\.(\w+)\s*=\s*(\w+)", macro.group(1)) +assert defaults == list(zip(fields, ["TRACEMALLOC_NOT_INITIALIZED", "0", "1"])), ( + "expected uninitialized, tracing disabled, and one traceback frame defaults" +) +initializer = re.search( + r"struct _PyTraceMalloc_Config _Py_tracemalloc_config\s*=\s*(.*?);", + source, + re.S, +) +assert initializer, "_Py_tracemalloc_config initializer not found" +body = re.sub(r"/\*.*?\*/", "", initializer.group(1), flags=re.S).strip() +assert body.startswith("{") and body.endswith("}") and not re.search( + r"\.\s*\w+\s*=", body +), "_Py_tracemalloc_config must use a VC6-compatible positional initializer" +values = [value.strip() for value in body[1:-1].strip().rstrip(",").split(",")] +assert values == [value for field, value in defaults], ( + "positional initializer must preserve every header default in field order" +) +print("obmalloc tracemalloc C89 positional initializer: PASS (initialized=TRACEMALLOC_NOT_INITIALIZED, tracing=0, max_nframe=1)") diff --git a/scripts/vc6-odict-list-c89.test.py b/scripts/vc6-odict-list-c89.test.py new file mode 100644 index 0000000..d9d3e49 --- /dev/null +++ b/scripts/vc6-odict-list-c89.test.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +"""Compile exact odictiter_reduce as C89 and check timing and ownership.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nodictiter_reduce\(odictiterobject \*di, PyObject \*Py_UNUSED\(ignored\)\)\n\{.*?\n\}", + source, re.S, +) +assert match, "odictiter_reduce definition not found" +harness = r''' +#include +#include +#include +typedef struct { int refs; } PyObject; +typedef struct { PyObject *di_odict, *di_current; int position; } odictiterobject; +static PyObject dict, current, list_obj, builtin, result_obj; +static odictiterobject *original; +static int stage, failure, consume; +static int iter; +#define Py_UNUSED(name) unused +#define _Py_ID(name) name +static void Py_XINCREF(PyObject *obj) { + assert(stage < 2); + assert(obj == (stage == 0 ? original->di_odict : original->di_current)); + if (obj != NULL) ++obj->refs; + ++stage; +} +static PyObject *PySequence_List(PyObject *obj) { + odictiterobject *tmp = (odictiterobject *)obj; + assert(stage == 2 && tmp != original); + assert(tmp->di_odict == original->di_odict); + assert(tmp->di_current == original->di_current); + assert(tmp->position == 17); + assert(dict.refs == (original->di_odict ? 2 : 1)); + assert(current.refs == (original->di_current ? 2 : 1)); + tmp->position = 99; + if (consume) { + if (tmp->di_odict) --tmp->di_odict->refs; + if (tmp->di_current) --tmp->di_current->refs; + tmp->di_odict = tmp->di_current = NULL; + } + stage = 3; + list_obj.refs = failure == 1 ? 0 : 1; + return failure == 1 ? NULL : &list_obj; +} +static void Py_XDECREF(PyObject *obj) { + assert(stage == 3 || stage == 4); + assert(obj == (consume ? NULL : (stage == 3 ? original->di_odict : original->di_current))); + if (obj != NULL) --obj->refs; + ++stage; +} +static PyObject *_PyEval_GetBuiltin(int *id) { + assert(stage == 5 && id == &iter && failure != 1); + assert(dict.refs == 1 && current.refs == 1); + stage = 6; + builtin.refs = 1; + return &builtin; +} +static PyObject *Py_BuildValue(const char *format, PyObject *func, PyObject *list) { + assert(stage == 6 && strcmp(format, "N(N)") == 0); + assert(func == &builtin && list == &list_obj); + assert(func->refs == 1 && list->refs == 1); + --func->refs; + --list->refs; + stage = 7; + return failure == 2 ? NULL : &result_obj; +} +''' +harness += match.group(0) +harness += r''' +int main(void) { + int mask; + odictiterobject di; + PyObject *result; + for (mask = 0; mask < 4; ++mask) { + for (consume = 0; consume < 2; ++consume) { + for (failure = 0; failure < 3; ++failure) { + dict.refs = current.refs = 1; + di.di_odict = mask & 1 ? &dict : NULL; + di.di_current = mask & 2 ? ¤t : NULL; + di.position = 17; + original = &di; + stage = 0; + result = odictiter_reduce(&di, NULL); + assert(result == (failure ? NULL : &result_obj)); + assert(stage == (failure == 1 ? 5 : 7)); + assert(dict.refs == 1 && current.refs == 1); + assert(list_obj.refs == 0); + assert(di.di_odict == (mask & 1 ? &dict : NULL)); + assert(di.di_current == (mask & 2 ? ¤t : NULL)); + assert(di.position == 17); + } + } + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-odict-list-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + compiled = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + "-Wno-unused-parameter", str(path / "test.c"), "-o", str(path / "test"), + ]) + if compiled.returncode: + sys.exit(compiled.returncode) + subprocess.run([str(path / "test")], check=True) +print("odictiter_reduce C89 compile and copy/incref/list/cleanup/ownership/failure order: PASS (24 cases)") diff --git a/scripts/vc6-odict-number-c89.test.py b/scripts/vc6-odict-number-c89.test.py new file mode 100644 index 0000000..1f6ac88 --- /dev/null +++ b/scripts/vc6-odict-number-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Compile the exact odict number table as C89 and check every named slot.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1]) +source = source_path.read_text() +match = re.search(r"static PyNumberMethods odict_as_number = \{.*?\n\};", source, re.S) +assert match, "odict_as_number initializer not found" +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"typedef struct \{([^{}]*)\} PyNumberMethods;", header, re.S) +assert layout, "PyNumberMethods layout not found" +# Use the actual header's order and types; check slots by name, not position. +body = re.sub(r"/\*.*?\*/", "", layout.group(1), flags=re.S) +fields = re.findall(r"\b(nb_\w+)\s*;", body) +assert len(fields) == 36 and len(set(fields)) == 36 +harness = r''' +#include +typedef struct { int value; } PyObject; +typedef PyObject *(*binaryfunc)(PyObject *, PyObject *); +typedef PyObject *(*ternaryfunc)(PyObject *, PyObject *, PyObject *); +typedef PyObject *(*unaryfunc)(PyObject *); +typedef int (*inquiry)(PyObject *); +static PyObject *odict_or(PyObject *a, PyObject *b) { (void)b; return a; } +static PyObject *odict_inplace_or(PyObject *a, PyObject *b) { (void)a; return b; } +''' +harness += "typedef struct {" + body + "} PyNumberMethods;\n" +harness += match.group(0) + "\nint main(void) {\n" +for field in fields: + expected = {"nb_or": "odict_or", "nb_inplace_or": "odict_inplace_or"}.get(field, "0") + harness += f" assert(odict_as_number.{field} == {expected});\n" +harness += " return 0;\n}\n" +with tempfile.TemporaryDirectory(prefix="vc6-odict-number-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("odict_as_number C89 compile and all 36 semantic field mappings: PASS") diff --git a/scripts/vc6-odict-or-c89.test.py b/scripts/vc6-odict-or-c89.test.py new file mode 100644 index 0000000..605f397 --- /dev/null +++ b/scripts/vc6-odict-or-c89.test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Compile the exact odict_or as C89 and exercise its operation ordering.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nodict_or\(PyObject \*left, PyObject \*right\)\n\{.*?\n\}", + source, re.S, +) +assert match, "odict_or definition not found" +harness = r''' +#include +#include +typedef struct { int ordered; int dict; } PyObject; +typedef PyObject PyTypeObject; +static PyObject left_obj, right_obj, result_obj, not_implemented; +static PyObject *expected_type; +static int stage, fail_call, fail_update; +static int PyODict_Check(PyObject *obj) { + assert(stage == 0 && obj == &left_obj); + stage = 1; + return obj->ordered; +} +static PyTypeObject *Py_TYPE(PyObject *obj) { + assert(stage == 1 && obj == expected_type); + stage = 2; + return obj; +} +static int PyDict_Check(PyObject *obj) { + assert(stage == 2); + assert(obj == (left_obj.ordered ? &right_obj : &left_obj)); + stage = 3; + return obj->dict; +} +#define Py_RETURN_NOTIMPLEMENTED return ¬_implemented +static PyObject *PyObject_CallOneArg(PyObject *type, PyObject *arg) { + assert(stage == 3 && type == expected_type && arg == &left_obj); + stage = 4; + return fail_call ? NULL : &result_obj; +} +static int mutablemapping_update_arg(PyObject *obj, PyObject *arg) { + assert(stage == 4 && obj == &result_obj && arg == &right_obj); + stage = 5; + return fail_update ? -1 : 0; +} +static void Py_DECREF(PyObject *obj) { + assert(stage == 5 && fail_update && obj == &result_obj); + stage = 6; +} +''' +harness += match.group(0) +harness += r''' +int main(void) { + int ordered, scenario; + PyObject *result; + for (ordered = 0; ordered < 2; ++ordered) { + for (scenario = 0; scenario < 4; ++scenario) { + left_obj.ordered = ordered; + right_obj.ordered = 1; + left_obj.dict = right_obj.dict = scenario != 0; + expected_type = ordered ? &left_obj : &right_obj; + fail_call = scenario == 1; + fail_update = scenario == 2; + stage = 0; + result = odict_or(&left_obj, &right_obj); + if (scenario == 0) { + assert(result == ¬_implemented && stage == 3); + } else if (scenario == 1) { + assert(result == NULL && stage == 4); + } else if (scenario == 2) { + assert(result == NULL && stage == 6); + } else { + assert(result == &result_obj && stage == 5); + } + } + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-odict-or-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + compiled = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if compiled.returncode: + sys.exit(compiled.returncode) + subprocess.run([str(path / "test")], check=True) +print("odict_or C89 compile and operand/rejection/construction/update/cleanup order: PASS (8 cases)") diff --git a/scripts/vc6-odict-update-arg-func-c89.test.py b/scripts/vc6-odict-update-arg-func-c89.test.py new file mode 100644 index 0000000..8dd47e7 --- /dev/null +++ b/scripts/vc6-odict-update-arg-func-c89.test.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +"""Check only update_arg's first declaration frontier, before later blockers.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static int\nmutablemapping_update_arg\(PyObject \*self, PyObject \*arg\)\n\{" + r".*?(?= if \(func != NULL\) \{)", source, re.S, +) +assert match, "mutablemapping_update_arg prefix not found" +# Compile the untouched prefix only: iterator/key declarations farther down +# are independent frontier defects. The synthetic tail observes lookup output. +harness = r''' +#include +#include +typedef struct { int unused; } PyObject; +static PyObject self_obj, arg_obj, items_obj, func_obj; +static int scenario, stage, keys; +#define _Py_ID(name) name +static int PyDict_CheckExact(PyObject *arg) { + assert(stage == 0 && arg == &arg_obj); + stage = 1; + return scenario < 3; +} +static PyObject *PyDict_Items(PyObject *arg) { + assert(stage == 1 && arg == &arg_obj); + stage = 2; + return scenario == 0 ? NULL : &items_obj; +} +static int mutablemapping_add_pairs(PyObject *self, PyObject *items) { + assert(stage == 2 && self == &self_obj && items == &items_obj); + stage = 3; + return scenario == 1 ? -1 : 0; +} +static void Py_DECREF(PyObject *obj) { + assert(stage == 3 && obj == &items_obj); + stage = 4; +} +static int _PyObject_LookupAttr(PyObject *arg, int *id, PyObject **func) { + assert(stage == 1 && arg == &arg_obj && id == &keys); + stage = 5; + *func = scenario == 5 ? &func_obj : NULL; + return scenario == 3 ? -1 : scenario == 5; +} +''' +harness += match.group(0) +harness += r''' + assert(stage == 5 && res == 0); + assert(func == (scenario == 5 ? &func_obj : NULL)); + stage = 6; + return 0; +} +int main(void) { + int result; + for (scenario = 0; scenario < 6; ++scenario) { + stage = 0; + result = mutablemapping_update_arg(&self_obj, &arg_obj); + assert(result == ((scenario < 2 || scenario == 3) ? -1 : 0)); + assert(stage == (scenario == 0 ? 2 : scenario < 3 ? 4 : + scenario == 3 ? 5 : 6)); + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-odict-update-arg-func-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("mutablemapping_update_arg prefix C89 compile and dict/lookup ordering: PASS (6 cases)") diff --git a/scripts/vc6-odict-update-arg-iterator-c89.test.py b/scripts/vc6-odict-update-arg-iterator-c89.test.py new file mode 100644 index 0000000..bf48070 --- /dev/null +++ b/scripts/vc6-odict-update-arg-iterator-c89.test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Compile update_arg's exact keys branch as C89; check evaluation/cleanup order.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +function = source.split("mutablemapping_update_arg(PyObject *self, PyObject *arg)\n{", 1)[1] +match = re.search( + r" if \(func != NULL\) \{.*?(?= if \(_PyObject_LookupAttr\(arg, &_Py_ID\(items\))", + function, re.S, +) +assert match, "update_arg keys branch not found" +harness = r''' +#include +#include +#include +typedef struct { int unused; } PyObject; +static PyObject self_obj, arg_obj, func_obj, keys_obj, iter_obj, key_obj, value_obj; +static int scenario, calls, error; +static char events[64]; +static void event(char c) { + size_t n = strlen(events); + assert(n + 1 < sizeof(events)); + events[n] = c; + events[n + 1] = '\0'; +} +static PyObject * _PyObject_CallNoArgs(PyObject *obj) { + assert(obj == &func_obj); event('C'); + return scenario == 0 ? NULL : &keys_obj; +} +static void Py_DECREF(PyObject *obj) { + if (obj == &func_obj) event('f'); + else if (obj == &keys_obj) event('k'); + else if (obj == &iter_obj) event('i'); + else if (obj == &key_obj) event('q'); + else { assert(obj == &value_obj); event('v'); } +} +static PyObject *PyObject_GetIter(PyObject *obj) { + assert(obj == &keys_obj); event('I'); + return scenario == 1 ? NULL : &iter_obj; +} +static PyObject *PyIter_Next(PyObject *obj) { + assert(obj == &iter_obj); event('N'); + if (scenario == 2 || scenario == 3 || calls++ > 0) { + error = scenario == 3 || scenario == 7; + return NULL; + } + return &key_obj; +} +static PyObject *PyObject_GetItem(PyObject *obj, PyObject *key) { + assert(obj == &arg_obj && key == &key_obj); event('G'); + return scenario == 4 ? NULL : &value_obj; +} +static int PyObject_SetItem(PyObject *obj, PyObject *key, PyObject *value) { + assert(obj == &self_obj && key == &key_obj && value == &value_obj); + event('S'); return scenario == 5 ? -1 : 0; +} +static int PyErr_Occurred(void) { event('E'); return error; } +static int run(PyObject *self, PyObject *arg, PyObject *func) { + int res = 0; +''' +harness += match.group(0) +harness += r''' + return 42; +} +int main(void) { + static const char *expected[] = { + "Cf", "CfIk", "CfIkNiE", "CfIkNiE", + "CfIkNGqi", "CfIkNGSvqi", "CfIkNGSvqNiE", "CfIkNGSvqNiE" + }; + int result; + for (scenario = 0; scenario < 8; ++scenario) { + events[0] = '\0'; calls = error = 0; + result = run(&self_obj, &arg_obj, &func_obj); + assert(result == (scenario == 2 || scenario == 6 ? 0 : -1)); + assert(strcmp(events, expected[scenario]) == 0); + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-odict-update-arg-iterator-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("update_arg keys branch C89 compile and evaluation/cleanup order: PASS (8 cases)") diff --git a/scripts/vc6-odict-update-len-c89.test.py b/scripts/vc6-odict-update-len-c89.test.py new file mode 100644 index 0000000..d9f70e4 --- /dev/null +++ b/scripts/vc6-odict-update-len-c89.test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Compile the exact update body as C89 and check evaluation/dispatch order.""" +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nmutablemapping_update\(PyObject \*self, PyObject \*args, PyObject \*kwargs\)\n\{.*?\n\}", + source, re.S, +) +assert match, "mutablemapping_update not found" +harness = r''' +#include +#include +#include +typedef long Py_ssize_t; +typedef struct { int unused; } PyObject; +static PyObject self_obj, args_obj, kwargs_obj, other_obj, items_obj, none_obj; +static int scenario, PyExc_TypeError; +static char events[64]; +static void event(char c) { + size_t n = strlen(events); + assert(n + 1 < sizeof(events)); + events[n] = c; events[n + 1] = '\0'; +} +static int PyTuple_Check(PyObject *obj) { + assert(obj == &args_obj); event('T'); return 1; +} +static Py_ssize_t PyTuple_GET_SIZE(PyObject *obj) { + assert(obj == &args_obj && strcmp(events, "T") == 0); + event('L'); return scenario == 2 ? 2 : scenario == 1 ? 0 : 1; +} +static void PyErr_Format(int exc, const char *msg, Py_ssize_t len) { + assert(exc == PyExc_TypeError && len == 2); + assert(strcmp(msg, "update() takes at most 1 positional argument (%zd given)") == 0); + event('E'); +} +static PyObject *PyTuple_GET_ITEM(PyObject *obj, int index) { + assert(obj == &args_obj && index == 0); event('G'); return &other_obj; +} +static void Py_INCREF(PyObject *obj) { assert(obj == &other_obj); event('I'); } +static void Py_DECREF(PyObject *obj) { + assert(obj == &other_obj || obj == &items_obj); + event(obj == &other_obj ? 'D' : 'd'); +} +static int mutablemapping_update_arg(PyObject *self, PyObject *other) { + assert(self == &self_obj && other == &other_obj); event('U'); + return scenario == 3 ? -1 : 0; +} +static int PyDict_Check(PyObject *obj) { + assert(obj == &kwargs_obj); event('K'); return 1; +} +static int PyDict_GET_SIZE(PyObject *obj) { + assert(obj == &kwargs_obj); event('S'); return scenario != 5; +} +static PyObject *PyDict_Items(PyObject *obj) { + assert(obj == &kwargs_obj); event('M'); return scenario == 6 ? NULL : &items_obj; +} +static int mutablemapping_add_pairs(PyObject *self, PyObject *items) { + assert(self == &self_obj && items == &items_obj); event('A'); + return scenario == 7 ? -1 : 0; +} +#define Py_RETURN_NONE return &none_obj +''' +harness += match.group(0) +harness += r''' +int main(void) { + static const char *expected[] = { + "", "TL", "TLE", "TLGIUD", "TLGIUD", "TLGIUDKS", + "TLGIUDKSM", "TLGIUDKSMAd", "TLGIUDKSMAd", "KSMAd" + }; + PyObject *result; + for (scenario = 0; scenario < 10; ++scenario) { + events[0] = '\0'; + result = mutablemapping_update(&self_obj, + scenario == 0 || scenario == 9 ? NULL : &args_obj, + scenario >= 5 ? &kwargs_obj : NULL); + assert(result == (scenario == 2 || scenario == 3 || scenario == 6 || + scenario == 7 ? NULL : &none_obj)); + assert(strcmp(events, expected[scenario]) == 0); + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-odict-update-len-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("mutablemapping_update C89 compile and evaluation/dispatch order: PASS (10 cases)") diff --git a/scripts/vc6-picklebuf-buffer-c89.test.py b/scripts/vc6-picklebuf-buffer-c89.test.py new file mode 100644 index 0000000..469878d --- /dev/null +++ b/scripts/vc6-picklebuf-buffer-c89.test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Compile the exact PickleBuffer buffer table as C89 and check both slots.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1]) +source = source_path.read_text() +match = re.search(r"static PyBufferProcs picklebuf_as_buffer = \{.*?\n\};", source, re.S) +assert match, "picklebuf_as_buffer initializer not found" +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"typedef struct \{([^{}]*)\} PyBufferProcs;", header, re.S) +assert layout, "PyBufferProcs layout not found" +body = re.sub(r"/\*.*?\*/", "", layout.group(1), flags=re.S) +assert re.findall(r"\b(bf_\w+)\s*;", body) == ["bf_getbuffer", "bf_releasebuffer"] +harness = r''' +#include +typedef struct { int unused; } PyObject; +typedef struct { int unused; } Py_buffer; +typedef int (*getbufferproc)(PyObject *, Py_buffer *, int); +typedef void (*releasebufferproc)(PyObject *, Py_buffer *); +static int picklebuf_getbuf(PyObject *self, Py_buffer *view, int flags) +{ + (void)self; (void)view; return flags; +} +static void picklebuf_releasebuf(PyObject *self, Py_buffer *view) +{ + (void)self; (void)view; +} +''' +harness += "typedef struct {" + body + "} PyBufferProcs;\n" +harness += match.group(0) +harness += r''' +int main(void) +{ + assert(picklebuf_as_buffer.bf_getbuffer == (getbufferproc)picklebuf_getbuf); + assert(picklebuf_as_buffer.bf_releasebuffer == (releasebufferproc)picklebuf_releasebuf); + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-picklebuf-buffer-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("picklebuf_as_buffer C89 compile and both semantic field mappings: PASS") diff --git a/scripts/vc6-picklebuf-raw-c89.test.py b/scripts/vc6-picklebuf-raw-c89.test.py new file mode 100644 index 0000000..9a2f693 --- /dev/null +++ b/scripts/vc6-picklebuf-raw-c89.test.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Compile the exact picklebuf_raw body as C89 and check its error order.""" +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\npicklebuf_raw\([^\n]+\)\n\{.*?\n\}", source, re.S +) +assert match, "picklebuf_raw not found" +harness = r''' +#include +#include +#include +typedef struct { int unused; } PyObject; +typedef struct { + PyObject *obj; + long *suboffsets; + const char *format; + int ndim; + long itemsize, len; + long *shape, *strides; +} Py_buffer; +typedef struct { Py_buffer view; } PyPickleBufferObject; +typedef struct { Py_buffer view; int flags; } PyMemoryViewObject; +#define Py_UNUSED(name) name +#define _Py_MEMORYVIEW_C 1 +#define _Py_MEMORYVIEW_FORTRAN 2 +static int PyExc_ValueError = 1, PyExc_BufferError = 2; +static int scenario; +static char events[16]; +static PyPickleBufferObject self; +static PyMemoryViewObject memory; +static PyObject base; +static void event(char c) { + size_t n = strlen(events); + assert(n + 1 < sizeof(events)); + events[n] = c; events[n + 1] = '\0'; +} +static void PyErr_SetString(int exc, const char *message) { + assert(exc == (scenario == 0 ? PyExc_ValueError : PyExc_BufferError)); + assert(strcmp(message, scenario == 0 + ? "operation forbidden on released PickleBuffer object" + : "cannot extract raw buffer from non-contiguous buffer") == 0); + event('E'); +} +static int PyBuffer_IsContiguous(Py_buffer *view, char order) { + assert(view == &self.view && order == 'A'); event('C'); + return scenario != 2; +} +static PyObject *PyMemoryView_FromObject(PyObject *obj) { + assert(obj == (PyObject *)&self); event('M'); + return scenario == 3 ? NULL : (PyObject *)&memory; +} +''' +harness += match.group(0) +harness += r''' +int main(void) { + static const char *expected[] = {"E", "E", "CE", "CM", "CM"}; + PyObject *result; + PyMemoryViewObject before; + Py_buffer original; + long offset = 0; + for (scenario = 0; scenario < 5; ++scenario) { + memset(&memory, 0, sizeof(memory)); + memory.view.obj = &base; + memory.view.format = "i"; + memory.view.ndim = 2; + memory.view.itemsize = 4; + memory.view.len = 24; + memory.flags = 8; + memcpy(&before, &memory, sizeof(memory)); + self.view = memory.view; + self.view.obj = scenario == 0 ? NULL : &base; + self.view.suboffsets = scenario == 1 ? &offset : NULL; + memcpy(&original, &self.view, sizeof(original)); + events[0] = '\0'; + result = picklebuf_raw(&self, NULL); + assert(strcmp(events, expected[scenario]) == 0); + assert(memcmp(&original, &self.view, sizeof(original)) == 0); + if (scenario < 4) { + assert(result == NULL); + assert(memcmp(&before, &memory, sizeof(memory)) == 0); + } else { + assert(result == (PyObject *)&memory); + assert(memory.view.obj == &base && memory.view.len == 24); + assert(memory.view.suboffsets == NULL); + assert(strcmp(memory.view.format, "B") == 0); + assert(memory.view.ndim == 1 && memory.view.itemsize == 1); + assert(memory.view.shape == &memory.view.len); + assert(memory.view.strides == &memory.view.itemsize); + assert(memory.flags == (_Py_MEMORYVIEW_C | _Py_MEMORYVIEW_FORTRAN)); + } + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-picklebuf-raw-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + "-Wno-unused-parameter", str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("picklebuf_raw C89 compile and validation/allocation order: PASS (5 cases)") diff --git a/scripts/vc6-picklebuf-type-c89.test.py b/scripts/vc6-picklebuf-type-c89.test.py new file mode 100644 index 0000000..7833b26 --- /dev/null +++ b/scripts/vc6-picklebuf-type-c89.test.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +"""Compile the exact PickleBuffer type as C89 and verify every static slot.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1]) +source = source_path.read_text() +match = re.search(r"PyTypeObject PyPickleBuffer_Type = \{.*?\n\};", source, re.S) +assert match, "PyPickleBuffer_Type initializer not found" +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"struct _typeobject \{(.*?)\n\};", header, re.S) +assert layout, "PyTypeObject layout not found" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", layout.group(1), flags=re.S) +fields = re.findall(r"\b(tp_\w+)\b", body) +assert len(fields) == len(set(fields)) == 48, "review changed PyTypeObject layout" +expected = { + "tp_name": '"pickle.PickleBuffer"', + "tp_basicsize": "sizeof(PyPickleBufferObject)", + "tp_dealloc": "(destructor)picklebuf_dealloc", + "tp_as_buffer": "&picklebuf_as_buffer", + "tp_flags": "Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC", + "tp_doc": '"Wrapper for potentially out-of-band buffers"', + "tp_traverse": "(traverseproc)picklebuf_traverse", + "tp_clear": "(inquiry)picklebuf_clear", + "tp_weaklistoffset": "offsetof(PyPickleBufferObject, weakreflist)", + "tp_methods": "picklebuf_methods", + "tp_new": "picklebuf_new", +} +assert expected.keys() <= set(fields) +# Use the real field declarations/order, with minimal stand-ins for dependencies. +harness = r''' +#include +#include +#include +typedef long Py_ssize_t; +typedef struct { int unused; } PyObject; +typedef struct { int unused; } PyAsyncMethods; +typedef struct { int unused; } PyNumberMethods; +typedef struct { int unused; } PySequenceMethods; +typedef struct { int unused; } PyMappingMethods; +typedef struct { int unused; } PyBufferProcs; +typedef struct { int unused; } PyMethodDef; +typedef struct { int unused; } PyMemberDef; +typedef struct { int unused; } PyGetSetDef; +typedef struct _typeobject PyTypeObject; +typedef struct { int view; PyObject *weakreflist; } PyPickleBufferObject; +#define PyObject_VAR_HEAD long ob_refcnt; PyTypeObject *ob_type; long ob_size; +#define PyVarObject_HEAD_INIT(type, size) 1, type, size, +#define PyDoc_STR(value) value +#define Py_TPFLAGS_DEFAULT 1UL +#define Py_TPFLAGS_HAVE_GC 16384UL +''' +for name in ( + "destructor getattrfunc setattrfunc reprfunc hashfunc ternaryfunc " + "getattrofunc setattrofunc traverseproc inquiry richcmpfunc getiterfunc " + "iternextfunc descrgetfunc descrsetfunc initproc allocfunc newfunc " + "freefunc vectorcallfunc" +).split(): + harness += f"typedef void (*{name})(void);\n" +harness += "struct _typeobject {" + body + "};\n" +for name in ("new", "dealloc", "traverse", "clear"): + harness += f"static void picklebuf_{name}(void) {{ }}\n" +harness += "static PyBufferProcs picklebuf_as_buffer;\n" +harness += "static PyMethodDef picklebuf_methods[1];\n" +harness += match.group(0) + "\nint main(void)\n{\n" +harness += " assert(PyPickleBuffer_Type.ob_refcnt == 1);\n" +harness += " assert(PyPickleBuffer_Type.ob_type == NULL);\n" +harness += " assert(PyPickleBuffer_Type.ob_size == 0);\n" +for field in fields: + value = expected.get(field, "0") + if field in ("tp_name", "tp_doc"): + harness += f" assert(strcmp(PyPickleBuffer_Type.{field}, {value}) == 0);\n" + else: + harness += f" assert(PyPickleBuffer_Type.{field} == ({value}));\n" +harness += " return 0;\n}\n" +with tempfile.TemporaryDirectory(prefix="vc6-picklebuf-type-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("PyPickleBuffer_Type C89 compile and all 48 semantic field mappings: PASS") diff --git a/scripts/vc6-probe.test.sh b/scripts/vc6-probe.test.sh index 4ad8128..f63086c 100755 --- a/scripts/vc6-probe.test.sh +++ b/scripts/vc6-probe.test.sh @@ -32,8 +32,8 @@ bad() { echo "not ok - $1"; fail=1; } # shellcheck source=scripts/vc6-probe.sh source "$PROBE" -prefix='Z:\home\ubuntu\projects\python-win9x\' -input="Z:\\home\\ubuntu\\projects\\python-win9x\\cpython\\Programs\\python.c(1) : error C2061" +prefix='Z:\home\ubuntu\Organized\Legacy-Ports\Projects\python-win9x\' +input="Z:\\home\\ubuntu\\Organized\\Legacy-Ports\\Projects\\python-win9x\\cpython\\Programs\\python.c(1) : error C2061" expected="cpython\\Programs\\python.c(1) : error C2061" actual="$(printf '%s\n' "$input" | strip_prefix "$prefix")" diff --git a/scripts/vc6-rangeobject-index-c89.test.py b/scripts/vc6-rangeobject-index-c89.test.py new file mode 100644 index 0000000..1ad7cd4 --- /dev/null +++ b/scripts/vc6-rangeobject-index-c89.test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Compile the exact range_index body as C89 and check evaluation order.""" +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nrange_index\([^\n]+\)\n\{.*?\n\}", source, re.S +) +assert match, "range_index not found" +harness = r''' +#include +#include +#include +typedef long Py_ssize_t; +typedef struct { int unused; } PyObject; +typedef struct { PyObject *start, *step; } rangeobject; +#define PY_ITERSEARCH_INDEX 2 +static int PyExc_ValueError = 1; +static int scenario; +static char events[16]; +static PyObject ob, start, step, one, idx, quotient, converted; +static rangeobject range; +static void event(char c) { + size_t n = strlen(events); + assert(n + 1 < sizeof(events)); + events[n] = c; events[n + 1] = '\0'; +} +static int PyLong_CheckExact(PyObject *obj) { + assert(obj == &ob); return scenario != 0 && scenario != 1 && scenario != 8; +} +static int PyBool_Check(PyObject *obj) { + assert(obj == &ob); return scenario == 8; +} +static Py_ssize_t _PySequence_IterSearch(PyObject *obj, PyObject *value, int op) { + assert(obj == (PyObject *)&range && value == &ob && op == PY_ITERSEARCH_INDEX); + event('I'); return scenario == 0 ? -1 : 3; +} +static PyObject *PyLong_FromSsize_t(Py_ssize_t value) { + assert(value == 3); event('L'); return &converted; +} +static int range_contains_long(rangeobject *r, PyObject *value) { + assert(r == &range && value == &ob); event('C'); + return scenario == 2 ? -1 : scenario != 3; +} +static PyObject *PyNumber_Subtract(PyObject *value, PyObject *first) { + assert(value == &ob && first == &start); event('S'); + return scenario == 4 ? NULL : &idx; +} +static PyObject *_PyLong_GetOne(void) { event('O'); return &one; } +static PyObject *PyNumber_FloorDivide(PyObject *value, PyObject *divisor) { + assert(value == &idx && divisor == &step); event('F'); + return scenario == 6 ? NULL : "ient; +} +static void Py_DECREF(PyObject *value) { assert(value == &idx); event('D'); } +static void PyErr_Format(int exc, const char *format, PyObject *value) { + assert(exc == PyExc_ValueError && value == &ob); + assert(strcmp(format, "%R is not in range") == 0); event('E'); +} +''' +harness += match.group(0) +harness += r''' +int main(void) { + static const char *expected[] = { + "I", "IL", "C", "CE", "CS", "CSO", "CSOFD", "CSOFD", "CSOFD" + }; + PyObject *result; + for (scenario = 0; scenario < 9; ++scenario) { + range.start = &start; + range.step = scenario == 5 ? &one : &step; + events[0] = '\0'; + result = range_index(&range, &ob); + assert(strcmp(events, expected[scenario]) == 0); + if (scenario == 1) assert(result == &converted); + else if (scenario == 5) assert(result == &idx); + else if (scenario == 7 || scenario == 8) assert(result == "ient); + else assert(result == NULL); + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-rangeobject-index-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + "-Wno-unused-parameter", str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("range_index C89 compile and evaluation/cleanup order: PASS (9 cases)") diff --git a/scripts/vc6-rangeobject-number-c89.test.py b/scripts/vc6-rangeobject-number-c89.test.py new file mode 100644 index 0000000..f6d5b5e --- /dev/null +++ b/scripts/vc6-rangeobject-number-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Compile the exact range number table as C89 and check every named slot.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1]) +source = source_path.read_text() +match = re.search(r"static PyNumberMethods range_as_number = \{.*?\n\};", source, re.S) +assert match, "range_as_number initializer not found" +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"typedef struct \{([^{}]*)\} PyNumberMethods;", header, re.S) +assert layout, "PyNumberMethods layout not found" +# Use the actual header's order and types; check slots by name, not position. +body = re.sub(r"/\*.*?\*/", "", layout.group(1), flags=re.S) +fields = re.findall(r"\b(nb_\w+)\s*;", body) +assert len(fields) == 36 and len(set(fields)) == 36 +assert len(body.split(";")) == len(fields) + 1, "unparsed header field" +harness = r''' +#include +typedef struct { int value; } PyObject; +typedef PyObject *(*binaryfunc)(PyObject *, PyObject *); +typedef PyObject *(*ternaryfunc)(PyObject *, PyObject *, PyObject *); +typedef PyObject *(*unaryfunc)(PyObject *); +typedef int (*inquiry)(PyObject *); +static int range_bool(PyObject *self) { (void)self; return 1; } +''' +harness += "typedef struct {" + body + "} PyNumberMethods;\n" +harness += match.group(0) + "\nint main(void) {\n" +for field in fields: + expected = {"nb_bool": "(inquiry)range_bool"}.get(field, "0") + harness += f" assert(range_as_number.{field} == {expected});\n" +harness += " return 0;\n}\n" +with tempfile.TemporaryDirectory(prefix="vc6-rangeobject-number-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("range_as_number C89 compile and all 36 semantic field mappings: PASS") diff --git a/scripts/vc6-rangeobject-vectorcall-c89.test.py b/scripts/vc6-rangeobject-vectorcall-c89.test.py new file mode 100644 index 0000000..0ef7caf --- /dev/null +++ b/scripts/vc6-rangeobject-vectorcall-c89.test.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Compile the exact range type as C89 and verify every static slot.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1]) +source = source_path.read_text() +match = re.search(r"PyTypeObject PyRange_Type = \{.*?\n\};", source, re.S) +assert match, "PyRange_Type initializer not found" +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"struct _typeobject \{(.*?)\n\};", header, re.S) +assert layout, "PyTypeObject layout not found" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", layout.group(1), flags=re.S) +fields = re.findall(r"\b(tp_\w+)\b", body) +assert len(fields) == len(set(fields)) == 48, "review changed PyTypeObject layout" +expected = { + "tp_name": '"range"', + "tp_basicsize": "sizeof(rangeobject)", + "tp_dealloc": "(destructor)range_dealloc", + "tp_repr": "(reprfunc)range_repr", + "tp_as_number": "&range_as_number", + "tp_as_sequence": "&range_as_sequence", + "tp_as_mapping": "&range_as_mapping", + "tp_hash": "(hashfunc)range_hash", + "tp_getattro": "PyObject_GenericGetAttr", + "tp_flags": "Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SEQUENCE", + "tp_doc": "range_doc", + "tp_richcompare": "range_richcompare", + "tp_iter": "range_iter", + "tp_methods": "range_methods", + "tp_members": "range_members", + "tp_new": "range_new", + "tp_vectorcall": "(vectorcallfunc)range_vectorcall", +} +assert expected.keys() <= set(fields) +# Use the real field declarations/order, with minimal stand-ins for dependencies. +harness = r''' +#include +#include +#include +typedef long Py_ssize_t; +typedef struct { int unused; } PyObject; +typedef struct { int unused; } PyAsyncMethods; +typedef struct { int unused; } PyNumberMethods; +typedef struct { int unused; } PySequenceMethods; +typedef struct { int unused; } PyMappingMethods; +typedef struct { int unused; } PyBufferProcs; +typedef struct { int unused; } PyMethodDef; +typedef struct { int unused; } PyMemberDef; +typedef struct { int unused; } PyGetSetDef; +typedef struct _typeobject PyTypeObject; +typedef struct { PyObject *start, *stop, *step, *length; } rangeobject; +#define PyObject_VAR_HEAD long ob_refcnt; PyTypeObject *ob_type; long ob_size; +#define PyVarObject_HEAD_INIT(type, size) 1, type, size, +#define Py_TPFLAGS_DEFAULT 1UL +#define Py_TPFLAGS_SEQUENCE 32UL +''' +for name in ( + "destructor getattrfunc setattrfunc reprfunc hashfunc ternaryfunc " + "getattrofunc setattrofunc traverseproc inquiry richcmpfunc getiterfunc " + "iternextfunc descrgetfunc descrsetfunc initproc allocfunc newfunc " + "freefunc vectorcallfunc" +).split(): + harness += f"typedef void (*{name})(void);\n" +harness += "struct _typeobject {" + body + "};\n" +for name in ( + "range_new range_dealloc range_repr range_hash PyObject_GenericGetAttr " + "range_richcompare range_iter range_vectorcall" +).split(): + harness += f"static void {name}(void) {{ }}\n" +harness += "static PyTypeObject PyType_Type;\n" +harness += "static PyNumberMethods range_as_number;\n" +harness += "static PySequenceMethods range_as_sequence;\n" +harness += "static PyMappingMethods range_as_mapping;\n" +harness += "static PyMethodDef range_methods[1];\n" +harness += "static PyMemberDef range_members[1];\n" +harness += 'static const char range_doc[] = "range documentation";\n' +harness += match.group(0) + "\nint main(void)\n{\n" +harness += " assert(PyRange_Type.ob_refcnt == 1);\n" +harness += " assert(PyRange_Type.ob_type == &PyType_Type);\n" +harness += " assert(PyRange_Type.ob_size == 0);\n" +for field in fields: + value = expected.get(field, "0") + if field in ("tp_name", "tp_doc"): + harness += f" assert(strcmp(PyRange_Type.{field}, {value}) == 0);\n" + else: + harness += f" assert(PyRange_Type.{field} == ({value}));\n" +harness += " return 0;\n}\n" +with tempfile.TemporaryDirectory(prefix="vc6-rangeobject-vectorcall-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("PyRange_Type C89 compile and all 48 semantic field mappings: PASS") diff --git a/scripts/vc6-setobject-frozenset-vectorcall-c89.test.py b/scripts/vc6-setobject-frozenset-vectorcall-c89.test.py new file mode 100644 index 0000000..4a7fe93 --- /dev/null +++ b/scripts/vc6-setobject-frozenset-vectorcall-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Check frozenset_vectorcall's C89 declarations and evaluation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nfrozenset_vectorcall\(PyObject \*type, PyObject \* const\*args," + r"\s*size_t nargsf, PyObject \*kwnames\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "frozenset_vectorcall not found" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t nargs;\s*PyObject \*iterable;", body), ( + "nargs and iterable must be declared without initializers in the initial block" +) +expected = """ + Py_ssize_t nargs; + PyObject *iterable; + + if (!_PyArg_NoKwnames("frozenset", kwnames)) { + return NULL; + } + + nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) { + return NULL; + } + + iterable = (nargs ? args[0] : NULL); + return make_new_frozenset(_PyType_CAST(type), iterable); +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve keyword rejection, nargs evaluation, positional rejection, guarded " + "iterable evaluation, and construction in their original order" +) +print("frozenset_vectorcall C89 declarations and evaluation order: PASS") diff --git a/scripts/vc6-setobject-issuperset-c89.test.py b/scripts/vc6-setobject-issuperset-c89.test.py new file mode 100644 index 0000000..5c9d164 --- /dev/null +++ b/scripts/vc6-setobject-issuperset-c89.test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Check set_issuperset's C89 declarations and unchanged iterator ownership.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nset_issuperset\(PySetObject \*so, PyObject \*other\)" + r"\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "set_issuperset not found" +body = match.group(1) +assert re.match(r"\s*PyObject \*key;\s*PyObject \*it;", body), ( + "set_issuperset: key and it must be declared in the initial declaration " + "block; late PyObject declaration after PyAnySet_Check is not C89 compatible" +) +expected = """ + PyObject *key; + PyObject *it; + + if (PyAnySet_Check(other)) { + return set_issubset((PySetObject *)other, (PyObject *)so); + } + + it = PyObject_GetIter(other); + if (it == NULL) { + return NULL; + } + while ((key = PyIter_Next(it)) != NULL) { + int rv = set_contains_key(so, key); + Py_DECREF(key); + if (rv < 0) { + Py_DECREF(it); + return NULL; + } + if (!rv) { + Py_DECREF(it); + Py_RETURN_FALSE; + } + } + Py_DECREF(it); + if (PyErr_Occurred()) { + return NULL; + } + Py_RETURN_TRUE; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve the set fast path, iterator acquisition, loop, reference ownership, " + "error handling, and return behavior" +) +print("set_issuperset C89 declarations and iterator ownership: PASS") diff --git a/scripts/vc6-setobject-make-new-set-c89.test.py b/scripts/vc6-setobject-make-new-set-c89.test.py new file mode 100644 index 0000000..ff49122 --- /dev/null +++ b/scripts/vc6-setobject-make-new-set-c89.test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Check make_new_set's C89 declaration and assertion/allocation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nmake_new_set\(PyTypeObject \*type, PyObject \*iterable\)" + r"\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "make_new_set not found" +body = match.group(1) +assert re.match(r"\s*PySetObject \*so;", body), ( + "so must be declared without initializer before the assertion" +) +assert re.match( + r"\s*PySetObject \*so;\s*assert\(PyType_Check\(type\)\);" + r"\s*so = \(PySetObject \*\)type->tp_alloc\(type, 0\);" + r"\s*if \(so == NULL\)\s*return NULL;", + body, +), "type assertion, allocation, and allocation failure check must retain their order" +assert body.count("PySetObject *so;") == 1, "so must be declared exactly once" +assert body.count("type->tp_alloc(") == 1, "allocation must occur exactly once" +print("make_new_set C89 declaration and assertion/allocation order: PASS") diff --git a/scripts/vc6-setobject-setiter-reduce-c89.test.py b/scripts/vc6-setobject-setiter-reduce-c89.test.py new file mode 100644 index 0000000..431d3ac --- /dev/null +++ b/scripts/vc6-setobject-setiter-reduce-c89.test.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Compile the exact setiter_reduce as C89 and check ownership and call order.""" +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject \*\nsetiter_reduce\([^\n]+\)\n\{.*?\n\}", source, re.S +) +assert match, "setiter_reduce not found" +harness = r''' +#include +#include +#include +typedef struct { int refs; } PyObject; +typedef struct { + PyObject head; + PyObject *si_set; + long si_used, si_pos, len; +} setiterobject; +#define Py_UNUSED(name) name +#define _Py_ID(name) name +static int iter, mode, exhausted; +static PyObject backing, list_value, builtin, built; +static setiterobject original; +static char events[32]; +static void event(char c) { + size_t n = strlen(events); + assert(n + 1 < sizeof(events)); + events[n] = c; + events[n + 1] = '\0'; +} +static void Py_XINCREF(PyObject *obj) { + assert(obj == original.si_set); + assert(strcmp(events, "") == 0); + event('I'); + if (obj != NULL) ++obj->refs; +} +static void Py_XDECREF(PyObject *obj) { + assert(obj == (mode == 1 ? NULL : original.si_set)); + assert(strcmp(events, "IL") == 0); + event('D'); + if (obj != NULL) --obj->refs; +} +static PyObject *PySequence_List(PyObject *obj) { + setiterobject *tmp = (setiterobject *)obj; + assert(tmp != &original); + assert(tmp->head.refs == original.head.refs); + assert(tmp->si_set == original.si_set); + assert(tmp->si_used == original.si_used); + assert(tmp->si_pos == original.si_pos && tmp->len == original.len); + assert(backing.refs == (exhausted ? 1 : 2)); + assert(strcmp(events, "I") == 0); + event('L'); + tmp->si_pos = 99; + tmp->len = 0; + if (mode == 1 && tmp->si_set != NULL) { + --tmp->si_set->refs; + tmp->si_set = NULL; + } + return mode == 2 ? NULL : &list_value; +} +static PyObject *_PyEval_GetBuiltin(int *name) { + assert(name == &iter); + assert(strcmp(events, "ILD") == 0 && backing.refs == 1); + event('G'); + return &builtin; +} +static PyObject *Py_BuildValue(const char *format, PyObject *func, PyObject *list) { + assert(strcmp(format, "N(N)") == 0); + assert(func == &builtin && list == &list_value); + assert(strcmp(events, "ILDG") == 0 && backing.refs == 1); + event('B'); + --func->refs; + --list->refs; + return mode == 3 ? NULL : &built; +} +''' +harness += match.group(0) +harness += r''' +int main(void) { + setiterobject before; + PyObject *result; + for (exhausted = 0; exhausted < 2; ++exhausted) { + for (mode = 0; mode < 4; ++mode) { + backing.refs = list_value.refs = builtin.refs = 1; + memset(&original, 0, sizeof(original)); + original.head.refs = 7; + original.si_set = exhausted ? NULL : &backing; + original.si_used = 5; + original.si_pos = 2; + original.len = 3; + memcpy(&before, &original, sizeof(before)); + events[0] = '\0'; + result = setiter_reduce(&original, NULL); + assert(memcmp(&before, &original, sizeof(before)) == 0); + assert(backing.refs == 1); + assert(strcmp(events, mode == 2 ? "ILD" : "ILDGB") == 0); + assert(result == (mode >= 2 ? NULL : &built)); + assert(list_value.refs == (mode == 2 ? 1 : 0)); + assert(builtin.refs == (mode == 2 ? 1 : 0)); + } + } + return 0; +} +''' +with tempfile.TemporaryDirectory(prefix="vc6-setiter-reduce-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + "-Wno-unused-parameter", str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("setiter_reduce C89 declaration/evaluation/cleanup/return: PASS (8 cases)") diff --git a/scripts/vc6-setobject-table-resize-c89.test.py b/scripts/vc6-setobject-table-resize-c89.test.py new file mode 100644 index 0000000..dc15bba --- /dev/null +++ b/scripts/vc6-setobject-table-resize-c89.test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Check set_table_resize's C89 declaration and preserve resize sizing order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static int\nset_table_resize\(PySetObject \*so, Py_ssize_t minused\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "set_table_resize not found" +body = match.group(1) +assert re.search(r"^\s*size_t newsize;\s*$", body, re.M), ( + "newsize must be declared without initializer in the function declaration block" +) +assert re.search( + r"assert\(minused >= 0\);\s*/\* Find the smallest table size > minused\. \*/" + r"\s*/\* XXX speed-up with intrinsics \*/\s*newsize = PySet_MINSIZE;" + r"\s*while \(newsize <= \(size_t\)minused\)", + body, +), "newsize initialization and resize loop must remain after the assertion in original order" +print("set_table_resize C89 declaration and sizing order: PASS") diff --git a/scripts/vc6-setobject-type-vectorcall-c89.test.py b/scripts/vc6-setobject-type-vectorcall-c89.test.py new file mode 100644 index 0000000..0cf49e8 --- /dev/null +++ b/scripts/vc6-setobject-type-vectorcall-c89.test.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +"""Compile the exact set types as C89 and verify every static slot.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1]) +source = source_path.read_text() +initializers = {} +for name in ("PySet_Type", "PyFrozenSet_Type"): + match = re.search(r"PyTypeObject " + name + r" = \{.*?\n\};", source, re.S) + assert match, name + " initializer not found" + initializers[name] = match.group(0) +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"struct _typeobject \{(.*?)\n\};", header, re.S) +assert layout, "PyTypeObject layout not found" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", layout.group(1), flags=re.S) +fields = re.findall(r"\b(tp_\w+)\b", body) +assert len(fields) == len(set(fields)) == 48, "review changed PyTypeObject layout" +expected = { + "tp_basicsize": "sizeof(PySetObject)", + "tp_dealloc": "(destructor)set_dealloc", + "tp_repr": "(reprfunc)set_repr", + "tp_as_sequence": "&set_as_sequence", + "tp_getattro": "PyObject_GenericGetAttr", + "tp_flags": "Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | _Py_TPFLAGS_MATCH_SELF", + "tp_traverse": "(traverseproc)set_traverse", + "tp_clear": "(inquiry)set_clear_internal", + "tp_richcompare": "(richcmpfunc)set_richcompare", + "tp_weaklistoffset": "offsetof(PySetObject, weakreflist)", + "tp_iter": "(getiterfunc)set_iter", + "tp_alloc": "PyType_GenericAlloc", + "tp_free": "PyObject_GC_Del", +} +assert expected.keys() <= set(fields) +# Use the real field declarations/order, with minimal stand-ins for dependencies. +harness = r''' +#include +#include +#include +typedef long Py_ssize_t; +typedef struct { int unused; } PyObject; +typedef struct { int unused; } PyAsyncMethods; +typedef struct { int unused; } PyNumberMethods; +typedef struct { int unused; } PySequenceMethods; +typedef struct { int unused; } PyMappingMethods; +typedef struct { int unused; } PyBufferProcs; +typedef struct { int unused; } PyMethodDef; +typedef struct { int unused; } PyMemberDef; +typedef struct { int unused; } PyGetSetDef; +typedef struct _typeobject PyTypeObject; +typedef struct { long head; PyObject *weakreflist; } PySetObject; +#define PyObject_VAR_HEAD long ob_refcnt; PyTypeObject *ob_type; long ob_size; +#define PyVarObject_HEAD_INIT(type, size) 1, type, size, +#define Py_TPFLAGS_DEFAULT 1UL +#define Py_TPFLAGS_HAVE_GC 2UL +#define Py_TPFLAGS_BASETYPE 4UL +#define _Py_TPFLAGS_MATCH_SELF 8UL +''' +for name in ( + "destructor getattrfunc setattrfunc reprfunc hashfunc ternaryfunc " + "getattrofunc setattrofunc traverseproc inquiry richcmpfunc getiterfunc " + "iternextfunc descrgetfunc descrsetfunc initproc allocfunc newfunc " + "freefunc vectorcallfunc" +).split(): + harness += f"typedef void (*{name})(void);\n" +harness += "struct _typeobject {" + body + "};\n" +for name in ( + "set_new frozenset_new set_dealloc set_repr PyObject_HashNotImplemented " + "frozenset_hash PyObject_GenericGetAttr set_traverse set_clear_internal " + "set_richcompare set_iter set_init PyType_GenericAlloc PyObject_GC_Del " + "set_vectorcall frozenset_vectorcall" +).split(): + harness += f"static void {name}(void) {{ }}\n" +harness += "static PyTypeObject PyType_Type;\n" +harness += "static PySequenceMethods set_as_sequence;\n" +for prefix in ("set", "frozenset"): + harness += f"static PyNumberMethods {prefix}_as_number;\n" + harness += f"static PyMethodDef {prefix}_methods[1];\n" + harness += f'static const char {prefix}_doc[] = "{prefix} documentation";\n' +harness += "\n".join(initializers.values()) + "\nint main(void)\n{\n" +for name, prefix in (("PySet_Type", "set"), ("PyFrozenSet_Type", "frozenset")): + values = dict(expected, tp_name=f'"{prefix}"', + tp_as_number=f"&{prefix}_as_number", tp_doc=f"{prefix}_doc", + tp_methods=f"{prefix}_methods", tp_new=f"{prefix}_new", + tp_vectorcall=f"{prefix}_vectorcall", + tp_hash="PyObject_HashNotImplemented" if prefix == "set" else "frozenset_hash", + tp_init="(initproc)set_init" if prefix == "set" else "0") + assert values.keys() <= set(fields) + harness += f" assert({name}.ob_refcnt == 1);\n" + harness += f" assert({name}.ob_type == &PyType_Type);\n" + harness += f" assert({name}.ob_size == 0);\n" + for field in fields: + value = values.get(field, "0") + if field in ("tp_name", "tp_doc"): + harness += f" assert(strcmp({name}.{field}, {value}) == 0);\n" + else: + harness += f" assert({name}.{field} == ({value}));\n" +harness += " return 0;\n}\n" +with tempfile.TemporaryDirectory(prefix="vc6-setobject-type-vectorcall-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("PySet_Type and PyFrozenSet_Type C89 compile and all 48 semantic field mappings each: PASS") diff --git a/scripts/vc6-setobject-vectorcall-c89.test.py b/scripts/vc6-setobject-vectorcall-c89.test.py new file mode 100644 index 0000000..dae091b --- /dev/null +++ b/scripts/vc6-setobject-vectorcall-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Check set_vectorcall's C89 declaration and unchanged evaluation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1]).read_text() +match = re.search( + r"static PyObject\*\nset_vectorcall\(PyObject \*type, PyObject \* const\*args," + r"\s*size_t nargsf, PyObject \*kwnames\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "set_vectorcall not found" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t nargs;", body), ( + "set_vectorcall: nargs must be declared without an initializer before " + "assert(PyType_Check(type)); late declaration is not C89 compatible" +) +expected = """ + Py_ssize_t nargs; + + assert(PyType_Check(type)); + + if (!_PyArg_NoKwnames("set", kwnames)) { + return NULL; + } + + nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("set", nargs, 0, 1)) { + return NULL; + } + + if (nargs) { + return make_new_set(_PyType_CAST(type), args[0]); + } + + return make_new_set(_PyType_CAST(type), NULL); +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve type assertion, keyword rejection, nargs evaluation, positional " + "rejection, guarded args[0] access, and construction in their original order" +) +print("set_vectorcall C89 declaration and evaluation order: PASS") diff --git a/scripts/vc6-sliceobject-py-slice-new-c89.test.py b/scripts/vc6-sliceobject-py-slice-new-c89.test.py new file mode 100644 index 0000000..83cc5c4 --- /dev/null +++ b/scripts/vc6-sliceobject-py-slice-new-c89.test.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +"""Regression for PySlice_New declarations accepted by VC6 C89.""" +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/sliceobject.c") +text = source.read_text() +match = re.search(r"PySlice_New\(PyObject \*start, PyObject \*stop, PyObject \*step\)\s*\{(.*?)\n\}", text, re.S) +assert match, "PySlice_New definition not found" +body = match.group(1) +assert re.search(r"^\s*PyInterpreterState \*interp;\s*$", body, re.M), "interp must be declared at function entry" +assert re.search(r"^\s*PySliceObject \*obj;\s*$", body, re.M), "obj must be declared at function entry" +assert "PyInterpreterState *interp = _PyInterpreterState_GET();" not in body, "interp initialization must remain a separate assignment" +assert re.search(r"interp\s*=\s*_PyInterpreterState_GET\(\);", body), "preserve interpreter lookup" +print("PySlice_New C89 declaration placement and lookup: PASS") diff --git a/scripts/vc6-sliceobject-richcompare-c89.test.py b/scripts/vc6-sliceobject-richcompare-c89.test.py new file mode 100644 index 0000000..f2633b0 --- /dev/null +++ b/scripts/vc6-sliceobject-richcompare-c89.test.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Guard slice_richcompare C89 locals and allocation/refcount order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/sliceobject.c") +match = re.search( + r"\nslice_richcompare\(PyObject \*v, PyObject \*w, int op\)\s*\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "slice_richcompare definition not found" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +declarations = re.match( + r"\s*PyObject \*t1;\s*PyObject \*t2;\s*PyObject \*res;", body +) +assert declarations, "slice_richcompare must declare t1, t2, res without initializers at function entry" + +expected_statements = """ + if (!PySlice_Check(v) || !PySlice_Check(w)) + Py_RETURN_NOTIMPLEMENTED; + if (v == w) { + switch (op) { + case Py_EQ: + case Py_LE: + case Py_GE: + res = Py_True; + break; + default: + res = Py_False; + break; + } + Py_INCREF(res); + return res; + } + t1 = PyTuple_Pack(3, + ((PySliceObject *)v)->start, + ((PySliceObject *)v)->stop, + ((PySliceObject *)v)->step); + if (t1 == NULL) { + return NULL; + } + t2 = PyTuple_Pack(3, + ((PySliceObject *)w)->start, + ((PySliceObject *)w)->stop, + ((PySliceObject *)w)->step); + if (t2 == NULL) { + Py_DECREF(t1); + return NULL; + } + res = PyObject_RichCompare(t1, t2, op); + Py_DECREF(t1); + Py_DECREF(t2); + return res; +""" +assert body[declarations.end():].split() == expected_statements.split(), ( + "slice_richcompare must preserve shortcut/allocation/failure/comparison/refcount order without late declarations" +) +print("slice_richcompare C89 declarations and allocation/refcount order: PASS") diff --git a/scripts/vc6-structseq-dealloc-c89.test.py b/scripts/vc6-structseq-dealloc-c89.test.py new file mode 100644 index 0000000..a185ef0 --- /dev/null +++ b/scripts/vc6-structseq-dealloc-c89.test.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Check structseq_dealloc's C89 declarations and teardown order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static void\nstructseq_dealloc\(PyStructSequence \*obj\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "structseq_dealloc definition not found" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t i, size;\s*PyTypeObject \*tp;", body), ( + "structseq_dealloc: tp must be declared without initializer alongside i and " + "size before GC untracking; declaration after statement is not C89 compatible" +) +expected = """ + Py_ssize_t i, size; + PyTypeObject *tp; + PyObject_GC_UnTrack(obj); + + tp = Py_TYPE(obj); + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_XDECREF(obj->ob_item[i]); + } + PyObject_GC_Del(obj); + if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) { + Py_DECREF(tp); + } +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve GC untracking before type capture and size lookup, item decref " + "order, GC deletion, and conditional heap-type decref" +) +print("structseq_dealloc C89 declarations and teardown order: PASS") diff --git a/scripts/vc6-structseq-initialize-structseq-dict-c89.test.py b/scripts/vc6-structseq-initialize-structseq-dict-c89.test.py new file mode 100644 index 0000000..0142f1d --- /dev/null +++ b/scripts/vc6-structseq-initialize-structseq-dict-c89.test.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Check initialize_structseq_dict's C89 declarations and operation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static int\ninitialize_structseq_dict\(.*?\) \{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "initialize_structseq_dict definition not found" +body = match.group(1) +assert re.match( + r"\s*PyObject \*v;\s*Py_ssize_t i, k;\s*PyObject\* keys;", body +), "i, k, and uninitialized keys must precede all statements for C89" +assert re.search( + r"for \(i = k = 0; i < desc->n_in_sequence; \+\+i\) \{" + r"\s*PyObject\* new_member;\s*if", body +), "uninitialized new_member must precede the loop's unnamed-field check for C89" + +expected = r""" + PyObject *v; + Py_ssize_t i, k; + PyObject* keys; + +#define SET_DICT_FROM_SIZE(key, value) \ + do { \ + v = PyLong_FromSsize_t(value); \ + if (v == NULL) { \ + return -1; \ + } \ + if (PyDict_SetItemString(dict, key, v) < 0) { \ + Py_DECREF(v); \ + return -1; \ + } \ + Py_DECREF(v); \ + } while (0) + + SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence); + SET_DICT_FROM_SIZE(real_length_key, n_members); + SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members); + + // Prepare and set __match_args__ + keys = PyTuple_New(desc->n_in_sequence); + if (keys == NULL) { + return -1; + } + + for (i = k = 0; i < desc->n_in_sequence; ++i) { + PyObject* new_member; + if (desc->fields[i].name == PyStructSequence_UnnamedField) { + continue; + } + new_member = PyUnicode_FromString(desc->fields[i].name); + if (new_member == NULL) { + goto error; + } + PyTuple_SET_ITEM(keys, k, new_member); + k++; + } + + if (_PyTuple_Resize(&keys, k) == -1) { + goto error; + } + + if (PyDict_SetItemString(dict, match_args_key, keys) < 0) { + goto error; + } + + Py_DECREF(keys); + return 0; + +error: + Py_DECREF(keys); + return -1; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve metadata writes and early returns before tuple allocation, skip " + "unnamed fields before Unicode allocation, and preserve insertion, resize, " + "match-args write, refcount, and cleanup order" +) +print("initialize_structseq_dict C89 declarations and operation order: PASS") diff --git a/scripts/vc6-structseq-new-c89.test.py b/scripts/vc6-structseq-new-c89.test.py new file mode 100644 index 0000000..9d44ef9 --- /dev/null +++ b/scripts/vc6-structseq-new-c89.test.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +"""Check PyStructSequence_New's C89 declaration and size lookup order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"PyStructSequence_New\(PyTypeObject \*type\)\s*\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "PyStructSequence_New definition not found" +body = match.group(1) +assert re.match( + r"\s*PyStructSequence \*obj;" + r"\s*Py_ssize_t size = REAL_SIZE_TP\(type\), i;" + r"\s*Py_ssize_t vsize;", + body, +), "vsize must be declared without initializer before the size < 0 check" +assert re.match( + r"\s*PyStructSequence \*obj;" + r"\s*Py_ssize_t size = REAL_SIZE_TP\(type\), i;" + r"\s*Py_ssize_t vsize;" + r"\s*if \(size < 0\) \{\s*return NULL;\s*\}" + r"\s*vsize = VISIBLE_SIZE_TP\(type\);" + r"\s*if \(vsize < 0\) \{\s*return NULL;\s*\}" + r"\s*obj = PyObject_GC_NewVar\(PyStructSequence, type, size\);", + body, +), "preserve size early return, visible-size lookup, and allocation order" +assert body.count("VISIBLE_SIZE_TP(type)") == 1, "visible size must be read exactly once" +assert body.count("Py_ssize_t vsize;") == 1, "vsize must be declared exactly once" +print("PyStructSequence_New C89 declaration and size lookup order: PASS") diff --git a/scripts/vc6-structseq-newtype-slots-c89.test.py b/scripts/vc6-structseq-newtype-slots-c89.test.py new file mode 100644 index 0000000..86aa069 --- /dev/null +++ b/scripts/vc6-structseq-newtype-slots-c89.test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Check NewType's C89 slot assignments and preserve all eight slot pairs.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"\n_PyStructSequence_NewType\([^\n]*\)\n\{.*?" + r"/\* Initialize Slots \*/(.*?)/\* Initialize Spec \*/", + source.read_text(), + re.S, +) +assert match, "_PyStructSequence_NewType slots initialization not found" +body = match.group(1) +assert not re.search(r"\(\s*PyType_Slot\s*\)\s*\{", body), ( + "_PyStructSequence_NewType: compound-literal slot initializers are not C89 compatible" +) +pairs = [ + ("Py_tp_dealloc", "(destructor)structseq_dealloc"), + ("Py_tp_repr", "(reprfunc)structseq_repr"), + ("Py_tp_doc", "(void *)desc->doc"), + ("Py_tp_methods", "structseq_methods"), + ("Py_tp_new", "structseq_new"), + ("Py_tp_members", "members"), + ("Py_tp_traverse", "(traverseproc)structseq_traverse"), + ("0", "0"), +] +expected = "\n".join( + f"slots[{i}].slot = {slot}; slots[{i}].pfunc = {value};" + for i, (slot, value) in enumerate(pairs) +) +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve all slot values, ordering, casts, and the zero sentinel" +) +print("_PyStructSequence_NewType C89 slots, values, ordering, casts, and sentinel: PASS") diff --git a/scripts/vc6-structseq-repr-c89.test.py b/scripts/vc6-structseq-repr-c89.test.py new file mode 100644 index 0000000..7310484 --- /dev/null +++ b/scripts/vc6-structseq-repr-c89.test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Check structseq_repr's loop declaration and unchanged iteration order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static PyObject \*\nstructseq_repr\(PyStructSequence \*obj\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "structseq_repr definition not found" +body = match.group(1) +assert not re.search(r"for\s*\(\s*Py_ssize_t\b", body), ( + "structseq_repr: VC6 rejects the C99 loop initializer declaration; " + "declare i in the function declaration block" +) +assert re.match( + r"\s*PyTypeObject \*typ = Py_TYPE\(obj\);" + r"\s*_PyUnicodeWriter writer;\s*Py_ssize_t i;", + body, +), "i must be declared without initialization in the function declaration block" +assert len(re.findall(r"\bPy_ssize_t\s+i\s*;", body)) == 1, ( + "declare i exactly once" +) +assert re.search( + r"if \(_PyUnicodeWriter_WriteChar\(&writer, '\('\) < 0\) " + r"\{\s*goto error;\s*\}\s*" + r"for \(i\s*=\s*0; i < VISIBLE_SIZE\(obj\); i\+\+\) \{", + body, +), "preserve zero initialization after '(' output, per-iteration size lookup, and increment" +assert len(re.findall(r"\bfor\s*\(", body)) == 1, "preserve the single item loop" +assert "typ->tp_members[i].name" in body, "preserve member-name indexing" +assert "PyStructSequence_GET_ITEM(obj, i)" in body, "preserve item indexing" +print("structseq_repr C89 loop declaration and iteration order: PASS") diff --git a/scripts/vc6-structseq-repr-name-c89.test.py b/scripts/vc6-structseq-repr-name-c89.test.py new file mode 100644 index 0000000..bf58141 --- /dev/null +++ b/scripts/vc6-structseq-repr-name-c89.test.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""Check structseq_repr's name declaration and decoding/refcount order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static PyObject \*\nstructseq_repr\(PyStructSequence \*obj\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "structseq_repr definition not found" +body = match.group(1) +assert re.search( + r"for \(i=0; i < VISIBLE_SIZE\(obj\); i\+\+\) \{" + r"\s*const char \*name_utf8;\s*PyObject \*name;\s*if \(i > 0\)", + body, +), "structseq_repr: VC6 requires name declared before loop-body statements" +assert len(re.findall(r"\bPyObject\s*\*name\b", body)) == 1, ( + "declare name exactly once without initialization" +) +expected = ''' + if (i > 0) { + /* Write ", " */ + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { + goto error; + } + } + + /* Write "name=repr" */ + name_utf8 = typ->tp_members[i].name; + if (name_utf8 == NULL) { + PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %zd name is NULL" + " for type %.500s", i, typ->tp_name); + goto error; + } + + name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL); + if (name == NULL) { + goto error; + } + if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { + Py_DECREF(name); + goto error; + } + Py_DECREF(name); + + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { + goto error; + } + + value = PyStructSequence_GET_ITEM(obj, i); +''' +assert re.sub(r"\s+", "", expected) in re.sub(r"\s+", "", body), ( + "preserve separator, member lookup, NULL check, decoding, write/decref, " + "error handling, and value lookup order" +) +assert len(re.findall(r"^\s*name\s*=(?!=)", body, re.M)) == 1, "assign name exactly once" +assert body.count("Py_DECREF(name)") == 2, "preserve both name decref paths" +print("structseq_repr name C89 declaration and decoding/refcount order: PASS") diff --git a/scripts/vc6-structseq-repr-name-utf8-c89.test.py b/scripts/vc6-structseq-repr-name-utf8-c89.test.py new file mode 100644 index 0000000..cc85dc2 --- /dev/null +++ b/scripts/vc6-structseq-repr-name-utf8-c89.test.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Check only structseq_repr's name_utf8 declaration and evaluation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static PyObject \*\nstructseq_repr\(PyStructSequence \*obj\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "structseq_repr definition not found" +body = match.group(1) +assert re.search( + r"for \(i=0; i < VISIBLE_SIZE\(obj\); i\+\+\) \{" + r"\s*const char \*name_utf8;\s*PyObject \*name;\s*if \(i > 0\)", + body, +), "structseq_repr: VC6 requires name_utf8 declared before loop-body statements" +assert len(re.findall(r"const char \*name_utf8\b", body)) == 1, ( + "declare name_utf8 exactly once" +) +assert re.search( + r'if \(i > 0\) \{\s*/\* Write ", " \*/\s*' + r'if \(_PyUnicodeWriter_WriteASCIIString\(&writer, ", ", 2\) < 0\) ' + r'\{\s*goto error;\s*\}\s*\}\s*' + r'/\* Write "name=repr" \*/\s*' + r'name_utf8 = typ->tp_members\[i\].name;\s*' + r'if \(name_utf8 == NULL\) \{\s*' + r'PyErr_Format\(PyExc_SystemError, "In structseq_repr\(\), member %zd name is NULL"' + r'\s*" for type %.500s", i, typ->tp_name\);\s*goto error;\s*\}\s*' + r'name = PyUnicode_DecodeUTF8\(name_utf8, strlen\(name_utf8\), NULL\);', + body, +), "preserve separator/error handling before member lookup, NULL check, and decoding" +assert len(re.findall(r"\bname_utf8\s*=", body)) == 2, ( + "preserve the single assignment and NULL comparison" +) +print("structseq_repr name_utf8 C89 declaration and evaluation order: PASS") diff --git a/scripts/vc6-structseq-repr-value-repr-c89.test.py b/scripts/vc6-structseq-repr-value-repr-c89.test.py new file mode 100644 index 0000000..dfe9867 --- /dev/null +++ b/scripts/vc6-structseq-repr-value-repr-c89.test.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +"""Check structseq_repr's value/repr declarations and ownership/order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static PyObject \*\nstructseq_repr\(PyStructSequence \*obj\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "structseq_repr definition not found" +body = match.group(1) +assert re.match( + r"\s*PyTypeObject \*typ = Py_TYPE\(obj\);" + r"\s*_PyUnicodeWriter writer;\s*Py_ssize_t i;" + r"\s*PyObject \*value;\s*PyObject \*repr;", + body, +), "structseq_repr: VC6 requires value and repr in the function entry declaration block" +for variable in ("value", "repr"): + assert len(re.findall(r"\bPyObject\s*\*" + variable + r"\b", body)) == 1, ( + "declare " + variable + " exactly once" + ) + assert len(re.findall(r"\b" + variable + r"\s*=(?!=)", body)) == 1, ( + "assign " + variable + " exactly once at its original evaluation point" + ) +expected = """ + Py_DECREF(name); + + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { + goto error; + } + + value = PyStructSequence_GET_ITEM(obj, i); + assert(value != NULL); + repr = PyObject_Repr(value); + if (repr == NULL) { + goto error; + } + if (_PyUnicodeWriter_WriteStr(&writer, repr) < 0) { + Py_DECREF(repr); + goto error; + } + Py_DECREF(repr); + } + + if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) { + goto error; + } + + return _PyUnicodeWriter_Finish(&writer); + +error: + _PyUnicodeWriter_Dealloc(&writer); + return NULL; +""" +assert re.sub(r"\s+", "", body).endswith(re.sub(r"\s+", "", expected)), ( + "preserve name cleanup, '=' output, borrowed value lookup, repr creation, " + "write/decref paths, and writer finish/error cleanup order" +) +assert len(re.findall(r"\bvalue\b", body)) == 4, "preserve borrowed value ownership" +assert len(re.findall(r"\brepr\b", re.sub(r"/\*.*?\*/", "", body, flags=re.S))) == 6, ( + "preserve repr ownership and both decref paths" +) +print("structseq_repr value/repr C89 declarations and ownership/order: PASS") diff --git a/scripts/vc6-structseq-traverse-c89.test.py b/scripts/vc6-structseq-traverse-c89.test.py new file mode 100644 index 0000000..3c39a8c --- /dev/null +++ b/scripts/vc6-structseq-traverse-c89.test.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Check structseq_traverse's C89 declarations and visit/size lookup order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c") +match = re.search( + r"static int\nstructseq_traverse\(PyStructSequence \*obj, visitproc visit, void \*arg\)" + r"\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "structseq_traverse definition not found" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t i, size;", body), ( + "structseq_traverse: i and size must be declared before the heap-type check; " + "declaration after statement is not C89 compatible" +) +expected = """ + Py_ssize_t i, size; + if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HEAPTYPE) { + Py_VISIT(Py_TYPE(obj)); + } + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_VISIT(obj->ob_item[i]); + } + return 0; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve heap-type visit and its early return before the single real-size " + "lookup, item visit order, loop initialization, and return behavior" +) +print("structseq_traverse C89 declarations and visit/size lookup order: PASS") diff --git a/scripts/vc6-tupleobject-alloc-c89.test.py b/scripts/vc6-tupleobject-alloc-c89.test.py new file mode 100644 index 0000000..8bcccd3 --- /dev/null +++ b/scripts/vc6-tupleobject-alloc-c89.test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Check tuple_alloc's C89 declaration and validation/allocation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"static PyTupleObject \*\ntuple_alloc\(Py_ssize_t size\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "tuple_alloc definition not found" +body = match.group(1) +assert re.match(r"\s*PyTupleObject \*op;", body), ( + "tuple_alloc: op must be declared without initializer before the size check; " + "declaration after statement is not C89 compatible" +) +expected = """ + PyTupleObject *op; + if (size < 0) { + PyErr_BadInternalCall(); + return NULL; + } +#ifdef Py_DEBUG + assert(size != 0); // The empty tuple is statically allocated. +#endif + + op = maybe_freelist_pop(size); + if (op == NULL) { + /* Check for overflow */ + if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) - + sizeof(PyObject *))) / sizeof(PyObject *)) { + return (PyTupleObject *)PyErr_NoMemory(); + } + op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size); + if (op == NULL) + return NULL; + } + return op; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve size validation, debug assertion, single freelist lookup, overflow " + "check, GC allocation, error/return order, and absence of refcount operations" +) +print("tuple_alloc C89 declaration and validation/allocation order: PASS") diff --git a/scripts/vc6-tupleobject-concat-b-c89.test.py b/scripts/vc6-tupleobject-concat-b-c89.test.py new file mode 100644 index 0000000..38678d8 --- /dev/null +++ b/scripts/vc6-tupleobject-concat-b-c89.test.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +"""Keep tupleconcat's b declaration C89-safe and assignment after validation.""" +import re +import sys +from pathlib import Path +source = Path(sys.argv[1] if len(sys.argv) > 1 else 'cpython/Objects/tupleobject.c') +match = re.search(r'tupleconcat\(PyTupleObject \*a, PyObject \*bb\)\n\{(.*?)\n\}', source.read_text(), re.S) +assert match, 'tupleconcat definition missing' +body = match.group(1) +assert re.match(r'\s*Py_ssize_t size;\s*Py_ssize_t i;\s*PyObject \*\*src, \*\*dest;\s*PyTupleObject \*np;\s*PyTupleObject \*b;\s*if', body), 'tupleconcat: b must be declared in the opening declaration group' +assert 'PyTupleObject *b =' not in body, 'tupleconcat: late initialized b declaration is not C89' +validation = re.search(r'if \(!PyTuple_Check\(bb\)\) \{.*?return NULL;\s*\}\s*b = \(PyTupleObject \*\)bb;\s*if \(Py_SIZE\(b\) == 0 && PyTuple_CheckExact\(a\)\)', body, re.S) +assert validation, 'tupleconcat: b assignment must follow type-check/error return and precede empty-b check' +assert body.index('return bb;') < validation.start(), 'tupleconcat: empty-a exact-b fast return must remain first' +assert body.count('b = (PyTupleObject *)bb;') == 1, 'tupleconcat: exactly one b assignment required' +assert body.index('b = (PyTupleObject *)bb;') < body.index('np = tuple_alloc(size);') < body.index('src = b->ob_item;') < body.index('_PyObject_GC_TRACK(np);'), 'tupleconcat: cast/allocation/copy/GC order changed' +print('tupleconcat b C89 declaration and validation/assignment order: PASS') diff --git a/scripts/vc6-tupleobject-dealloc-c89.test.py b/scripts/vc6-tupleobject-dealloc-c89.test.py new file mode 100644 index 0000000..178f1a9 --- /dev/null +++ b/scripts/vc6-tupleobject-dealloc-c89.test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Check tupledealloc's C89 declaration and exact teardown evaluation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"static void\ntupledealloc\(PyTupleObject \*op\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "tupledealloc definition not found" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t i;", body), ( + "tupledealloc: i must be declared without initializer before the empty " + "tuple check; declaration after Py_TRASHCAN_BEGIN is not C89 compatible" +) +expected = """ + Py_ssize_t i; + if (Py_SIZE(op) == 0) { + /* The empty tuple is statically allocated. */ + if (op == &_Py_SINGLETON(tuple_empty)) { +#ifdef Py_DEBUG + _Py_FatalRefcountError("deallocating the empty tuple singleton"); +#else + return; +#endif + } +#ifdef Py_DEBUG + /* tuple subclasses have their own empty instances. */ + assert(!PyTuple_CheckExact(op)); +#endif + } + + PyObject_GC_UnTrack(op); + Py_TRASHCAN_BEGIN(op, tupledealloc) + + i = Py_SIZE(op); + while (--i >= 0) { + Py_XDECREF(op->ob_item[i]); + } + // This will abort on the empty singleton (if there is one). + if (!maybe_freelist_push(op)) { + Py_TYPE(op)->tp_free((PyObject *)op); + } + + Py_TRASHCAN_END +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve empty-tuple guards, GC untracking, size assignment immediately " + "after trashcan entry, reverse item decrefs, freelist/free, and trashcan exit" +) +print("tupledealloc C89 declaration and exact teardown evaluation order: PASS") diff --git a/scripts/vc6-tupleobject-debug-malloc-stats-c89.test.py b/scripts/vc6-tupleobject-debug-malloc-stats-c89.test.py new file mode 100644 index 0000000..641a31d --- /dev/null +++ b/scripts/vc6-tupleobject-debug-malloc-stats-c89.test.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Check only _PyTuple_DebugMallocStats's C89 index and reporting loop.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"void\n_PyTuple_DebugMallocStats\(FILE \*out\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "_PyTuple_DebugMallocStats definition missing" +body = match.group(1) +assert re.match( + r"\s*#if PyTuple_NFREELISTS > 0\s*" + r"PyInterpreterState \*interp = _PyInterpreterState_GET\(\);\s*int i;", + body, +), "_PyTuple_DebugMallocStats: i must be declared before the loop for C89" +expected = """ +#if PyTuple_NFREELISTS > 0 + PyInterpreterState *interp = _PyInterpreterState_GET(); + int i; + for (i = 0; i < PyTuple_NFREELISTS; i++) { + int len = i + 1; + char buf[128]; + PyOS_snprintf(buf, sizeof(buf), + "free %d-sized PyTupleObject", len); + _PyDebugAllocatorStats(out, buf, STATE.numfree[i], + _PyObject_VAR_SIZE(&PyTuple_Type, len)); + } +#endif +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "_PyTuple_DebugMallocStats: preserve loop assignment, bounds, increment, " + "tuple length, buffer, label, freelist count, and allocation size" +) +print("_PyTuple_DebugMallocStats C89 index and reporting loop: PASS") diff --git a/scripts/vc6-tupleobject-freelist-push-index-c89.test.py b/scripts/vc6-tupleobject-freelist-push-index-c89.test.py new file mode 100644 index 0000000..b076357 --- /dev/null +++ b/scripts/vc6-tupleobject-freelist-push-index-c89.test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +"""Check only maybe_freelist_push's index declaration and evaluation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"static inline int\nmaybe_freelist_push\(PyTupleObject \*op\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "maybe_freelist_push definition missing" +body = match.group(1) +assert re.match( + r"\s*#if PyTuple_NFREELISTS > 0\s*" + r"PyInterpreterState \*interp = _PyInterpreterState_GET\(\);\s*" + r"Py_ssize_t index;\s*#ifdef Py_DEBUG", + body, +), "maybe_freelist_push: index must be declared before the debug assertion and empty-tuple check" +assert len(re.findall(r"\bPy_ssize_t\s+index\b", body)) == 1, ( + "maybe_freelist_push: exactly one index declaration required" +) +assert re.search( + r"if \(Py_SIZE\(op\) == 0\)\s*\{\s*return 0;\s*\}\s*" + r"index = Py_SIZE\(op\) - 1;\s*if \(index < PyTuple_NFREELISTS", + body, +), "maybe_freelist_push: assign index at its original evaluation point after the empty-tuple return" +assert len(re.findall(r"\bindex\s*=", body)) == 1, ( + "maybe_freelist_push: exactly one index assignment required" +) +print("maybe_freelist_push index C89 declaration and evaluation order: PASS") diff --git a/scripts/vc6-tupleobject-from-array-c89.test.py b/scripts/vc6-tupleobject-from-array-c89.test.py new file mode 100644 index 0000000..eefafa8 --- /dev/null +++ b/scripts/vc6-tupleobject-from-array-c89.test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Check _PyTuple_FromArray's C89 declarations and preserve its order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"PyObject \*\n_PyTuple_FromArray\(PyObject \*const \*src, Py_ssize_t n\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "_PyTuple_FromArray definition not found" +body = match.group(1) +assert re.match( + r"\s*PyTupleObject \*tuple;\s*PyObject \*\*dst;\s*Py_ssize_t i;" + r"\s*if \(n == 0\)", body +), ( + "_PyTuple_FromArray: tuple, dst and i must be declared without initializers " + "before the empty-tuple check; a loop declaration is not C89 compatible" +) +expected = """ + PyTupleObject *tuple; + PyObject **dst; + Py_ssize_t i; + if (n == 0) { + return tuple_get_empty(); + } + + tuple = tuple_alloc(n); + if (tuple == NULL) { + return NULL; + } + dst = tuple->ob_item; + for (i = 0; i < n; i++) { + PyObject *item = src[i]; + Py_INCREF(item); + dst[i] = item; + } + _PyObject_GC_TRACK(tuple); + return (PyObject *)tuple; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve early empty return before single allocation, NULL handling, " + "dst assignment immediately after NULL check, i initialization/condition/increment, " + "unchanged item declaration, " + "INCREF/store, GC tracking and return order" +) +print("_PyTuple_FromArray C89 declarations and evaluation/refcount/error order: PASS") diff --git a/scripts/vc6-tupleobject-from-array-steal-c89.test.py b/scripts/vc6-tupleobject-from-array-steal-c89.test.py new file mode 100644 index 0000000..c19a79a --- /dev/null +++ b/scripts/vc6-tupleobject-from-array-steal-c89.test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Check only _PyTuple_FromArraySteal's allocation-failure and success loop C89 fixes.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"PyObject \*\n_PyTuple_FromArraySteal\(PyObject \*const \*src, Py_ssize_t n\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "_PyTuple_FromArraySteal definition not found" +body = match.group(1) +assert re.match( + r"\s*PyTupleObject \*tuple;\s*Py_ssize_t i;\s*PyObject \*\*dst;\s*if \(n == 0\)", body +), "_PyTuple_FromArraySteal: function-scope Py_ssize_t i must precede statements" +assert "for (Py_ssize_t i =" not in body, ( + "_PyTuple_FromArraySteal: success loop must reuse function-scope i with assignment" +) +expected = """ + PyTupleObject *tuple; + Py_ssize_t i; + PyObject **dst; + if (n == 0) { + return tuple_get_empty(); + } + tuple = tuple_alloc(n); + if (tuple == NULL) { + for (i = 0; i < n; i++) { + Py_DECREF(src[i]); + } + return NULL; + } + dst = tuple->ob_item; + for (i = 0; i < n; i++) { + PyObject *item = src[i]; + dst[i] = item; + } + _PyObject_GC_TRACK(tuple); + return (PyObject *)tuple; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve empty return/allocation/NULL check, failure loop initialization, " + "condition, increment, DECREF and NULL return order; retain later " + "dst/item declarations and success-loop initialization/condition/increment/order" +) +print("_PyTuple_FromArraySteal failure/success C89 loops and evaluation/DECREF/return order: PASS") diff --git a/scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py b/scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py new file mode 100644 index 0000000..1a63629 --- /dev/null +++ b/scripts/vc6-tupleobject-from-array-steal-dst-c89.test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Check only _PyTuple_FromArraySteal's dst declaration and evaluation point.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"PyObject \*\n_PyTuple_FromArraySteal\(PyObject \*const \*src, Py_ssize_t n\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "_PyTuple_FromArraySteal definition not found" +body = match.group(1) +assert re.match( + r"\s*PyTupleObject \*tuple;\s*Py_ssize_t i;\s*PyObject \*\*dst;\s*if \(n == 0\)", + body, +), "_PyTuple_FromArraySteal: function-scope PyObject **dst must precede statements" +expected = """ + PyTupleObject *tuple; + Py_ssize_t i; + PyObject **dst; + if (n == 0) { + return tuple_get_empty(); + } + tuple = tuple_alloc(n); + if (tuple == NULL) { + for (i = 0; i < n; i++) { + Py_DECREF(src[i]); + } + return NULL; + } + dst = tuple->ob_item; + for (i = 0; i < n; i++) { + PyObject *item = src[i]; + dst[i] = item; + } + _PyObject_GC_TRACK(tuple); + return (PyObject *)tuple; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve dst assignment immediately after successful allocation and NULL " + "check, failure DECREFs/return, loop index and item declarations, stores, " + "GC tracking and return order" +) +print("_PyTuple_FromArraySteal dst declaration placement and evaluation/refcount/error order: PASS") diff --git a/scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py b/scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py new file mode 100644 index 0000000..92d458a --- /dev/null +++ b/scripts/vc6-tupleobject-from-array-steal-tuple-c89.test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Check only _PyTuple_FromArraySteal's tuple declaration placement and order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"PyObject \*\n_PyTuple_FromArraySteal\(PyObject \*const \*src, Py_ssize_t n\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "_PyTuple_FromArraySteal definition not found" +body = match.group(1) +assert re.match(r"\s*PyTupleObject \*tuple;\s*Py_ssize_t i;\s*PyObject \*\*dst;\s*if \(n == 0\)", body), ( + "_PyTuple_FromArraySteal: tuple must be declared without an initializer " + "before the empty-tuple check" +) +expected = """ + PyTupleObject *tuple; + Py_ssize_t i; + PyObject **dst; + if (n == 0) { + return tuple_get_empty(); + } + tuple = tuple_alloc(n); + if (tuple == NULL) { + for (i = 0; i < n; i++) { + Py_DECREF(src[i]); + } + return NULL; + } + dst = tuple->ob_item; + for (i = 0; i < n; i++) { + PyObject *item = src[i]; + dst[i] = item; + } + _PyObject_GC_TRACK(tuple); + return (PyObject *)tuple; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve empty return before single allocation, allocation failure DECREFs " + "and NULL return, unchanged dst/loop/item declarations, item stores, " + "GC tracking and return order" +) +print("_PyTuple_FromArraySteal tuple declaration placement and evaluation/refcount/error order: PASS") diff --git a/scripts/vc6-tupleobject-maybe-freelist-clear-c89.test.py b/scripts/vc6-tupleobject-maybe-freelist-clear-c89.test.py new file mode 100644 index 0000000..e366286 --- /dev/null +++ b/scripts/vc6-tupleobject-maybe-freelist-clear-c89.test.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Check only maybe_freelist_clear's C89 index and teardown order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"static void\nmaybe_freelist_clear\(PyInterpreterState \*interp, int fini\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "maybe_freelist_clear definition missing" +body = match.group(1) +assert re.match(r"\s*#if PyTuple_NFREELISTS > 0\s*Py_ssize_t i;", body), ( + "maybe_freelist_clear: i must be declared before the loop for C89" +) +expected = """ +#if PyTuple_NFREELISTS > 0 + Py_ssize_t i; + for (i = 0; i < PyTuple_NFREELISTS; i++) { + PyTupleObject *p = STATE.free_list[i]; + STATE.free_list[i] = NULL; + STATE.numfree[i] = fini ? -1 : 0; + while (p) { + PyTupleObject *q = p; + p = (PyTupleObject *)(p->ob_item[0]); + PyObject_GC_Del(q); + } + } +#endif +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "maybe_freelist_clear: preserve loop assignment, bounds, increment, " + "freelist reset, fini count, and linked-list deletion order" +) +print("maybe_freelist_clear C89 index and teardown order: PASS") diff --git a/scripts/vc6-tupleobject-new-c89.test.py b/scripts/vc6-tupleobject-new-c89.test.py new file mode 100644 index 0000000..d2bfc67 --- /dev/null +++ b/scripts/vc6-tupleobject-new-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Check PyTuple_New's C89 loop declaration and initialization order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"PyObject \*\nPyTuple_New\(Py_ssize_t size\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "PyTuple_New definition not found" +body = match.group(1) +assert re.match(r"\s*PyTupleObject \*op;\s*Py_ssize_t i;", body), ( + "PyTuple_New: i must be declared before the size check; " + "for-loop declarations are not C89 compatible" +) +expected = """ + PyTupleObject *op; + Py_ssize_t i; + if (size == 0) { + return tuple_get_empty(); + } + op = tuple_alloc(size); + if (op == NULL) { + return NULL; + } + for (i = 0; i < size; i++) { + op->ob_item[i] = NULL; + } + _PyObject_GC_TRACK(op); + return (PyObject *) op; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve empty-tuple return, single allocation and failure return, loop " + "initialization/condition/increment, item clearing, GC tracking, and return order" +) +print("PyTuple_New C89 loop declaration and initialization order: PASS") diff --git a/scripts/vc6-tupleobject-pack-c89.test.py b/scripts/vc6-tupleobject-pack-c89.test.py new file mode 100644 index 0000000..3829600 --- /dev/null +++ b/scripts/vc6-tupleobject-pack-c89.test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Check PyTuple_Pack's C89 declaration and evaluation/refcount/error order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"PyObject \*\nPyTuple_Pack\(Py_ssize_t n, \.\.\.\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "PyTuple_Pack definition not found" +body = match.group(1) +assert re.match( + r"\s*Py_ssize_t i;\s*PyObject \*o;\s*PyObject \*\*items;" + r"\s*va_list vargs;\s*PyTupleObject \*result;", body +), ( + "PyTuple_Pack: result must be declared without initializer before the empty " + "tuple check; declaration after statement is not C89 compatible" +) +expected = """ + Py_ssize_t i; + PyObject *o; + PyObject **items; + va_list vargs; + PyTupleObject *result; + + if (n == 0) { + return tuple_get_empty(); + } + + va_start(vargs, n); + result = tuple_alloc(n); + if (result == NULL) { + va_end(vargs); + return NULL; + } + items = result->ob_item; + for (i = 0; i < n; i++) { + o = va_arg(vargs, PyObject *); + Py_INCREF(o); + items[i] = o; + } + va_end(vargs); + _PyObject_GC_TRACK(result); + return (PyObject *)result; +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve empty-tuple return, va_start before single allocation, failure " + "va_end/NULL return, item extraction/INCREF/store, final va_end, GC tracking, " + "and return order" +) +print("PyTuple_Pack C89 declaration and evaluation/refcount/error order: PASS") diff --git a/scripts/vc6-tupleobject-repeat-dest-c89.test.py b/scripts/vc6-tupleobject-repeat-dest-c89.test.py new file mode 100644 index 0000000..41e87bc --- /dev/null +++ b/scripts/vc6-tupleobject-repeat-dest-c89.test.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Check only tuplerepeat's dest declaration and allocation-time assignment.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"tuplerepeat\(PyTupleObject \*a, Py_ssize_t n\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "tuplerepeat definition missing" +body = match.group(1) +assert re.match( + r"\s*Py_ssize_t size;\s*PyTupleObject \*np;\s*PyObject \*\*dest;" + r"\s*PyObject \*\*dest_end;\s*if", + body, +), "tuplerepeat: dest must be declared in the opening declaration block" +assert len(re.findall(r"PyObject\s*\*\*dest\b", body)) == 1, ( + "tuplerepeat: exactly one uninitialized dest declaration required" +) +assert re.search( + r"np = tuple_alloc\(size\);\s*if \(np == NULL\)\s*return NULL;" + r"\s*dest = np->ob_item;\s*dest_end = dest \+ size;", + body, +), "tuplerepeat: assign dest immediately after allocation/NULL check, before unchanged dest_end" +assert len(re.findall(r"\bdest\s*=", body)) == 1, ( + "tuplerepeat: exactly one dest assignment required" +) +print("tuplerepeat dest C89 declaration and allocation/assignment order: PASS") diff --git a/scripts/vc6-tupleobject-repeat-dest-end-c89.test.py b/scripts/vc6-tupleobject-repeat-dest-end-c89.test.py new file mode 100644 index 0000000..34ebfe4 --- /dev/null +++ b/scripts/vc6-tupleobject-repeat-dest-end-c89.test.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +"""Check only tuplerepeat's dest_end declaration and assignment order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"tuplerepeat\(PyTupleObject \*a, Py_ssize_t n\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "tuplerepeat definition missing" +body = match.group(1) +assert re.match( + r"\s*Py_ssize_t size;\s*PyTupleObject \*np;\s*PyObject \*\*dest;" + r"\s*PyObject \*\*dest_end;\s*if", + body, +), "tuplerepeat: dest_end must be declared in the opening declaration block" +assert len(re.findall(r"PyObject\s*\*\*dest_end\b", body)) == 1, ( + "tuplerepeat: exactly one uninitialized dest_end declaration required" +) +assert re.search( + r"dest = np->ob_item;\s*dest_end = dest \+ size;", + body, +), "tuplerepeat: assign dest_end immediately after dest at its original evaluation point" +assert len(re.findall(r"\bdest_end\s*=", body)) == 1, ( + "tuplerepeat: exactly one dest_end assignment required" +) +print("tuplerepeat dest_end C89 declaration and assignment order: PASS") diff --git a/scripts/vc6-tupleobject-type-vectorcall-c89.test.py b/scripts/vc6-tupleobject-type-vectorcall-c89.test.py new file mode 100644 index 0000000..751f2eb --- /dev/null +++ b/scripts/vc6-tupleobject-type-vectorcall-c89.test.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Compile the exact tuple type as C89 and verify every static slot.""" + +import re +import subprocess +import sys +import tempfile +from pathlib import Path + +source_path = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +source = source_path.read_text() +initializers = {} +for name in ("PyTuple_Type",): + match = re.search(r"PyTypeObject " + name + r" = \{.*?\n\};", source, re.S) + assert match, name + " initializer not found" + initializers[name] = match.group(0) +header = (source_path.parent.parent / "Include/cpython/object.h").read_text() +layout = re.search(r"struct _typeobject \{(.*?)\n\};", header, re.S) +assert layout, "PyTypeObject layout not found" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", layout.group(1), flags=re.S) +fields = re.findall(r"\b(tp_\w+)\b", body) +assert len(fields) == len(set(fields)) == 48, "review changed PyTypeObject layout" +expected = { + "tp_name": '"tuple"', + "tp_basicsize": "sizeof(PyTupleObject) - sizeof(PyObject *)", + "tp_itemsize": "sizeof(PyObject *)", + "tp_dealloc": "(destructor)tupledealloc", + "tp_repr": "(reprfunc)tuplerepr", + "tp_as_sequence": "&tuple_as_sequence", + "tp_as_mapping": "&tuple_as_mapping", + "tp_hash": "(hashfunc)tuplehash", + "tp_getattro": "PyObject_GenericGetAttr", + "tp_flags": "Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS | _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_SEQUENCE", + "tp_doc": "tuple_new__doc__", + "tp_traverse": "(traverseproc)tupletraverse", + "tp_richcompare": "tuplerichcompare", + "tp_iter": "tuple_iter", + "tp_methods": "tuple_methods", + "tp_new": "tuple_new", + "tp_free": "PyObject_GC_Del", + "tp_vectorcall": "tuple_vectorcall", +} +assert expected.keys() <= set(fields) +# Use the real field declarations/order, with minimal stand-ins for dependencies. +harness = r''' +#include +#include +#include +typedef long Py_ssize_t; +typedef struct { int unused; } PyObject; +typedef struct { int unused; } PyAsyncMethods; +typedef struct { int unused; } PyNumberMethods; +typedef struct { int unused; } PySequenceMethods; +typedef struct { int unused; } PyMappingMethods; +typedef struct { int unused; } PyBufferProcs; +typedef struct { int unused; } PyMethodDef; +typedef struct { int unused; } PyMemberDef; +typedef struct { int unused; } PyGetSetDef; +typedef struct _typeobject PyTypeObject; +typedef struct { long head; PyObject *ob_item[1]; } PyTupleObject; +#define PyObject_VAR_HEAD long ob_refcnt; PyTypeObject *ob_type; long ob_size; +#define PyVarObject_HEAD_INIT(type, size) 1, type, size, +#define Py_TPFLAGS_DEFAULT 1UL +#define Py_TPFLAGS_HAVE_GC 2UL +#define Py_TPFLAGS_BASETYPE 4UL +#define _Py_TPFLAGS_MATCH_SELF 8UL +#define Py_TPFLAGS_TUPLE_SUBCLASS 16UL +#define Py_TPFLAGS_SEQUENCE 32UL +''' +for name in ( + "destructor getattrfunc setattrfunc reprfunc hashfunc ternaryfunc " + "getattrofunc setattrofunc traverseproc inquiry richcmpfunc getiterfunc " + "iternextfunc descrgetfunc descrsetfunc initproc allocfunc newfunc " + "freefunc vectorcallfunc" +).split(): + harness += f"typedef void (*{name})(void);\n" +harness += "struct _typeobject {" + body + "};\n" +for name in ( + "tuple_new tupledealloc tuplerepr tuplehash PyObject_GenericGetAttr " + "tupletraverse tuplerichcompare tuple_iter PyObject_GC_Del tuple_vectorcall" +).split(): + harness += f"static void {name}(void) {{ }}\n" +harness += "static PyTypeObject PyType_Type;\n" +harness += "static PySequenceMethods tuple_as_sequence;\n" +harness += "static PyMappingMethods tuple_as_mapping;\n" +harness += "static PyMethodDef tuple_methods[1];\n" +harness += 'static const char tuple_new__doc__[] = "tuple documentation";\n' +harness += "\n".join(initializers.values()) + "\nint main(void)\n{\n" +for name in initializers: + values = expected + harness += f" assert({name}.ob_refcnt == 1);\n" + harness += f" assert({name}.ob_type == &PyType_Type);\n" + harness += f" assert({name}.ob_size == 0);\n" + for field in fields: + value = values.get(field, "0") + if field in ("tp_name", "tp_doc"): + harness += f" assert(strcmp({name}.{field}, {value}) == 0);\n" + else: + harness += f" assert({name}.{field} == ({value}));\n" +harness += " return 0;\n}\n" +with tempfile.TemporaryDirectory(prefix="vc6-tupleobject-type-vectorcall-") as directory: + path = Path(directory) + (path / "test.c").write_text(harness) + result = subprocess.run([ + "cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror", + str(path / "test.c"), "-o", str(path / "test"), + ]) + if result.returncode: + sys.exit(result.returncode) + subprocess.run([str(path / "test")], check=True) +print("PyTuple_Type C89 compile and all 48 semantic field mappings: PASS") diff --git a/scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py b/scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py new file mode 100644 index 0000000..c1b069a --- /dev/null +++ b/scripts/vc6-tupleobject-vectorcall-nargs-c89.test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Check tuple_vectorcall's C89 nargs declaration and evaluation order.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") +match = re.search( + r"static PyObject \*\ntuple_vectorcall\([^)]*\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "tuple_vectorcall definition not found" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t nargs;", body), ( + "tuple_vectorcall: nargs must be declared in the initial declaration block " + "before the keyword check for C89 compatibility" +) +expected = """ + Py_ssize_t nargs; + if (!_PyArg_NoKwnames("tuple", kwnames)) { + return NULL; + } + + nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("tuple", nargs, 0, 1)) { + return NULL; + } + + if (nargs) { + return tuple_new_impl(_PyType_CAST(type), args[0]); + } + else { + return tuple_get_empty(); + } +""" +assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( + "preserve keyword rejection before the single nargs evaluation, positional " + "validation, and nonempty/empty tuple return paths" +) +print("tuple_vectorcall C89 nargs declaration and evaluation order: PASS") diff --git a/scripts/vc6-typeobject-add-descriptors-dict-c89.test.py b/scripts/vc6-typeobject-add-descriptors-dict-c89.test.py new file mode 100644 index 0000000..e34556e --- /dev/null +++ b/scripts/vc6-typeobject-add-descriptors-dict-c89.test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +"""Check descriptor dictionary locals and evaluation after the NULL guard.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +failures = [] +for function, local_type, local, factory in ( + ("type_add_members", "PyMemberDef", "memb", "PyDescr_NewMember"), + ("type_add_getset", "PyGetSetDef", "gsp", "PyDescr_NewGetSet"), +): + match = re.search(r"\nstatic int\n" + function + r"\(PyTypeObject \*type\)\n\{(.*?)\n\}", source, re.S) + assert match, function + " definition missing" + body = match.group(1) + opening = rf"\s*{local_type} \*{local} = type->tp_\w+;\s*PyObject \*dict;\s*if" + if not re.match(opening, body): + failures.append(function + ": dict must be in opening C89 declarations") + continue + assert len(re.findall(r"\bPyObject\s*\*\s*dict\b", body)) == 1 + assert len(re.findall(r"\bdict\s*=(?!=)", body)) == 1 + guard = f"if ({local} == NULL) {{\n return 0;\n }}" + ordered = [guard, "dict = type->tp_dict;", f"for (; {local}->name != NULL; {local}++)", f"PyObject *descr = {factory}(type, {local});", "if (descr == NULL)", "return -1;", "if (PyDict_SetDefault(dict, PyDescr_NAME(descr), descr) == NULL)", "Py_DECREF(descr);", "return -1;", "Py_DECREF(descr);", "return 0;"] + cursor = 0 + for token in ordered: + position = body.find(token, cursor) + assert position >= 0, f"{function}: missing/reordered operation: {token}" + cursor = position + len(token) + print(function + ": C89 dictionary declaration, NULL guard and cleanup: PASS") +assert not failures, "; ".join(failures) diff --git a/scripts/vc6-typeobject-add-method-locals-c89.test.py b/scripts/vc6-typeobject-add-method-locals-c89.test.py new file mode 100644 index 0000000..62ea5e2 --- /dev/null +++ b/scripts/vc6-typeobject-add-method-locals-c89.test.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +"""Keep type_add_method locals C89-compatible without moving API calls.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search(r"\nstatic int\ntype_add_method\(PyTypeObject \*type, PyMethodDef \*meth\)\n\{(.*?)\n\}", source, re.S) +assert match, "type_add_method definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*descr;\s*PyObject \*name;\s*int err;\s*int isdescr = 1;\s*if", body), ( + "type_add_method: name and err must be in the opening C89 declaration block" +) +for declaration in (r"\bPyObject\s*\*\s*name\b", r"\bint\s+err\b"): + assert len(re.findall(declaration, body)) == 1, "declare each moved local exactly once" + +# Search in execution order: duplicate cleanup calls occur on error paths. +ordered = [ + "if (meth->ml_flags & METH_CLASS)", + "if (meth->ml_flags & METH_STATIC)", + "descr = PyDescr_NewClassMethod(type, meth);", + "else if (meth->ml_flags & METH_STATIC)", + "PyObject *cfunc = PyCFunction_NewEx(meth, (PyObject*)type, NULL);", + "descr = PyStaticMethod_New(cfunc);", + "isdescr = 0;", + "Py_DECREF(cfunc);", + "descr = PyDescr_NewMethod(type, meth);", + "if (descr == NULL)", + "if (isdescr)", + "name = PyDescr_NAME(descr);", + "name = PyUnicode_FromString(meth->ml_name);", + "if (name == NULL)", + "Py_DECREF(descr);", + "if (!(meth->ml_flags & METH_COEXIST))", + "err = PyDict_SetDefault(type->tp_dict, name, descr) == NULL;", + "err = PyDict_SetItem(type->tp_dict, name, descr) < 0;", + "if (!isdescr)", + "Py_DECREF(name);", + "Py_DECREF(descr);", + "if (err)", + "return -1;", + "return 0;", +] +cursor = 0 +for token in ordered: + position = body.find(token, cursor) + assert position >= 0, f"type_add_method: missing or reordered operation: {token}" + cursor = position + len(token) +assert len(re.findall(r"\bname\s*=(?!=)", body)) == 2, "retain both name assignment branches" +assert len(re.findall(r"\berr\s*=(?!=)", body)) == 2, "retain both dictionary insertion branches" +print("type_add_method C89 locals, branch ordering and reference cleanup: PASS") diff --git a/scripts/vc6-typeobject-assign-version-tag-index-c89.test.py b/scripts/vc6-typeobject-assign-version-tag-index-c89.test.py new file mode 100644 index 0000000..46ac6f0 --- /dev/null +++ b/scripts/vc6-typeobject-assign-version-tag-index-c89.test.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Check only assign_version_tag's C89 loop index and unchanged loop.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nassign_version_tag\(struct type_cache \*cache, PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "assign_version_tag definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;\s*if\b", body +), "assign_version_tag: Py_ssize_t i; must precede statements at function scope" +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, ( + "assign_version_tag: declare i exactly once" +) +loop = re.search(r"\bfor\s*\(.*?\n \}", body, re.S) +expected = """ + for (i = 0; i < n; i++) { + PyObject *b = PyTuple_GET_ITEM(bases, i); + if (!assign_version_tag(cache, _PyType_CAST(b))) + return 0; + } +""" +assert loop and loop.group().split() == expected.split(), ( + "assign_version_tag: preserve loop initializer, bounds, increment, and body" +) +print("assign_version_tag loop index C89 declaration and unchanged loop: PASS") diff --git a/scripts/vc6-typeobject-assign-version-tag-n-c89.test.py b/scripts/vc6-typeobject-assign-version-tag-n-c89.test.py new file mode 100644 index 0000000..07b8171 --- /dev/null +++ b/scripts/vc6-typeobject-assign-version-tag-n-c89.test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Check assign_version_tag's n declaration and preserve evaluation order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nassign_version_tag\(struct type_cache \*cache, PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "assign_version_tag definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;\s*if\b", body), ( + "assign_version_tag: Py_ssize_t n; must be in the opening declaration block" +) +assert len(re.findall(r"\bPy_ssize_t\s+n\b", body)) == 1, ( + "assign_version_tag: declare n exactly once" +) +expected = """ + PyObject *bases; + Py_ssize_t n; + Py_ssize_t i; + if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) { + return 1; + } + if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) { + return 0; + } + if (next_version_tag == 0) { + return 0; + } + type->tp_version_tag = next_version_tag++; + assert (type->tp_version_tag != 0); + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); + for (i = 0; i < n; i++) { + PyObject *b = PyTuple_GET_ITEM(bases, i); + if (!assign_version_tag(cache, _PyType_CAST(b))) + return 0; + } + type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; + return 1; +""" +assert body.split() == expected.split(), ( + "assign_version_tag: preserve n initialization timing, guards, and loop" +) +print("assign_version_tag n C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-best-base-base-i-c89.test.py b/scripts/vc6-typeobject-best-base-base-i-c89.test.py new file mode 100644 index 0000000..ec568e0 --- /dev/null +++ b/scripts/vc6-typeobject-best-base-base-i-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Check best_base's base_i declaration and post-validation cast timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyTypeObject \*\nbest_base\(PyObject \*bases\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "best_base definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +loop = body.split("for (i = 0; i < n; i++) {", 1)[1] +assert re.match( + r"\s*PyObject \*base_proto = PyTuple_GET_ITEM\(bases, i\);" + r"\s*PyTypeObject \*base_i;\s*if\b", + loop, +), "best_base: base_i must be in the loop's opening declaration block (C89)" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*base_i\b", body)) == 1, ( + "declare base_i exactly once" +) +assert len(re.findall(r"\bbase_i\s*=(?!=)", body)) == 1, ( + "assign base_i exactly once" +) +expected = """ + PyObject *base_proto = PyTuple_GET_ITEM(bases, i); + PyTypeObject *base_i; + if (!PyType_Check(base_proto)) { + PyErr_SetString( + PyExc_TypeError, + "bases must be types"); + return NULL; + } + base_i = (PyTypeObject *)base_proto; + + if (!_PyType_IsReady(base_i)) { + if (PyType_Ready(base_i) < 0) + return NULL; + } +""" +prefix = loop.split("if (!_PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE))", 1)[0] +assert prefix.split() == expected.split(), ( + "best_base: preserve item retrieval, successful type validation, cast " + "assignment, and first base_i use in their original order" +) +print("best_base base_i C89 declaration and post-validation cast timing: PASS") diff --git a/scripts/vc6-typeobject-cache-clear-index-c89.test.py b/scripts/vc6-typeobject-cache-clear-index-c89.test.py new file mode 100644 index 0000000..9a4fab9 --- /dev/null +++ b/scripts/vc6-typeobject-cache-clear-index-c89.test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Check type_cache_clear's C89 index declaration and unchanged loop body.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c") +match = re.search( + r"static void\ntype_cache_clear\(struct type_cache \*cache, PyObject \*value\)\n\{(.*?)\n\}", + source.read_text(), + re.S, +) +assert match, "type_cache_clear definition missing" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t i;", body), ( + "type_cache_clear: Py_ssize_t i; must be declared at function entry" +) +assert re.fullmatch( + r"\s*Py_ssize_t i;\s*" + r"for \(i = 0; i < \(1 << MCACHE_SIZE_EXP\); i\+\+\) \{\s*" + r"struct type_cache_entry \*entry = &cache->hashtable\[i\];\s*" + r"entry->version = 0;\s*" + r"Py_XSETREF\(entry->name, _Py_XNewRef\(value\)\);\s*" + r"entry->value = NULL;\s*\}\s*", + body, +), "type_cache_clear: preserve loop assignment, bound, increment, body and order" +print("type_cache_clear index C89 declaration and unchanged loop body: PASS") diff --git a/scripts/vc6-typeobject-custom-mro-c89.test.py b/scripts/vc6-typeobject-custom-mro-c89.test.py new file mode 100644 index 0000000..086fbec --- /dev/null +++ b/scripts/vc6-typeobject-custom-mro-c89.test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Check custom_mro's C89 declaration and lookup/decref evaluation order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +start = source.index("type_mro_modified(PyTypeObject *type, PyObject *bases) {") +end = source.index("\n}", start) +function = source[start:end] +start = function.index(" if (custom) {") +end = function.index("\n n = PyTuple_GET_SIZE(bases);", start) +block = function[start:end] +assert re.match( + r"if \(custom\) \{\s*PyObject \*mro_meth, \*type_mro_meth;\s*" + r"int custom_mro;\s*mro_meth =", + block.strip(), +), "custom_mro must be declared in the opening declaration block" +assert len(re.findall(r"\bint\s+custom_mro\b", function)) == 1, ( + "declare custom_mro exactly once" +) +expected = """ + if (custom) { + PyObject *mro_meth, *type_mro_meth; + int custom_mro; + mro_meth = lookup_maybe_method( + (PyObject *)type, &_Py_ID(mro), &unbound); + if (mro_meth == NULL) { + goto clear; + } + type_mro_meth = lookup_maybe_method( + (PyObject *)&PyType_Type, &_Py_ID(mro), &unbound); + if (type_mro_meth == NULL) { + Py_DECREF(mro_meth); + goto clear; + } + custom_mro = (mro_meth != type_mro_meth); + Py_DECREF(mro_meth); + Py_DECREF(type_mro_meth); + if (custom_mro) { + goto clear; + } + } +""" +assert block.split() == expected.split(), ( + "preserve both successful lookups before custom_mro assignment, " + "then decrefs and conditional, including lookup failure handling" +) +print("type_mro_modified custom_mro C89 declaration and evaluation order: PASS") diff --git a/scripts/vc6-typeobject-find-name-in-mro-c89.test.py b/scripts/vc6-typeobject-find-name-in-mro-c89.test.py new file mode 100644 index 0000000..eb30e50 --- /dev/null +++ b/scripts/vc6-typeobject-find-name-in-mro-c89.test.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +"""Keep find_name_in_mro mro/res C89-safe without changing lookup timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nfind_name_in_mro\(PyTypeObject \*type, PyObject \*name, int \*error\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "find_name_in_mro definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*Py_hash_t hash;\s*PyObject \*mro;\s*PyObject \*res;\s*Py_ssize_t n;\s*(?:Py_ssize_t i;\s*)?if", body), ( + "find_name_in_mro: mro and res must be declared at function entry (C89)" +) +assert not re.search(r"for\s*\(\s*Py_ssize_t\s+i\b", body), ( + "find_name_in_mro: i remains declared in the for initializer (C89)" +) +expected = """ + Py_hash_t hash; + PyObject *mro; + PyObject *res; + Py_ssize_t n; + Py_ssize_t i; + if (!PyUnicode_CheckExact(name) || + (hash = _PyASCIIObject_CAST(name)->hash) == -1) + { + hash = PyObject_Hash(name); + if (hash == -1) { + *error = -1; + return NULL; + } + } + + + mro = type->tp_mro; + if (mro == NULL) { + if ((type->tp_flags & Py_TPFLAGS_READYING) == 0) { + if (PyType_Ready(type) < 0) { + *error = -1; + return NULL; + } + mro = type->tp_mro; + } + if (mro == NULL) { + *error = 1; + return NULL; + } + } + + res = NULL; + + Py_INCREF(mro); + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *base = PyTuple_GET_ITEM(mro, i); + PyObject *dict = _PyType_CAST(base)->tp_dict; + assert(dict && PyDict_Check(dict)); + res = _PyDict_GetItem_KnownHash(dict, name, hash); + if (res != NULL) { + break; + } + if (PyErr_Occurred()) { + *error = -1; + goto done; + } + } + *error = 0; +done: + Py_DECREF(mro); + return res;""" +assert body.split() == expected.split(), ( + "find_name_in_mro: preserve hash/readiness checks, mro/res assignment timing, " + "reference handling, lookup, errors, and opening n/i declarations" +) +print("find_name_in_mro mro/res C89 declarations and same-point assignments: PASS") diff --git a/scripts/vc6-typeobject-find-name-in-mro-n-c89.test.py b/scripts/vc6-typeobject-find-name-in-mro-n-c89.test.py new file mode 100644 index 0000000..60df42c --- /dev/null +++ b/scripts/vc6-typeobject-find-name-in-mro-n-c89.test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Check only find_name_in_mro's n declaration and initialization timing.""" +import re +from pathlib import Path + +source = (Path(__file__).resolve().parents[1] / "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nfind_name_in_mro\(PyTypeObject \*type, PyObject \*name, int \*error\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "find_name_in_mro definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_hash_t hash;\s*PyObject \*mro;\s*PyObject \*res;" + r"\s*Py_ssize_t n;\s*Py_ssize_t i;\s*if\b", body, +), "find_name_in_mro: Py_ssize_t n; must be in the opening declaration block" +assert len(re.findall(r"\bPy_ssize_t\s+n\b", body)) == 1, ( + "find_name_in_mro: declare n exactly once" +) +assert len(re.findall(r"\bn\s*=", body)) == 1, ( + "find_name_in_mro: initialize n exactly once" +) +assert re.search( + r"\bres = NULL;\s*Py_INCREF\(mro\);\s*n = PyTuple_GET_SIZE\(mro\);" + r"\s*for \(i = 0; i < n; i\+\+\) \{", body, +), "find_name_in_mro: preserve n assignment after INCREF and the separate i loop" +print("find_name_in_mro n C89 declaration and same-point assignment: PASS") diff --git a/scripts/vc6-typeobject-from-module-and-spec-doc-c89.test.py b/scripts/vc6-typeobject-from-module-and-spec-doc-c89.test.py new file mode 100644 index 0000000..000d9d0 --- /dev/null +++ b/scripts/vc6-typeobject-from-module-and-spec-doc-c89.test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Keep type-spec doc locals C89-safe without moving their evaluations.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_FromModuleAndSpec\(PyObject \*module, PyType_Spec \*spec, PyObject \*bases\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_FromModuleAndSpec definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +match = re.search( + r"else if \(slot->slot == Py_tp_doc\) \{(.*?)\n \}" + r"\s*else if \(slot->slot == Py_tp_members\)", body, re.S, +) +assert match, "Py_tp_doc branch missing" +branch = match.group(1) +assert re.match(r"\s*size_t len;\s*char \*tp_doc;\s*if", branch), ( + "len and tp_doc must be declared at the start of the Py_tp_doc block (C89)" +) +expected = """ + size_t len; + char *tp_doc; + if (slot->pfunc == NULL) { + type->tp_doc = NULL; + continue; + } + len = strlen(slot->pfunc)+1; + tp_doc = PyObject_Malloc(len); + if (tp_doc == NULL) { + type->tp_doc = NULL; + PyErr_NoMemory(); + goto fail; + } + memcpy(tp_doc, slot->pfunc, len); + type->tp_doc = tp_doc; +""" +assert branch.split() == expected.split(), ( + "preserve NULL guard, length/allocation evaluation order, failure handling, and copy" +) +print("PyType_FromModuleAndSpec doc locals C89 declarations and evaluation order: PASS") diff --git a/scripts/vc6-typeobject-from-module-and-spec-memb-c89.test.py b/scripts/vc6-typeobject-from-module-and-spec-memb-c89.test.py new file mode 100644 index 0000000..35febc0 --- /dev/null +++ b/scripts/vc6-typeobject-from-module-and-spec-memb-c89.test.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Keep the type-spec member loop C89-safe without moving its initialization.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_FromModuleAndSpec\(PyObject \*module, PyType_Spec \*spec, PyObject \*bases\)\n" + r"\{(.*?)\n\}", + source, + re.S, +) +assert match, "PyType_FromModuleAndSpec definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.search( + r"if \(slot->slot == Py_tp_members\)\s*\{" + r"\s*const PyMemberDef \*memb;\s*nmembers = 0;" + r"\s*for \(memb = slot->pfunc; memb->name != NULL; memb\+\+\)\s*\{", + body, +), "memb must be declared at block start (C89), with initialization still in the loop header" +assert len(re.findall(r"\bconst PyMemberDef\s*\*memb\b", body)) == 1, ( + "declare memb exactly once" +) +scan = body[body.index(" nmembers = weaklistoffset"):body.index(" res = (PyHeapTypeObject*)")] +expected = """ + nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0; + for (slot = spec->slots; slot->slot; slot++) { + if (slot->slot == Py_tp_members) { + const PyMemberDef *memb; + nmembers = 0; + for (memb = slot->pfunc; memb->name != NULL; memb++) { + nmembers++; + if (strcmp(memb->name, "__weaklistoffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + weaklistoffset = memb->offset; + } + if (strcmp(memb->name, "__dictoffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + dictoffset = memb->offset; + } + if (strcmp(memb->name, "__vectorcalloffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + vectorcalloffset = memb->offset; + } + } + } + } +""" +assert scan.split() == expected.split(), ( + "preserve member scan guards, evaluation order, bounds, increments, and offset handling" +) +print("PyType_FromModuleAndSpec memb C89 declaration and same-point initialization: PASS") diff --git a/scripts/vc6-typeobject-from-module-and-spec-name-buf-len-c89.test.py b/scripts/vc6-typeobject-from-module-and-spec-name-buf-len-c89.test.py new file mode 100644 index 0000000..c577e4a --- /dev/null +++ b/scripts/vc6-typeobject-from-module-and-spec-name-buf-len-c89.test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Keep the type-spec name buffer length C89-safe at its evaluation point.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_FromModuleAndSpec\(PyObject \*module, PyType_Spec \*spec, PyObject \*bases\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_FromModuleAndSpec definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +opening = body[:body.index(" nmembers = weaklistoffset")] +assert re.search(r"\bPy_ssize_t name_buf_len;", opening), ( + "name_buf_len must be declared in the opening declaration block (C89), before statements" +) +assert len(re.findall(r"\bPy_ssize_t\s+name_buf_len\b", body)) == 1, ( + "declare name_buf_len exactly once" +) +assert len(re.findall(r"\bname_buf_len\s*=", body)) == 1, ( + "assign name_buf_len exactly once" +) +expected = """ + res->ht_name = PyUnicode_FromString(s); + if (!res->ht_name) { + goto fail; + } + res->ht_qualname = Py_NewRef(res->ht_name); + name_buf_len = strlen(spec->name) + 1; + res->_ht_tpname = PyMem_Malloc(name_buf_len); + if (res->_ht_tpname == NULL) { + goto fail; + } + type->tp_name = memcpy(res->_ht_tpname, spec->name, name_buf_len); + res->ht_module = Py_XNewRef(module); +""" +actual = body[body.index(" res->ht_name = PyUnicode_FromString(s);"): + body.index(" if (!bases)")] +assert actual.split() == expected.split(), ( + "preserve name creation, length evaluation timing, allocation, failure handling, and copy" +) +print("PyType_FromModuleAndSpec name_buf_len C89 declaration and same-point initialization: PASS") diff --git a/scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py b/scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py new file mode 100644 index 0000000..4730b36 --- /dev/null +++ b/scripts/vc6-typeobject-from-module-and-spec-s-c89.test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Keep the type-spec name pointer C89-safe and initialize it after flags.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_FromModuleAndSpec\(PyObject \*module, PyType_Spec \*spec, PyObject \*bases\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_FromModuleAndSpec definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +opening = body[:body.index(" nmembers = weaklistoffset")] +assert re.search(r"\bconst char \*s;", opening), ( + "s must be declared in the opening declaration block (C89), before statements" +) +assert len(re.findall(r"\bconst char\s*\*s\b", body)) == 1, "declare s exactly once" +name_setup = body[body.index(" type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE;"):] +name_setup = name_setup[:name_setup.index(" res->ht_name = PyUnicode_FromString(s);")] +assert len(re.findall(r"strrchr\(spec->name, '\.'\)", name_setup)) == 1, ( + "evaluate name search exactly once in name setup" +) +expected = """ + if (spec->name == NULL) { + PyErr_SetString(PyExc_SystemError, + "Type spec does not define the name field."); + goto fail; + } + type = &res->ht_type; + type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; + s = strrchr(spec->name, '.'); + if (s == NULL) { + s = spec->name; + } + else { + s++; + } + res->ht_name = PyUnicode_FromString(s); +""" +actual = body[body.index(" if (spec->name == NULL)"): + body.index(" if (!res->ht_name)")] +assert actual.split() == expected.split(), ( + "preserve name validation, flags, search initialization timing, and name selection" +) +print("PyType_FromModuleAndSpec s C89 declaration and same-point initialization: PASS") diff --git a/scripts/vc6-typeobject-get-annotations-c89.test.py b/scripts/vc6-typeobject-get-annotations-c89.test.py new file mode 100644 index 0000000..2f7db02 --- /dev/null +++ b/scripts/vc6-typeobject-get-annotations-c89.test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Check type_get_annotations's C89 local and preserve every executable statement.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\ntype_get_annotations\(PyTypeObject \*type, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_get_annotations definition missing" +body = match.group(1) +assert re.match(r"\s*PyObject \*annotations;\s*if\b", body), ( + "type_get_annotations: annotations must be declared before the heap-type guard" +) +assert len(re.findall(r"\bPyObject\s*\*\s*annotations\b", body)) == 1, ( + "type_get_annotations: declare annotations exactly once" +) +expected = """ + PyObject *annotations; + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '__annotations__'", type->tp_name); + return NULL; + } + + annotations = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__annotations__)); + if (annotations) { + if (Py_TYPE(annotations)->tp_descr_get) { + annotations = Py_TYPE(annotations)->tp_descr_get( + annotations, NULL, (PyObject *)type); + } else { + Py_INCREF(annotations); + } + } + else if (!PyErr_Occurred()) { + annotations = PyDict_New(); + if (annotations) { + int result = PyDict_SetItem( + type->tp_dict, &_Py_ID(__annotations__), annotations); + if (result) { + Py_CLEAR(annotations); + } else { + PyType_Modified(type); + } + } + } + return annotations; +""" +assert body.split() == expected.split(), ( + "type_get_annotations: preserve guard, lookup, descriptor handling, references, " + "dictionary creation, error handling, invalidation, and return in their original order" +) +print("type_get_annotations annotations C89 declaration and unchanged executable body: PASS") diff --git a/scripts/vc6-typeobject-get-module-by-def-ht-module-c89.test.py b/scripts/vc6-typeobject-get-module-by-def-ht-module-c89.test.py new file mode 100644 index 0000000..4048191 --- /dev/null +++ b/scripts/vc6-typeobject-get-module-by-def-ht-module-c89.test.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +"""Keep heap-type/module locals at entry and their reads after the static-type skip.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_GetModuleByDef\(PyTypeObject \*type, PyModuleDef \*def\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_GetModuleByDef definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*mro;\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyHeapTypeObject \*ht;\s*PyObject \*module;\s*assert\(", body), ( + "PyType_GetModuleByDef: ht and module must be declared in the opening declaration block (C89)" +) +for declaration in (r"\bPyHeapTypeObject\s*\*ht\b", r"\bPyObject\s*\*module\b"): + assert len(re.findall(declaration, body)) == 1, ( + "PyType_GetModuleByDef: declare ht and module exactly once" + ) +expected = """ + PyObject *mro; + Py_ssize_t n; + Py_ssize_t i; + PyHeapTypeObject *ht; + PyObject *module; + assert(PyType_Check(type)); + + mro = type->tp_mro; + assert(mro != NULL); + assert(PyTuple_Check(mro)); + assert(PyTuple_GET_SIZE(mro) >= 1); + + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *super = PyTuple_GET_ITEM(mro, i); + if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) { + continue; + } + + ht = (PyHeapTypeObject*)super; + module = ht->ht_module; + if (module && _PyModule_GetDef(module) == def) { + return module; + } + } + + PyErr_Format( + PyExc_TypeError, + "PyType_GetModuleByDef: No superclass of '%s' has the given module", + type->tp_name); + return NULL; +""" +assert body.split() == expected.split(), ( + "PyType_GetModuleByDef: preserve ht/module assignments after the static-type skip and before module lookup, " + "loop, module lookup, and error handling" +) +print("PyType_GetModuleByDef ht/module C89 declarations and same-point assignments: PASS") diff --git a/scripts/vc6-typeobject-get-module-by-def-index-c89.test.py b/scripts/vc6-typeobject-get-module-by-def-index-c89.test.py new file mode 100644 index 0000000..052c8e8 --- /dev/null +++ b/scripts/vc6-typeobject-get-module-by-def-index-c89.test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Keep PyType_GetModuleByDef's loop index in opening C89 locals.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_GetModuleByDef\(PyTypeObject \*type, PyModuleDef \*def\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_GetModuleByDef definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*mro;\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyHeapTypeObject \*ht;\s*PyObject \*module;\s*assert\(", body), ( + "PyType_GetModuleByDef: i must be declared in the opening declaration block (C89)" +) +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, ( + "PyType_GetModuleByDef: declare i exactly once" +) +expected = """ + PyObject *mro; + Py_ssize_t n; + Py_ssize_t i; + PyHeapTypeObject *ht; + PyObject *module; + assert(PyType_Check(type)); + + mro = type->tp_mro; + assert(mro != NULL); + assert(PyTuple_Check(mro)); + assert(PyTuple_GET_SIZE(mro) >= 1); + + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *super = PyTuple_GET_ITEM(mro, i); + if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) { + continue; + } + + ht = (PyHeapTypeObject*)super; + module = ht->ht_module; + if (module && _PyModule_GetDef(module) == def) { + return module; + } + } + + PyErr_Format( + PyExc_TypeError, + "PyType_GetModuleByDef: No superclass of '%s' has the given module", + type->tp_name); + return NULL; +""" +assert body.split() == expected.split(), ( + "PyType_GetModuleByDef: preserve loop initialization, bound, increment, body, and surrounding " + "loop, module lookup, and error handling" +) +print("PyType_GetModuleByDef C89 loop index and preserved loop semantics: PASS") diff --git a/scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py b/scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py new file mode 100644 index 0000000..0f4d78c --- /dev/null +++ b/scripts/vc6-typeobject-get-module-by-def-mro-c89.test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Keep PyType_GetModuleByDef's mro declaration C89-safe and read in place.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_GetModuleByDef\(PyTypeObject \*type, PyModuleDef \*def\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_GetModuleByDef definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*mro;\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyHeapTypeObject \*ht;\s*PyObject \*module;\s*assert\(", body), ( + "PyType_GetModuleByDef: mro must be declared at function entry (C89)" +) +expected = """ + PyObject *mro; + Py_ssize_t n; + Py_ssize_t i; + PyHeapTypeObject *ht; + PyObject *module; + assert(PyType_Check(type)); + + mro = type->tp_mro; + assert(mro != NULL); + assert(PyTuple_Check(mro)); + assert(PyTuple_GET_SIZE(mro) >= 1); + + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *super = PyTuple_GET_ITEM(mro, i); + if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) { + continue; + } + + ht = (PyHeapTypeObject*)super; + module = ht->ht_module; + if (module && _PyModule_GetDef(module) == def) { + return module; + } + } + + PyErr_Format( + PyExc_TypeError, + "PyType_GetModuleByDef: No superclass of '%s' has the given module", + type->tp_name); + return NULL; +""" +assert body.split() == expected.split(), ( + "PyType_GetModuleByDef: preserve mro read timing, checks, later declarations, " + "loop, module lookup, and error handling" +) +print("PyType_GetModuleByDef mro C89 declaration and same-point read: PASS") diff --git a/scripts/vc6-typeobject-get-module-by-def-n-c89.test.py b/scripts/vc6-typeobject-get-module-by-def-n-c89.test.py new file mode 100644 index 0000000..4782cbc --- /dev/null +++ b/scripts/vc6-typeobject-get-module-by-def-n-c89.test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Keep PyType_GetModuleByDef's n declaration C89-safe and evaluated in place.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_GetModuleByDef\(PyTypeObject \*type, PyModuleDef \*def\)\n" + r"\{(.*?)\n\}", source, re.S, +) +assert match, "PyType_GetModuleByDef definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*mro;\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyHeapTypeObject \*ht;\s*PyObject \*module;\s*assert\(", body), ( + "PyType_GetModuleByDef: n must be declared in the opening declaration block (C89)" +) +assert len(re.findall(r"\bPy_ssize_t\s+n\b", body)) == 1, ( + "PyType_GetModuleByDef: declare n exactly once" +) +expected = """ + PyObject *mro; + Py_ssize_t n; + Py_ssize_t i; + PyHeapTypeObject *ht; + PyObject *module; + assert(PyType_Check(type)); + + mro = type->tp_mro; + assert(mro != NULL); + assert(PyTuple_Check(mro)); + assert(PyTuple_GET_SIZE(mro) >= 1); + + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *super = PyTuple_GET_ITEM(mro, i); + if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) { + continue; + } + + ht = (PyHeapTypeObject*)super; + module = ht->ht_module; + if (module && _PyModule_GetDef(module) == def) { + return module; + } + } + + PyErr_Format( + PyExc_TypeError, + "PyType_GetModuleByDef: No superclass of '%s' has the given module", + type->tp_name); + return NULL; +""" +assert body.split() == expected.split(), ( + "PyType_GetModuleByDef: preserve n evaluation timing and mro read timing, checks, later declarations, " + "loop, module lookup, and error handling" +) +print("PyType_GetModuleByDef n C89 declaration and same-point evaluation: PASS") diff --git a/scripts/vc6-typeobject-get-module-et-c89.test.py b/scripts/vc6-typeobject-get-module-et-c89.test.py new file mode 100644 index 0000000..4418f92 --- /dev/null +++ b/scripts/vc6-typeobject-get-module-et-c89.test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Keep PyType_GetModule's heap-type declaration C89-safe and cast in place.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject \*\nPyType_GetModule\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "PyType_GetModule definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyHeapTypeObject \*et;\s*assert\(", body), ( + "PyType_GetModule: et must be declared at function entry (C89)" +) +expected = """ + PyHeapTypeObject *et; + assert(PyType_Check(type)); + if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { + PyErr_Format( + PyExc_TypeError, + "PyType_GetModule: Type '%s' is not a heap type", + type->tp_name); + return NULL; + } + + et = (PyHeapTypeObject*)type; + if (!et->ht_module) { + PyErr_Format( + PyExc_TypeError, + "PyType_GetModule: Type '%s' has no associated module", + type->tp_name); + return NULL; + } + return et->ht_module; +""" +assert body.split() == expected.split(), ( + "PyType_GetModule: preserve validation, cast timing, module check, and return" +) +print("PyType_GetModule et C89 declaration and same-point cast: PASS") diff --git a/scripts/vc6-typeobject-get-subclasses-index-c89.test.py b/scripts/vc6-typeobject-get-subclasses-index-c89.test.py new file mode 100644 index 0000000..b8ffa97 --- /dev/null +++ b/scripts/vc6-typeobject-get-subclasses-index-c89.test.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Keep _PyType_GetSubclasses's index in opening C89 locals.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject\*\n_PyType_GetSubclasses\(PyTypeObject \*self\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "_PyType_GetSubclasses definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*subclasses;\s*Py_ssize_t i;\s*" + r"PyObject \*list = PyList_New\(0\);", + body, +), "_PyType_GetSubclasses: i must be declared in the opening declaration block (C89)" +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, ( + "_PyType_GetSubclasses: declare i exactly once" +) +expected = """ + PyObject *subclasses; + Py_ssize_t i; + PyObject *list = PyList_New(0); + PyObject *ref; + PyObject *obj; + if (list == NULL) { + return NULL; + } + + subclasses = self->tp_subclasses; + if (subclasses == NULL) { + return list; + } + assert(PyDict_CheckExact(subclasses)); + + + + i = 0; + while (PyDict_Next(subclasses, &i, NULL, &ref)) { + assert(PyWeakref_CheckRef(ref)); + obj = PyWeakref_GET_OBJECT(ref); + if (obj == Py_None) { + continue; + } + assert(PyType_Check(obj)); + + if (PyList_Append(list, obj) < 0) { + Py_DECREF(list); + return NULL; + } + } + return list; +""" +assert body.split() == expected.split(), ( + "_PyType_GetSubclasses: preserve index initialization timing, guards, loop, " + "and ref/obj uses" +) +print("_PyType_GetSubclasses C89 index declaration and preserved initialization timing: PASS") diff --git a/scripts/vc6-typeobject-get-subclasses-obj-c89.test.py b/scripts/vc6-typeobject-get-subclasses-obj-c89.test.py new file mode 100644 index 0000000..df08056 --- /dev/null +++ b/scripts/vc6-typeobject-get-subclasses-obj-c89.test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Keep _PyType_GetSubclasses's obj in opening C89 locals.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject\*\n_PyType_GetSubclasses\(PyTypeObject \*self\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "_PyType_GetSubclasses definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*subclasses;\s*Py_ssize_t i;\s*" + r"PyObject \*list = PyList_New\(0\);\s*PyObject \*ref;\s*" + r"PyObject \*obj;", + body, +), "_PyType_GetSubclasses: obj must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyObject\s*\*\s*obj\b", body)) == 1, ( + "_PyType_GetSubclasses: declare obj exactly once without initialization" +) +assert body.count("PyWeakref_GET_OBJECT(ref)") == 1, ( + "_PyType_GetSubclasses: preserve the single weakref object read" +) +assert re.search( + r"while \(PyDict_Next\(subclasses, &i, NULL, &ref\)\) \{\s*" + r"assert\(PyWeakref_CheckRef\(ref\)\);\s*" + r"obj = PyWeakref_GET_OBJECT\(ref\);\s*" + r"if \(obj == Py_None\) \{\s*continue;\s*\}\s*" + r"assert\(PyType_Check\(obj\)\);\s*" + r"if \(PyList_Append\(list, obj\) < 0\) \{\s*" + r"Py_DECREF\(list\);\s*return NULL;\s*\}\s*\}\s*return list;\s*$", + body, +), "_PyType_GetSubclasses: preserve obj assignment timing and loop control flow" +print("_PyType_GetSubclasses obj C89 declaration and preserved assignment timing: PASS") diff --git a/scripts/vc6-typeobject-get-subclasses-ref-c89.test.py b/scripts/vc6-typeobject-get-subclasses-ref-c89.test.py new file mode 100644 index 0000000..9cc76b0 --- /dev/null +++ b/scripts/vc6-typeobject-get-subclasses-ref-c89.test.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Keep _PyType_GetSubclasses's ref in opening C89 locals.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject\*\n_PyType_GetSubclasses\(PyTypeObject \*self\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "_PyType_GetSubclasses definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*subclasses;\s*Py_ssize_t i;\s*" + r"PyObject \*list = PyList_New\(0\);\s*PyObject \*ref;", + body, +), "_PyType_GetSubclasses: ref must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyObject\s*\*\s*ref\b", body)) == 1, ( + "_PyType_GetSubclasses: declare ref exactly once without initialization" +) +expected = """ + PyObject *subclasses; + Py_ssize_t i; + PyObject *list = PyList_New(0); + PyObject *ref; + PyObject *obj; + if (list == NULL) { + return NULL; + } + subclasses = self->tp_subclasses; + if (subclasses == NULL) { + return list; + } + assert(PyDict_CheckExact(subclasses)); + i = 0; + while (PyDict_Next(subclasses, &i, NULL, &ref)) { + assert(PyWeakref_CheckRef(ref)); + obj = PyWeakref_GET_OBJECT(ref); + if (obj == Py_None) { + continue; + } + assert(PyType_Check(obj)); + if (PyList_Append(list, obj) < 0) { + Py_DECREF(list); + return NULL; + } + } + return list; +""" +assert body.split() == expected.split(), ( + "_PyType_GetSubclasses: preserve guards, iteration, ref uses, " + "and obj assignment timing" +) +print("_PyType_GetSubclasses ref C89 declaration and unchanged use order: PASS") diff --git a/scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py b/scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py new file mode 100644 index 0000000..b2f1c7e --- /dev/null +++ b/scripts/vc6-typeobject-get-subclasses-subclasses-c89.test.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Keep _PyType_GetSubclasses's subclasses declaration C89-safe.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nPyObject\*\n_PyType_GetSubclasses\(PyTypeObject \*self\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "_PyType_GetSubclasses definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*subclasses;", body), ( + "_PyType_GetSubclasses: subclasses must be declared at function entry (C89)" +) +assert len(re.findall(r"\bPyObject\s*\*\s*subclasses\b", body)) == 1, ( + "_PyType_GetSubclasses: declare subclasses exactly once" +) +assert re.match( + r"\s*PyObject \*subclasses;\s*" + r"(?:Py_ssize_t i;\s*)?" + r"PyObject \*list = PyList_New\(0\);\s*" + r"PyObject \*ref;\s*" + r"PyObject \*obj;\s*" + r"if \(list == NULL\) \{\s*return NULL;\s*\}\s*" + r"subclasses = self->tp_subclasses;\s*" + r"if \(subclasses == NULL\) \{\s*return list;\s*\}\s*" + r"assert\(PyDict_CheckExact\(subclasses\)\);", + body, +), "_PyType_GetSubclasses: preserve allocation, guard, and tp_subclasses read timing" +assert body.count("self->tp_subclasses") == 1, ( + "_PyType_GetSubclasses: preserve the single tp_subclasses read" +) +print("_PyType_GetSubclasses subclasses C89 declaration and read timing: PASS") diff --git a/scripts/vc6-typeobject-lookup-cache-entry-c89.test.py b/scripts/vc6-typeobject-lookup-cache-entry-c89.test.py new file mode 100644 index 0000000..7331f84 --- /dev/null +++ b/scripts/vc6-typeobject-lookup-cache-entry-c89.test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +"""Check only _PyType_Lookup's cache-update entry declaration and timing.""" +import re +from pathlib import Path + +source = (Path(__file__).resolve().parents[1] / "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\n_PyType_Lookup\(PyTypeObject \*type, PyObject \*name\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "_PyType_Lookup definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +guard = "if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(cache, type)) {" +assert body.count(guard) == 1, "cache-update block must be unique" +update = body.split(guard, 1)[1] +assert re.match(r"\s*struct type_cache_entry \*entry;\s*h =", update), ( + "_PyType_Lookup cache update: entry must precede statements (C89)" +) +assert len(re.findall(r"\bstruct type_cache_entry\s*\*entry\b", update)) == 1, ( + "cache update: declare entry exactly once" +) +assert len(re.findall(r"\bentry\s*=", update)) == 1, ( + "cache update: initialize entry exactly once" +) +assert re.match( + r"\s*struct type_cache_entry \*entry;" + r"\s*h = MCACHE_HASH_METHOD\(type, name\);" + r"\s*entry = &cache->hashtable\[h\];" + r"\s*entry->version = type->tp_version_tag;" + r"\s*entry->value = res;", update, +), "cache update: preserve entry assignment between hash recalculation and writes" +print("_PyType_Lookup cache-update entry C89 declaration and same-point assignment: PASS") diff --git a/scripts/vc6-typeobject-lookup-maybe-method-c89.test.py b/scripts/vc6-typeobject-lookup-maybe-method-c89.test.py new file mode 100644 index 0000000..8c80da7 --- /dev/null +++ b/scripts/vc6-typeobject-lookup-maybe-method-c89.test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Keep lookup_maybe_method's descriptor getter C89-safe without reordering.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nlookup_maybe_method\(PyObject \*self, PyObject \*attr, int \*unbound\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "lookup_maybe_method definition missing" +body = match.group(1) +assert re.match( + r"\s*PyObject \*res = _PyType_Lookup\(Py_TYPE\(self\), attr\);\s*descrgetfunc f;", + body, +), "lookup_maybe_method: f must be declared in the opening declaration block (C89)" +assert len(re.findall(r"\bdescrgetfunc\s+f\b", body)) == 1, ( + "lookup_maybe_method: declare the descriptor getter exactly once" +) +expected = """ + PyObject *res = _PyType_Lookup(Py_TYPE(self), attr); + descrgetfunc f; + if (res == NULL) { + return NULL; + } + + if (_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) { + /* Avoid temporary PyMethodObject */ + *unbound = 1; + Py_INCREF(res); + } + else { + *unbound = 0; + f = Py_TYPE(res)->tp_descr_get; + if (f == NULL) { + Py_INCREF(res); + } + else { + res = f(res, self, (PyObject *)(Py_TYPE(self))); + } + } + return res; +""" +assert body.split() == expected.split(), ( + "lookup_maybe_method: preserve getter evaluation after *unbound = 0 and all control flow" +) +print("lookup_maybe_method descriptor getter C89 declaration and unchanged evaluation/control flow: PASS") diff --git a/scripts/vc6-typeobject-modified-index-c89.test.py b/scripts/vc6-typeobject-modified-index-c89.test.py new file mode 100644 index 0000000..501a10b --- /dev/null +++ b/scripts/vc6-typeobject-modified-index-c89.test.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +"""Check only PyType_Modified's loop-index declaration and initialization timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nvoid\nPyType_Modified\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "PyType_Modified definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*subclasses;\s*Py_ssize_t i;", body), ( + "PyType_Modified: Py_ssize_t i; must be declared at function entry" +) +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, ( + "PyType_Modified: declare i exactly once" +) +assert re.search( + r"if \(subclasses != NULL\) \{\s*" + r"assert\(PyDict_CheckExact\(subclasses\)\);\s*" + r"i = 0;\s*" + r"while \(PyDict_Next\(subclasses, &i, NULL, &ref\)\) \{", + body, +), "PyType_Modified: initialize i at its original point before the while loop" +assert len(re.findall(r"\bi\s*=", body)) == 1, ( + "PyType_Modified: initialize i exactly once" +) +print("PyType_Modified index C89 declaration and initialization timing: PASS") diff --git a/scripts/vc6-typeobject-modified-ref-c89.test.py b/scripts/vc6-typeobject-modified-ref-c89.test.py new file mode 100644 index 0000000..986dd8b --- /dev/null +++ b/scripts/vc6-typeobject-modified-ref-c89.test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Check PyType_Modified's ref/obj declarations and unchanged use order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nvoid\nPyType_Modified\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "PyType_Modified definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*subclasses;\s*Py_ssize_t i;\s*PyObject \*ref;", + body, +), "PyType_Modified: PyObject *ref; must be in the opening declaration block" +assert len(re.findall(r"\bPyObject\s*\*\s*ref\b", body)) == 1, ( + "PyType_Modified: declare ref exactly once without initialization" +) +assert re.match( + r"\s*PyObject \*subclasses;\s*Py_ssize_t i;\s*PyObject \*ref;\s*" + r"PyObject \*obj;", + body, +), "PyType_Modified: PyObject *obj; must be in the opening declaration block" +assert len(re.findall(r"\bPyObject\s*\*\s*obj\b", body)) == 1, ( + "PyType_Modified: declare obj exactly once without initialization" +) +assert re.fullmatch( + r"\s*PyObject \*subclasses;\s*Py_ssize_t i;\s*PyObject \*ref;\s*" + r"PyObject \*obj;\s*" + r"if \(!_PyType_HasFeature\(type, Py_TPFLAGS_VALID_VERSION_TAG\)\) \{\s*" + r"return;\s*\}\s*" + r"subclasses = type->tp_subclasses;\s*" + r"if \(subclasses != NULL\) \{\s*" + r"assert\(PyDict_CheckExact\(subclasses\)\);\s*i = 0;\s*" + r"while \(PyDict_Next\(subclasses, &i, NULL, &ref\)\) \{\s*" + r"assert\(PyWeakref_CheckRef\(ref\)\);\s*" + r"obj = PyWeakref_GET_OBJECT\(ref\);\s*" + r"if \(obj == Py_None\) \{\s*continue;\s*\}\s*" + r"PyType_Modified\(_PyType_CAST\(obj\)\);\s*\}\s*\}\s*" + r"type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;\s*" + r"type->tp_version_tag = 0;\s*", + body, +), "PyType_Modified: preserve all assignments, uses and evaluation order" +print("PyType_Modified ref/obj C89 declarations and unchanged use order: PASS") diff --git a/scripts/vc6-typeobject-modified-subclasses-c89.test.py b/scripts/vc6-typeobject-modified-subclasses-c89.test.py new file mode 100644 index 0000000..344f850 --- /dev/null +++ b/scripts/vc6-typeobject-modified-subclasses-c89.test.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +"""Check only PyType_Modified's subclasses declaration and read timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nvoid\nPyType_Modified\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "PyType_Modified definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*subclasses;", body), ( + "PyType_Modified: PyObject *subclasses; must be declared at function entry" +) +assert len(re.findall(r"\bPyObject\s*\*\s*subclasses\b", body)) == 1, ( + "PyType_Modified: declare subclasses exactly once" +) +assert re.match( + r"\s*PyObject \*subclasses;\s*" + r"(?:Py_ssize_t i;\s*)?" + r"PyObject \*ref;\s*" + r"PyObject \*obj;\s*" + r"if \(!_PyType_HasFeature\(type, Py_TPFLAGS_VALID_VERSION_TAG\)\) \{\s*" + r"return;\s*\}\s*" + r"subclasses = type->tp_subclasses;\s*" + r"if \(subclasses != NULL\) \{", + body, +), "PyType_Modified: read tp_subclasses immediately after the early-return guard" +assert body.count("type->tp_subclasses") == 1, ( + "PyType_Modified: preserve the single tp_subclasses read" +) +print("PyType_Modified subclasses C89 declaration and read timing: PASS") diff --git a/scripts/vc6-typeobject-mro-bases-c89.test.py b/scripts/vc6-typeobject-mro-bases-c89.test.py new file mode 100644 index 0000000..3b3ab68 --- /dev/null +++ b/scripts/vc6-typeobject-mro-bases-c89.test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Check only the late bases declaration in assign_version_tag near MRO code.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nassign_version_tag\(struct type_cache \*cache, PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "assign_version_tag definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*bases;", body), ( + "assign_version_tag: PyObject *bases; must be in the opening declarations" +) +assert len(re.findall(r"\bPyObject\s*\*\s*bases\b", body)) == 1, ( + "assign_version_tag: declare bases exactly once" +) +expected = """ + PyObject *bases; + Py_ssize_t n; + Py_ssize_t i; + if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) { + return 1; + } + if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) { + return 0; + } + if (next_version_tag == 0) { + return 0; + } + type->tp_version_tag = next_version_tag++; + assert (type->tp_version_tag != 0); + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); + for (i = 0; i < n; i++) { + PyObject *b = PyTuple_GET_ITEM(bases, i); + if (!assign_version_tag(cache, _PyType_CAST(b))) + return 0; + } + type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; + return 1; +""" +assert body.split() == expected.split(), ( + "assign_version_tag: preserve bases read timing, guards, n, and loop index" +) +print("assign_version_tag bases C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-mro-check-c89.test.py b/scripts/vc6-typeobject-mro-check-c89.test.py new file mode 100644 index 0000000..6e111c7 --- /dev/null +++ b/scripts/vc6-typeobject-mro-check-c89.test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Check mro_check's C89 base declaration and validation/cast order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nmro_check\(PyTypeObject \*type, PyObject \*mro\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_check definition missing" +body = match.group(1) +loop = body[body.index(" for (i = 0; i < n; i++) {"):] +opening = loop.split("if (!PyType_Check(obj))", 1)[0] +assert re.search(r"\bPyTypeObject \*base;", opening), ( + "mro_check: PyTypeObject *base; must precede loop statements (C89)" +) +expected = """ + for (i = 0; i < n; i++) { + PyObject *obj = PyTuple_GET_ITEM(mro, i); + PyTypeObject *base; + if (!PyType_Check(obj)) { + PyErr_Format( + PyExc_TypeError, + "mro() returned a non-class ('%.500s')", + Py_TYPE(obj)->tp_name); + return -1; + } + base = (PyTypeObject*)obj; + + if (!PyType_IsSubtype(solid, solid_base(base))) { + PyErr_Format( + PyExc_TypeError, + "mro() returned base with unsuitable layout ('%.500s')", + base->tp_name); + return -1; + } + } + + return 0; +""" +assert loop.split() == expected.split(), ( + "preserve item lookup, non-class rejection before cast, layout validation, and returns" +) +print("mro_check C89 base declaration and unchanged validation/cast order: PASS") diff --git a/scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py b/scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py new file mode 100644 index 0000000..535986e --- /dev/null +++ b/scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Check mro_hierarchy's n/i declarations and guarded subclass loop timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nmro_hierarchy\(PyTypeObject \*type, PyObject \*temp\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_hierarchy definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*old_mro;\s*PyObject \*new_mro;\s*PyObject \*tuple;" + r"\s*Py_ssize_t n;\s*Py_ssize_t i;\s*int res = mro_internal\(", body +), "mro_hierarchy: n and i must be uninitialized opening function declarations" +for name in ("n", "i"): + assert len(re.findall(rf"\bPy_ssize_t\s+{name}\b", body)) == 1, ( + f"mro_hierarchy: declare {name} exactly once" + ) + assert len(re.findall(rf"\b{name}\s*=(?!=)", body)) == 1, ( + f"mro_hierarchy: initialize {name} exactly once at its original point" + ) +expected = """ + if (type->tp_subclasses != NULL) { + PyObject *subclasses = _PyType_GetSubclasses(type); + if (subclasses == NULL) { + return -1; + } + n = PyList_GET_SIZE(subclasses); + for (i = 0; i < n; i++) { + PyTypeObject *subclass = _PyType_CAST(PyList_GET_ITEM(subclasses, i)); + res = mro_hierarchy(subclass, temp); + if (res < 0) { + break; + } + } + Py_DECREF(subclasses); + } + return res; +""" +tail = body[body.index("if (type->tp_subclasses != NULL)"):] +assert tail.split() == expected.split(), ( + "mro_hierarchy: preserve NULL guard, size read, loop, cleanup, and return" +) +print("mro_hierarchy n/i C89 declarations and guarded subclass loop timing: PASS") diff --git a/scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py b/scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py new file mode 100644 index 0000000..a9e47de --- /dev/null +++ b/scripts/vc6-typeobject-mro-hierarchy-new-mro-c89.test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Check only mro_hierarchy's new_mro declaration and guarded read timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nmro_hierarchy\(PyTypeObject \*type, PyObject \*temp\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_hierarchy definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*old_mro;\s*PyObject \*new_mro;", body), ( + "mro_hierarchy: PyObject *new_mro; must be in the opening declarations" +) +assert len(re.findall(r"\bPyObject\s*\*\s*new_mro\b", body)) == 1, ( + "mro_hierarchy: declare new_mro exactly once without initialization" +) +expected_prefix = """ + PyObject *old_mro; + PyObject *new_mro; + PyObject *tuple; + Py_ssize_t n; + Py_ssize_t i; + int res = mro_internal(type, &old_mro); + if (res <= 0) { + return res; + } + new_mro = type->tp_mro; + + if (old_mro != NULL) { + tuple = PyTuple_Pack(3, type, new_mro, old_mro); + } + else { + tuple = PyTuple_Pack(2, type, new_mro); + } +""" +assert body.split()[:len(expected_prefix.split())] == expected_prefix.split(), ( + "mro_hierarchy: preserve the guard, new_mro read timing, and tuple branches" +) +assert len(re.findall(r"\bnew_mro\s*=", body)) == 1, ( + "mro_hierarchy: assign new_mro exactly once" +) +print("mro_hierarchy new_mro C89 declaration and guarded read timing: PASS") diff --git a/scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py b/scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py new file mode 100644 index 0000000..ece78da --- /dev/null +++ b/scripts/vc6-typeobject-mro-hierarchy-tuple-c89.test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Check only mro_hierarchy's tuple declaration and branch assignment timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nmro_hierarchy\(PyTypeObject \*type, PyObject \*temp\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_hierarchy definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*old_mro;\s*PyObject \*new_mro;\s*PyObject \*tuple;", body +), "mro_hierarchy: PyObject *tuple; must be in the opening declarations" +assert len(re.findall(r"\bPyObject\s*\*\s*tuple\b", body)) == 1, ( + "mro_hierarchy: declare tuple exactly once without initialization" +) +expected_prefix = """ + PyObject *old_mro; + PyObject *new_mro; + PyObject *tuple; + Py_ssize_t n; + Py_ssize_t i; + int res = mro_internal(type, &old_mro); + if (res <= 0) { + return res; + } + new_mro = type->tp_mro; + if (old_mro != NULL) { + tuple = PyTuple_Pack(3, type, new_mro, old_mro); + } + else { + tuple = PyTuple_Pack(2, type, new_mro); + } + if (tuple != NULL) { + res = PyList_Append(temp, tuple); + } + else { + res = -1; + } + Py_XDECREF(tuple); +""" +assert body.split()[:len(expected_prefix.split())] == expected_prefix.split(), ( + "mro_hierarchy: preserve the guard, branch assignments, and tuple consumption" +) +assert len(re.findall(r"\btuple\s*=", body)) == 2, ( + "mro_hierarchy: assign tuple only in the two original branches" +) +print("mro_hierarchy tuple C89 declaration and branch assignment timing: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-bases-c89.test.py b/scripts/vc6-typeobject-mro-implementation-bases-c89.test.py new file mode 100644 index 0000000..440514b --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-bases-c89.test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Check only mro_implementation's bases declaration and guarded read timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*bases;", body), ( + "mro_implementation: PyObject *bases; must be in the opening declarations" +) +assert len(re.findall(r"\bPyObject\s*\*\s*bases\b", body)) == 1, ( + "mro_implementation: declare bases exactly once without initialization" +) +expected_prefix = """ + PyObject *bases; + Py_ssize_t n; + Py_ssize_t i; + PyObject **to_merge; + PyObject *result; + if (!_PyType_IsReady(type)) { + if (PyType_Ready(type) < 0) + return NULL; + } + + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); +""" +assert body.split()[:len(expected_prefix.split())] == expected_prefix.split(), ( + "mro_implementation: preserve the ready check and bases read timing" +) +assert len(re.findall(r"\bbases\s*=", body)) == 1, ( + "mro_implementation: assign bases exactly once" +) +print("mro_implementation bases C89 declaration and guarded read timing: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-fast-path-index-c89.test.py b/scripts/vc6-typeobject-mro-implementation-fast-path-index-c89.test.py new file mode 100644 index 0000000..7af5e50 --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-fast-path-index-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Check only mro_implementation's single-base fast-path loop index.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;" + r"\s*PyObject \*\*to_merge;\s*PyObject \*result;\s*if\b", + body, +), ( + "mro_implementation: reuse i from the opening declaration block" +) +fast_path = body.split("if (n == 1) {", 1)[1].split("return result;", 1)[0] +assert not re.search(r"\bPy_ssize_t\s+i\b", fast_path), ( + "mro_implementation: fast-path loop must reuse function-scope i for C89" +) +expected = """ + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, 0)); + Py_ssize_t k = PyTuple_GET_SIZE(base->tp_mro); + PyObject *result = PyTuple_New(k + 1); + if (result == NULL) { + return NULL; + } + Py_INCREF(type); + PyTuple_SET_ITEM(result, 0, (PyObject *) type); + for (i = 0; i < k; i++) { + PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i); + Py_INCREF(cls); + PyTuple_SET_ITEM(result, i + 1, cls); + } +""" +assert fast_path.split() == expected.split(), ( + "mro_implementation: preserve fast-path initialization timing, loop bounds, " + "increment, allocation, reference counts, and tuple writes" +) +print("mro_implementation fast-path loop index C89 declaration and unchanged semantics: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-index-c89.test.py b/scripts/vc6-typeobject-mro-implementation-index-c89.test.py new file mode 100644 index 0000000..e6f2a6e --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-index-c89.test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Check only mro_implementation's first loop index and validation semantics.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +validation = body.split("if (n == 1)", 1)[0] +assert re.match( + r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;" + r"\s*PyObject \*\*to_merge;\s*PyObject \*result;\s*if\b", + validation, +), ( + "mro_implementation: first loop index must be declared in the opening block" +) +assert len(re.findall(r"\bPy_ssize_t\s+i\b", validation)) == 1, "declare first loop index exactly once" +assert len(re.findall(r"\bi\s*=(?!=)", validation)) == 1, "initialize first loop index exactly once" +expected = """ + PyObject *bases; + Py_ssize_t n; + Py_ssize_t i; + PyObject **to_merge; + PyObject *result; + if (!_PyType_IsReady(type)) { + if (PyType_Ready(type) < 0) + return NULL; + } + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); + for (i = 0; i < n; i++) { + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); + if (base->tp_mro == NULL) { + PyErr_Format(PyExc_TypeError, + "Cannot extend an incomplete type '%.100s'", + base->tp_name); + return NULL; + } + assert(PyTuple_Check(base->tp_mro)); + } +""" +assert validation.split() == expected.split(), ( + "mro_implementation: preserve readiness, initialization timing, loop bounds, " + "increment, and base validation" +) +print("mro_implementation first loop index C89 declaration and unchanged validation: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-merge-index-c89.test.py b/scripts/vc6-typeobject-mro-implementation-merge-index-c89.test.py new file mode 100644 index 0000000..f7e051f --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-merge-index-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Check only mro_implementation's to_merge population loop index.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;" + r"\s*PyObject \*\*to_merge;\s*PyObject \*result;\s*if\b", body +), "mro_implementation: reuse i from the opening declaration block" +population = body.split("to_merge = PyMem_New(PyObject *, n + 1);", 1)[1].split( + "result = PyList_New(1);", 1 +)[0] +assert not re.search(r"\bfor\s*\(\s*Py_ssize_t\s+i\b", population), ( + "mro_implementation: to_merge population loop must reuse function-scope i for C89" +) +expected = """ + if (to_merge == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < n; i++) { + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); + to_merge[i] = base->tp_mro; + } + to_merge[n] = bases; +""" +assert population.split() == expected.split(), ( + "mro_implementation: preserve allocation error handling, loop initialization, " + "bounds, increment, base MRO writes, and final bases entry" +) +print("mro_implementation to_merge loop index C89 declaration and unchanged semantics: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-n-c89.test.py b/scripts/vc6-typeobject-mro-implementation-n-c89.test.py new file mode 100644 index 0000000..5bc7672 --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-n-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Check only mro_implementation's n declaration and evaluation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;" + r"\s*PyObject \*\*to_merge;\s*PyObject \*result;\s*if\b", + body, +), ( + "mro_implementation: Py_ssize_t n; must be in the opening declaration block" +) +assert len(re.findall(r"\bPy_ssize_t\s+n\b", body)) == 1, ( + "mro_implementation: declare n exactly once" +) +expected_prefix = """ + PyObject *bases; + Py_ssize_t n; + Py_ssize_t i; + PyObject **to_merge; + PyObject *result; + if (!_PyType_IsReady(type)) { + if (PyType_Ready(type) < 0) + return NULL; + } + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); + for (i = 0; i < n; i++) { +""" +assert body.split()[:len(expected_prefix.split())] == expected_prefix.split(), ( + "mro_implementation: preserve n evaluation timing and loop index initialization" +) +assert len(re.findall(r"\bn\s*=(?!=)", body)) == 1, ( + "mro_implementation: assign n exactly once" +) +print("mro_implementation n C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-population-index-c89.test.py b/scripts/vc6-typeobject-mro-implementation-population-index-c89.test.py new file mode 100644 index 0000000..230f862 --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-population-index-c89.test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Regress the probe's C2143 at the MRO population loop initializer.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = match.group(1) +declarations = body.split("if (!_PyType_IsReady(type))", 1)[0] +assert re.search(r"\bPy_ssize_t i;", declarations), "function-scope i missing" +population = body.split("to_merge = PyMem_New(PyObject *, n + 1);", 1)[1] +loop = re.search(r"\bfor\s*\((.*?)\)\s*\{(.*?)\n \}", population, re.S) +assert loop, "to_merge population loop missing" +assert loop.group(1).split() == "i = 0; i < n; i++".split(), ( + "C2143 regression: to_merge population loop must reuse existing i: " + "for (i = 0; i < n; i++)" +) +assert loop.group(2).split() == """ + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); + to_merge[i] = base->tp_mro; +""".split(), "preserve population loop behavior" +print("mro_implementation population index C2143 regression: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-result-c89.test.py b/scripts/vc6-typeobject-mro-implementation-result-c89.test.py new file mode 100644 index 0000000..0bdca89 --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-result-c89.test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Check the slow-path MRO result declaration and allocation order for C89.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = match.group(1) +opening = body.split("if (!_PyType_IsReady(type))", 1)[0] +assert re.search(r"\bPyObject \*result;", opening), ( + "mro_implementation: PyObject *result; must precede statements (C89)" +) +assert len(re.findall(r"\bPyObject \*result;", body)) == 1, ( + "declare the slow-path result exactly once without initialization" +) +expected = """ + for (i = 0; i < n; i++) { + PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); + to_merge[i] = base->tp_mro; + } + to_merge[n] = bases; + + result = PyList_New(1); + if (result == NULL) { + PyMem_Free(to_merge); + return NULL; + } + + Py_INCREF(type); + PyList_SET_ITEM(result, 0, (PyObject *)type); + if (pmerge(result, to_merge, n + 1) < 0) { + Py_CLEAR(result); + } + PyMem_Free(to_merge); + + return result; +""" +tail = body[body.index(" for (i = 0; i < n; i++)", body.index("to_merge = PyMem_New")):] +assert tail.split() == expected.split(), ( + "preserve result allocation after merge-array population and all subsequent control flow" +) +assert body.count("PyList_New(1)") == 1, "allocate the slow-path result exactly once" +assert "PyObject *result = PyTuple_New(k + 1);" in body, ( + "preserve the separate fast-path result initialization" +) +print("mro_implementation result C89 declaration and unchanged allocation order: PASS") diff --git a/scripts/vc6-typeobject-mro-implementation-to-merge-c89.test.py b/scripts/vc6-typeobject-mro-implementation-to-merge-c89.test.py new file mode 100644 index 0000000..cd51928 --- /dev/null +++ b/scripts/vc6-typeobject-mro-implementation-to-merge-c89.test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Check only mro_implementation's to_merge declaration and allocation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "mro_implementation definition missing" +body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;" + r"\s*PyObject \*\*to_merge;\s*PyObject \*result;\s*if\b", body +), "mro_implementation: PyObject **to_merge; must be in the opening declaration block" +assert len(re.findall(r"\bPyObject\s*\*\*\s*to_merge\b", body)) == 1, ( + "mro_implementation: declare to_merge exactly once" +) +assert len(re.findall(r"\bto_merge\s*=(?!=)", body)) == 1, ( + "mro_implementation: assign to_merge exactly once" +) +expected = """ + if (check_duplicates(bases) < 0) { + return NULL; + } + to_merge = PyMem_New(PyObject *, n + 1); + if (to_merge == NULL) { + PyErr_NoMemory(); + return NULL; + } +""" +allocation = re.split( + r"\bfor\s*\(", body[body.index("if (check_duplicates(bases)"):], maxsplit=1 +)[0] +assert allocation.split() == expected.split(), ( + "mro_implementation: preserve allocation after duplicate validation and error handling" +) +print("mro_implementation to_merge C89 declaration and unchanged allocation timing: PASS") diff --git a/scripts/vc6-typeobject-mro-loop-c89.test.py b/scripts/vc6-typeobject-mro-loop-c89.test.py new file mode 100644 index 0000000..21dc473 --- /dev/null +++ b/scripts/vc6-typeobject-mro-loop-c89.test.py @@ -0,0 +1,16 @@ +from pathlib import Path + + +def test_mro_loop_index_declared_before_c89_for_loop(): + source = Path("cpython/Objects/typeobject.c").read_text() + start = source.index("_PyType_InitCache(PyInterpreterState *interp)") + end = source.index("\n}", start) + 2 + function = source[start:end] + assert "Py_ssize_t i;" in function + assert "for (i = 0;" in function + assert "for (Py_ssize_t i = 0;" not in function + + +if __name__ == "__main__": + test_mro_loop_index_declared_before_c89_for_loop() + print("typeobject MRO loop index C89 declaration: PASS") \ No newline at end of file diff --git a/scripts/vc6-typeobject-object-new-obj-c89.test.py b/scripts/vc6-typeobject-object-new-obj-c89.test.py new file mode 100644 index 0000000..cd39c73 --- /dev/null +++ b/scripts/vc6-typeobject-object-new-obj-c89.test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Check object_new's C89 obj declaration and allocation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nobject_new\(PyTypeObject \*type, PyObject \*args, " + r"PyObject \*kwds\)\n\{(.*?)\n\}", source, re.S, +) +assert match, "object_new definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match(r"\s*PyObject \*obj;\s*if \(excess_args\(args, kwds\)\)", body), ( + "object_new: obj must be in the opening declaration block (C89)" +) +assert len(re.findall(r"\bPyObject\s*\*\s*obj\b", body)) == 1, "declare obj exactly once" +assert len(re.findall(r"\bobj\s*=(?!=)", body)) == 1, "assign obj exactly once" +expected = """ + Py_DECREF(joined); + return NULL; + } + obj = type->tp_alloc(type, 0); + if (obj == NULL) { + return NULL; + } + if (_PyObject_InitializeDict(obj)) { + Py_DECREF(obj); + return NULL; + } + return obj; +""" +assert body[body.index("Py_DECREF(joined);"):].split() == expected.split(), ( + "object_new: preserve allocation after abstract-type rejection, NULL check, " + "dictionary initialization, cleanup, and return order" +) +print("object_new obj C89 declaration and allocation timing: PASS") diff --git a/scripts/vc6-typeobject-object-set-class-newto-c89.test.py b/scripts/vc6-typeobject-object-set-class-newto-c89.test.py new file mode 100644 index 0000000..9710723 --- /dev/null +++ b/scripts/vc6-typeobject-object-set-class-newto-c89.test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Check object_set_class's C89 newto declaration and evaluation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nobject_set_class\(PyObject \*self, PyObject \*value, " + r"void \*closure\)\n\{(.*?)\n\}", source, re.S, +) +assert match, "object_set_class definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyTypeObject \*oldto = Py_TYPE\(self\);\s*PyTypeObject \*newto;\s*if", + body, +), "object_set_class: newto must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*newto\b", body)) == 1, "declare newto exactly once" +assert len(re.findall(r"\bnewto\s*=(?!=)", body)) == 1, "assign newto exactly once" +expected = """ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "can't delete __class__ attribute"); + return -1; + } + if (!PyType_Check(value)) { + PyErr_Format(PyExc_TypeError, + "__class__ must be set to a class, not '%s' object", + Py_TYPE(value)->tp_name); + return -1; + } + newto = (PyTypeObject *)value; + + if (PySys_Audit("object.__setattr__", "OsO", + self, "__class__", value) < 0) { + return -1; + } +""" +assert body[body.index("if (value == NULL)"):body.index("if (!(PyType_IsSubtype")].split() == expected.split(), ( + "object_set_class: preserve rejection paths, cast after type validation, " + "and audit before compatibility checks" +) +print("object_set_class newto C89 declaration and evaluation timing: PASS") diff --git a/scripts/vc6-typeobject-overrides-hash-r-c89.test.py b/scripts/vc6-typeobject-overrides-hash-r-c89.test.py new file mode 100644 index 0000000..b7800ae --- /dev/null +++ b/scripts/vc6-typeobject-overrides-hash-r-c89.test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Keep overrides_hash's query after its assertion with C89 locals.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search(r"\nstatic int\noverrides_hash\(PyTypeObject \*type\)\n\{(.*?)\n\}", source, re.S) +assert match, "overrides_hash definition missing" +body = match.group(1) +assert re.match(r"\s*PyObject \*dict = type->tp_dict;\s*int r;\s*assert", body), ( + "overrides_hash: r must be in the opening C89 declaration block" +) +assert len(re.findall(r"\bint\s+r\b", body)) == 1 +expected = '''assert(dict != NULL); + r = PyDict_Contains(dict, &_Py_ID(__eq__)); + if (r == 0) { + r = PyDict_Contains(dict, &_Py_ID(__hash__)); + } + return r;''' +assert body[body.index("assert(dict") :].split() == expected.split(), ( + "overrides_hash: preserve assertion, query ordering, conditional and error propagation" +) +print("overrides_hash C89 r, query ordering and result propagation: PASS") diff --git a/scripts/vc6-typeobject-set-annotations-c89.test.py b/scripts/vc6-typeobject-set-annotations-c89.test.py new file mode 100644 index 0000000..aab9085 --- /dev/null +++ b/scripts/vc6-typeobject-set-annotations-c89.test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Check type_set_annotations's C89 local and unchanged executable body.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_annotations\(PyTypeObject \*type, PyObject \*value, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_annotations definition missing" +body = match.group(1) +assert re.match(r"\s*int result;\s*if\b", body), ( + "type_set_annotations: result must be declared before the immutable-type guard" +) +assert len(re.findall(r"\bint\s+result\b", body)) == 1, ( + "type_set_annotations: declare result exactly once" +) +expected = """ + int result; + if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) { + PyErr_Format(PyExc_TypeError, + "cannot set '__annotations__' attribute of immutable type '%s'", + type->tp_name); + return -1; + } + + if (value != NULL) { + /* set */ + result = PyDict_SetItem(type->tp_dict, &_Py_ID(__annotations__), value); + } else { + /* delete */ + result = PyDict_DelItem(type->tp_dict, &_Py_ID(__annotations__)); + if (result < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) { + PyErr_SetString(PyExc_AttributeError, "__annotations__"); + } + } + + if (result == 0) { + PyType_Modified(type); + } + return result; +""" +assert body.split() == expected.split(), ( + "type_set_annotations: preserve guard, assignments, set/delete branches, " + "error handling, invalidation, and return in their original order" +) +print("type_set_annotations result C89 declaration and unchanged executable body: PASS") diff --git a/scripts/vc6-typeobject-set-bases-base-c89.test.py b/scripts/vc6-typeobject-set-bases-base-c89.test.py new file mode 100644 index 0000000..185a055 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-base-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Check type_set_bases's base declaration and post-validation cast timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +loop = body.split("for (i = 0; i < n; i++) {", 1)[1].split( + "new_base = best_base(new_bases);", 1 +)[0] +assert re.match( + r"\s*PyObject \*ob = PyTuple_GET_ITEM\(new_bases, i\);\s*PyTypeObject \*base;\s*if\b", + loop, +), "type_set_bases: base must be in the loop's opening declaration block" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*base\b", body)) == 1, "declare base exactly once" +assert len(re.findall(r"\bbase\s*=(?!=)", body)) == 1, "assign base exactly once" +expected = """ + PyObject *ob = PyTuple_GET_ITEM(new_bases, i); + PyTypeObject *base; + if (!PyType_Check(ob)) { + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; + } + base = (PyTypeObject*)ob; + + if (PyType_IsSubtype(base, type) || + (base->tp_mro != NULL && type_is_subtype_base_chain(base, type))) + { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; + } + } +""" +assert loop.split() == expected.split(), ( + "type_set_bases: preserve item retrieval, validation, post-validation base " + "assignment, and inheritance-cycle checks in their original order" +) +print("type_set_bases base C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-set-bases-index-c89.test.py b/scripts/vc6-typeobject-set-bases-index-c89.test.py new file mode 100644 index 0000000..b857ea8 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-index-c89.test.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""Check type_set_bases's loop index declaration and initialization timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyTypeObject \*new_base;\s*PyObject \*old_bases;\s*PyTypeObject \*old_base;\s*PyObject \*temp;\s*int res;\s*if\b", + body, +), ( + "type_set_bases: Py_ssize_t i; must follow n in the opening declarations" +) +assert len(re.findall(r"\bPy_ssize_t\s+n\b", body)) == 1, ( + "type_set_bases: declare n exactly once" +) +assert len(re.findall(r"\bn\s*=\s*PyTuple_GET_SIZE\(new_bases\)", body)) == 1, ( + "type_set_bases: read the new_bases size into n exactly once" +) +validation = body.split("new_base = best_base(new_bases);", 1)[0] +assert len(re.findall(r"\bPy_ssize_t\s+i\b", validation)) == 1, "declare i exactly once" +assert len(re.findall(r"\bi\s*=(?!=)", validation)) == 1, "initialize i exactly once" +assert not re.search(r"for\s*\(\s*Py_ssize_t\s+i\b", validation), "C99 loop index declaration remains" +expected = """ + Py_ssize_t n; + Py_ssize_t i; + PyTypeObject *new_base; + PyObject *old_bases; + PyTypeObject *old_base; + PyObject *temp; + int res; + if (!check_set_special_type_attr(type, new_bases, "__bases__")) { + return -1; + } + assert(new_bases != NULL); + + if (!PyTuple_Check(new_bases)) { + PyErr_Format(PyExc_TypeError, + "can only assign tuple to %s.__bases__, not %s", + type->tp_name, Py_TYPE(new_bases)->tp_name); + return -1; + } + if (PyTuple_GET_SIZE(new_bases) == 0) { + PyErr_Format(PyExc_TypeError, + "can only assign non-empty tuple to %s.__bases__, not ()", + type->tp_name); + return -1; + } + n = PyTuple_GET_SIZE(new_bases); + for (i = 0; i < n; i++) { +""" +assert body.split()[:len(expected.split())] == expected.split(), ( + "type_set_bases: preserve validation, empty-tuple guard, n assignment timing, " + "and index initialization at the original loop point" +) +print("type_set_bases loop index C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-set-bases-n-c89.test.py b/scripts/vc6-typeobject-set-bases-n-c89.test.py new file mode 100644 index 0000000..4d68342 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-n-c89.test.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Check type_set_bases's n declaration and preserve validation order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyTypeObject \*new_base;\s*PyObject \*old_bases;\s*PyTypeObject \*old_base;\s*PyObject \*temp;\s*int res;\s*if\b", + body, +), ( + "type_set_bases: Py_ssize_t n; must be in the opening declarations" +) +assert len(re.findall(r"\bPy_ssize_t\s+n\b", body)) == 1, ( + "type_set_bases: declare n exactly once" +) +assert len(re.findall(r"\bn\s*=\s*PyTuple_GET_SIZE\(new_bases\)", body)) == 1, ( + "type_set_bases: read the new_bases size into n exactly once" +) +expected = """ + Py_ssize_t n; + Py_ssize_t i; + PyTypeObject *new_base; + PyObject *old_bases; + PyTypeObject *old_base; + PyObject *temp; + int res; + if (!check_set_special_type_attr(type, new_bases, "__bases__")) { + return -1; + } + assert(new_bases != NULL); + + if (!PyTuple_Check(new_bases)) { + PyErr_Format(PyExc_TypeError, + "can only assign tuple to %s.__bases__, not %s", + type->tp_name, Py_TYPE(new_bases)->tp_name); + return -1; + } + if (PyTuple_GET_SIZE(new_bases) == 0) { + PyErr_Format(PyExc_TypeError, + "can only assign non-empty tuple to %s.__bases__, not ()", + type->tp_name); + return -1; + } + n = PyTuple_GET_SIZE(new_bases); + for (i = 0; i < n; i++) { +""" +assert body.split()[:len(expected.split())] == expected.split(), ( + "type_set_bases: preserve validation, empty-tuple guard, n assignment timing, " + "and loop index initialization timing" +) +print("type_set_bases n C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-set-bases-new-base-c89.test.py b/scripts/vc6-typeobject-set-bases-new-base-c89.test.py new file mode 100644 index 0000000..6553094 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-new-base-c89.test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Check type_set_bases's new_base declaration and best_base call timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t n;\s*Py_ssize_t i;\s*PyTypeObject \*new_base;\s*PyObject \*old_bases;\s*PyTypeObject \*old_base;\s*PyObject \*temp;\s*int res;\s*if\b", + body, +), "type_set_bases: new_base must be in the opening declaration block" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*new_base\b", body)) == 1, ( + "type_set_bases: declare new_base exactly once" +) +assert len(re.findall(r"\bnew_base\s*=(?!=)", body)) == 1, ( + "type_set_bases: assign new_base exactly once" +) +assert len(re.findall(r"\bbest_base\s*\(", body)) == 1, ( + "type_set_bases: call best_base exactly once" +) +expected = """ + if (PyType_IsSubtype(base, type) || + (base->tp_mro != NULL && type_is_subtype_base_chain(base, type))) + { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; + } + } + + new_base = best_base(new_bases); + if (new_base == NULL) + return -1; + + if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) { + return -1; + } + + old_bases = type->tp_bases; +""" +assert " ".join(expected.split()) in " ".join(body.split()), ( + "type_set_bases: preserve best_base assignment after the validation loop, " + "followed by the NULL guard and compatibility check before saving old bases" +) +print("type_set_bases new_base C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-set-bases-old-base-c89.test.py b/scripts/vc6-typeobject-set-bases-old-base-c89.test.py new file mode 100644 index 0000000..1e25be4 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-old-base-c89.test.py @@ -0,0 +1,27 @@ +"""Check type_set_bases declares old_base before statements without moving its read.""" +from pathlib import Path +import re +import sys + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = match.group(1) +assert re.search( + r"\A\n\s*Py_ssize_t n;\n\s*Py_ssize_t i;\n\s*PyTypeObject \*new_base;\n\s*PyObject \*old_bases;\n\s*PyTypeObject \*old_base;", + body, +), "type_set_bases: old_base must be declared with the opening locals" +assert body.count("PyTypeObject *old_base;") == 1, "old_base declaration must occur once" +assert body.count("old_base = type->tp_base;") == 1, "old_base read must occur once" +assert re.search( + r'if \(!compatible_for_assignment\(type->tp_base, new_base, "__bases__"\)\) \{\s*' + r'return -1;\s*\}\s*old_bases = type->tp_bases;\s*' + r'assert\(old_bases != NULL\);\s*old_base = type->tp_base;\s*' + r'type->tp_bases = Py_NewRef\(new_bases\);\s*' + r'type->tp_base = \(PyTypeObject \*\)Py_NewRef\(new_base\);', + body, +), "type_set_bases: preserve old_base read after validation and before base replacement" diff --git a/scripts/vc6-typeobject-set-bases-old-bases-c89.test.py b/scripts/vc6-typeobject-set-bases-old-bases-c89.test.py new file mode 100644 index 0000000..48f0342 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-old-bases-c89.test.py @@ -0,0 +1,21 @@ +"""Check type_set_bases declares old_bases in its opening declaration block.""" +from pathlib import Path +import re +import sys + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = match.group(1) +assert re.search( + r"\A\n\s*Py_ssize_t n;\n\s*Py_ssize_t i;\n\s*PyTypeObject \*new_base;\n\s*PyObject \*old_bases;", + body, +), "type_set_bases: old_bases must be declared with the opening locals" +assert body.count("PyObject *old_bases;") == 1, "old_bases declaration must occur once" +assert re.search(r"\n\s*old_bases = type->tp_bases;\n\s*assert\(old_bases != NULL\);", body), ( + "type_set_bases: preserve old_bases assignment and assertion order" +) \ No newline at end of file diff --git a/scripts/vc6-typeobject-set-bases-res-c89.test.py b/scripts/vc6-typeobject-set-bases-res-c89.test.py new file mode 100644 index 0000000..11c5cc9 --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-res-c89.test.py @@ -0,0 +1,33 @@ +"""Check type_set_bases declares res with opening locals without moving assignments.""" +from pathlib import Path +import re +import sys + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = match.group(1) +assert re.search( + r"\A\n\s*Py_ssize_t n;\n\s*Py_ssize_t i;\n\s*PyTypeObject \*new_base;\n" + r"\s*PyObject \*old_bases;\n\s*PyTypeObject \*old_base;\n\s*PyObject \*temp;\n\s*int res;", + body, +), "type_set_bases: res must be declared with the opening locals" +assert body.count("int res;") == 1, "res declaration must occur once" +assert re.findall(r"\bres\s*=\s*([^;]+);", body) == [ + "0", "add_all_subclasses(type, new_bases)", "0", +], "type_set_bases: preserve all res assignments and their order" +without_comments = re.sub(r"/\*.*?\*/|//[^\n]*", "", body, flags=re.S) +assert re.search( + r"if \(mro_hierarchy\(type, temp\) < 0\) \{\s*goto undo;\s*\}\s*" + r"Py_DECREF\(temp\);\s*res = 0;\s*if \(type->tp_bases == new_bases\) \{\s*" + r"remove_all_subclasses\(type, old_bases\);\s*" + r"res = add_all_subclasses\(type, new_bases\);\s*update_all_slots\(type\);\s*" + r"\}\s*else \{\s*res = 0;\s*\}\s*" + r"Py_DECREF\(old_bases\);\s*Py_DECREF\(old_base\);\s*" + r"assert\(_PyType_CheckConsistency\(type\)\);\s*return res;", + without_comments, +), "type_set_bases: preserve res assignment evaluation and control-flow order" diff --git a/scripts/vc6-typeobject-set-bases-rollback-index-c89.test.py b/scripts/vc6-typeobject-set-bases-rollback-index-c89.test.py new file mode 100644 index 0000000..c29155c --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-rollback-index-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Check the C89 rollback index and reverse MRO restoration order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert not re.search(r"for\s*\(\s*Py_ssize_t\s+i\b", body), ( + "type_set_bases: C99 rollback loop index declaration remains" +) +assert re.match(r"\s*Py_ssize_t n;\s*Py_ssize_t i;", body), ( + "type_set_bases: reuse i from the opening declarations" +) +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, ( + "type_set_bases: declare i exactly once" +) +rollback = body.split("undo:", 1)[1].split("bail:", 1)[0] +expected = ''' + n = PyList_GET_SIZE(temp); + for (i = n - 1; i >= 0; i--) { + PyTypeObject *cls; + PyObject *new_mro, *old_mro = NULL; + + PyArg_UnpackTuple(PyList_GET_ITEM(temp, i), + "", 2, 3, &cls, &new_mro, &old_mro); + if (cls->tp_mro == new_mro) { + Py_XINCREF(old_mro); + cls->tp_mro = old_mro; + Py_DECREF(new_mro); + } + } + Py_DECREF(temp); +''' +assert rollback.split() == expected.split(), ( + "type_set_bases: preserve rollback size evaluation, reverse iteration, " + "newer-MRO guard, reference operations, and temp cleanup order" +) +print("type_set_bases rollback index C89 and unchanged restoration order: PASS") diff --git a/scripts/vc6-typeobject-set-bases-temp-c89.test.py b/scripts/vc6-typeobject-set-bases-temp-c89.test.py new file mode 100644 index 0000000..ffe774b --- /dev/null +++ b/scripts/vc6-typeobject-set-bases-temp-c89.test.py @@ -0,0 +1,25 @@ +"""Check type_set_bases declares temp before statements without moving its initialization.""" +from pathlib import Path +import re +import sys + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_set_bases\(PyTypeObject \*type, PyObject \*new_bases, void \*context\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_set_bases definition missing" +body = match.group(1) +assert re.search( + r"\A\n\s*Py_ssize_t n;\n\s*Py_ssize_t i;\n\s*PyTypeObject \*new_base;\n\s*PyObject \*old_bases;\n\s*PyTypeObject \*old_base;\n\s*PyObject \*temp;", + body, +), "type_set_bases: temp must be declared with the opening locals" +assert body.count("PyObject *temp;") == 1, "temp declaration must occur once" +assert body.count("temp = PyList_New(0);") == 1, "temp initialization must occur once" +assert re.search( + r"old_base = type->tp_base;\s*type->tp_bases = Py_NewRef\(new_bases\);\s*" + r"type->tp_base = \(PyTypeObject \*\)Py_NewRef\(new_base\);\s*" + r"temp = PyList_New\(0\);", + body, +), "type_set_bases: preserve temp initialization after base replacement" diff --git a/scripts/vc6-typeobject-static-initializers-c89.test.py b/scripts/vc6-typeobject-static-initializers-c89.test.py new file mode 100644 index 0000000..a4f2776 --- /dev/null +++ b/scripts/vc6-typeobject-static-initializers-c89.test.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""Check only the two static type initializer mappings at the VC6 frontier.""" +import re +from pathlib import Path + +source = Path('cpython/Objects/typeobject.c').read_text() +header = Path('cpython/Include/cpython/object.h').read_text() + + +def uncomment(text): + return re.sub(r'/\*.*?\*/|//[^\n]*', '', text, flags=re.S) + + +def check(name, declaration, layout, prefix, expected, head=''): + match = re.search(declaration + ' ' + name + r' = \{(.*?)\n\};', source, re.S) + assert match, name + ': initializer missing' + body = uncomment(match.group(1)).strip() + assert not re.search(r'\.\w+\s*=', body), name + ': designated initializer is not VC6/C89 compatible' + if head: + assert body.startswith(head), name + ': object header changed' + body = body[len(head):] + fields = re.findall(r'\b(' + prefix + r'\w+)\b', uncomment(layout)) + assert len(fields) == len(set(fields)) == (36 if prefix == 'nb_' else 48) + # Split only at top-level commas (offsetof arguments contain commas). + values = [v.strip() for v in re.split(r',\s*(?![^()]*\))', body) if v.strip()] + assert len(values) <= len(fields), name + ': excess initializer entries' + values += ['0'] * (len(fields) - len(values)) + normalize = lambda value: re.sub(r'\s+', '', value) + actual = dict(zip(fields, map(normalize, values))) + wanted = {field: normalize(expected.get(field, '0')) for field in fields} + assert expected.keys() <= actual.keys(), name + ': expected fields absent from header' + assert actual == wanted, name + ': field mappings changed: ' + repr({k: (actual[k], wanted[k]) for k in fields if actual[k] != wanted[k]}) + print(f'{name}: C89 positional structure and all {len(fields)} field mappings PASS') + + +number_layout = re.search(r'typedef struct \{([^{}]*)\} PyNumberMethods;', header, re.S) +assert number_layout, 'PyNumberMethods layout missing' +check('type_as_number', 'static PyNumberMethods', number_layout.group(1), 'nb_', { + 'nb_or': '_Py_union_type_or', +}) +type_layout = re.search(r'struct _typeobject \{(.*?)\n\};', header, re.S) +assert type_layout, 'PyTypeObject layout missing' +check('PyType_Type', 'PyTypeObject', type_layout.group(1), 'tp_', { + 'tp_name': '"type"', + 'tp_basicsize': 'sizeof(PyHeapTypeObject)', + 'tp_itemsize': 'sizeof(PyMemberDef)', + 'tp_dealloc': '(destructor)type_dealloc', + 'tp_vectorcall_offset': 'offsetof(PyTypeObject, tp_vectorcall)', + 'tp_repr': '(reprfunc)type_repr', + 'tp_as_number': '&type_as_number', + 'tp_call': '(ternaryfunc)type_call', + 'tp_getattro': '(getattrofunc)type_getattro', + 'tp_setattro': '(setattrofunc)type_setattro', + 'tp_flags': 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS | Py_TPFLAGS_HAVE_VECTORCALL', + 'tp_doc': 'type_doc', + 'tp_traverse': '(traverseproc)type_traverse', + 'tp_clear': '(inquiry)type_clear', + 'tp_weaklistoffset': 'offsetof(PyTypeObject, tp_weaklist)', + 'tp_methods': 'type_methods', + 'tp_members': 'type_members', + 'tp_getset': 'type_getsets', + 'tp_dictoffset': 'offsetof(PyTypeObject, tp_dict)', + 'tp_init': 'type_init', + 'tp_new': 'type_new', + 'tp_free': 'PyObject_GC_Del', + 'tp_is_gc': '(inquiry)type_is_gc', + 'tp_vectorcall': 'type_vectorcall', +}, 'PyVarObject_HEAD_INIT(&PyType_Type, 0)') diff --git a/scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py b/scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py new file mode 100644 index 0000000..e9d2d73 --- /dev/null +++ b/scripts/vc6-typeobject-subtype-dealloc-gc-type-needs-decref-c89.test.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Keep GC subtype_dealloc's decref decision C89-safe at its evaluation point.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic void\nsubtype_dealloc\(PyObject \*self\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "subtype_dealloc definition missing" +body = match.group(1) +assert re.match( + r"\s*PyTypeObject \*type, \*base;\s*destructor basedealloc;" + r"\s*int has_finalizer;\s*int type_needs_decref;", + body, +), "GC subtype_dealloc: type_needs_decref must be declared at function entry (C89)" +start = body.index(" /* We get here only if the type has GC */") +end = body.index(" /* Explanation of the weirdness", start) +branch = re.sub(r"/\*.*?\*/|//[^\n]*", "", body[start:end], flags=re.S) +expected = r""" + PyObject_GC_UnTrack(self); + Py_TRASHCAN_BEGIN(self, subtype_dealloc); + base = type; + while (( base->tp_dealloc) == subtype_dealloc) { + base = base->tp_base; + assert(base); + } + has_finalizer = type->tp_finalize || type->tp_del; + if (type->tp_finalize) { + _PyObject_GC_TRACK(self); + if (PyObject_CallFinalizerFromDealloc(self) < 0) { + goto endlabel; + } + _PyObject_GC_UNTRACK(self); + } + if (type->tp_weaklistoffset && !base->tp_weaklistoffset) { + PyObject_ClearWeakRefs(self); + } + if (type->tp_del) { + _PyObject_GC_TRACK(self); + type->tp_del(self); + if (Py_REFCNT(self) > 0) { + goto endlabel; + } + _PyObject_GC_UNTRACK(self); + } + if (has_finalizer) { + if (type->tp_weaklistoffset && !base->tp_weaklistoffset) { + PyWeakReference **list = (PyWeakReference **) \ + _PyObject_GET_WEAKREFS_LISTPTR(self); + while (*list) + _PyWeakref_ClearRef(*list); + } + } + base = type; + while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { + if (Py_SIZE(base)) + clear_slots(base, self); + base = base->tp_base; + assert(base); + } + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + PyObject **dictptr = _PyObject_ManagedDictPointer(self); + if (*dictptr != NULL) { + assert(*_PyObject_ValuesPointer(self) == NULL); + Py_DECREF(*dictptr); + *dictptr = NULL; + } + else { + _PyObject_FreeInstanceAttributes(self); + } + } + else if (type->tp_dictoffset && !base->tp_dictoffset) { + PyObject **dictptr = _PyObject_DictPointer(self); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + if (dict != NULL) { + Py_DECREF(dict); + *dictptr = NULL; + } + } + } + type = Py_TYPE(self); + if (_PyType_IS_GC(base)) { + _PyObject_GC_TRACK(self); + } + type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE + && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + assert(basedealloc); + basedealloc(self); + if (type_needs_decref) { + Py_DECREF(type); + } + endlabel: + Py_TRASHCAN_END +""" +assert branch.split() == expected.split(), ( + "GC subtype_dealloc: preserve assignment evaluation point and all control flow" +) +print("GC subtype_dealloc type_needs_decref C89 declaration and unchanged control flow: PASS") diff --git a/scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py b/scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py new file mode 100644 index 0000000..1de790f --- /dev/null +++ b/scripts/vc6-typeobject-subtype-dealloc-type-needs-decref-c89.test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Keep only non-GC subtype_dealloc's type_needs_decref C89-safe.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic void\nsubtype_dealloc\(PyObject \*self\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "subtype_dealloc definition missing" +body = match.group(1) +start = body.index(" if (!_PyType_IS_GC(type)) {") +end = body.index(" /* We get here only if the type has GC */", start) +branch = re.sub(r"/\*.*?\*/|//[^\n]*", "", body[start:end], flags=re.S) +assert re.match(r"\s*if \(!_PyType_IS_GC\(type\)\) \{\s*int type_needs_decref;", branch), ( + "non-GC subtype_dealloc: type_needs_decref must be declared at block entry (C89)" +) +expected = """ + if (!_PyType_IS_GC(type)) { + int type_needs_decref; + if (type->tp_finalize) { + if (PyObject_CallFinalizerFromDealloc(self) < 0) + return; + } + if (type->tp_del) { + type->tp_del(self); + if (Py_REFCNT(self) > 0) { + return; + } + } + base = type; + while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { + base = base->tp_base; + assert(base); + } + type = Py_TYPE(self); + type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE + && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); + assert(basedealloc); + basedealloc(self); + if (type_needs_decref) { + Py_DECREF(type); + } + return; + } +""" +assert branch.split() == expected.split(), ( + "non-GC subtype_dealloc: preserve assignment evaluation point and all control flow" +) +print("non-GC subtype_dealloc type_needs_decref C89 declaration and unchanged control flow: PASS") diff --git a/scripts/vc6-typeobject-subtype-traverse-err-c89.test.py b/scripts/vc6-typeobject-subtype-traverse-err-c89.test.py new file mode 100644 index 0000000..27afa07 --- /dev/null +++ b/scripts/vc6-typeobject-subtype-traverse-err-c89.test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Keep subtype_traverse's managed-dict err C89-safe without moving evaluation.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\nsubtype_traverse\(PyObject \*self, visitproc visit, void \*arg\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "subtype_traverse definition missing" +body = match.group(1) +assert re.match( + r"\s*PyTypeObject \*type, \*base;\s*traverseproc basetraverse;\s*int err;", + body, +), "subtype_traverse: managed-dict err must be declared at function entry (C89)" +assert len(re.findall(r"\bint\s+err\b", body)) == 2, ( + "subtype_traverse: retain the separate slot-local err and one function-local err" +) +expected = """ + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + assert(type->tp_dictoffset); + err = _PyObject_VisitInstanceAttributes(self, visit, arg); + if (err) { + return err; + } + } +""" +managed_dict = body[body.index(" if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT)"):body.index(" if (type->tp_dictoffset != base->tp_dictoffset)")] +assert managed_dict.split() == expected.split(), ( + "subtype_traverse: preserve guarded evaluation after assertion and error propagation" +) +assert body.count("_PyObject_VisitInstanceAttributes(") == 1, ( + "subtype_traverse: visit instance attributes exactly once" +) +slots = """ + if (Py_SIZE(base)) { + int err = traverse_slots(base, self, visit, arg); + if (err) + return err; + } +""" +assert " ".join(slots.split()) in " ".join(body.split()), ( + "subtype_traverse: preserve the slot-local err declaration and control flow" +) +print("subtype_traverse managed-dict err C89 declaration and unchanged evaluation/control flow: PASS") diff --git a/scripts/vc6-typeobject-type-call-nargs-c89.test.py b/scripts/vc6-typeobject-type-call-nargs-c89.test.py new file mode 100644 index 0000000..666e115 --- /dev/null +++ b/scripts/vc6-typeobject-type-call-nargs-c89.test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Keep type_call's nargs declaration C89-safe and its evaluation after asserts.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\ntype_call\(PyTypeObject \*type, PyObject \*args, PyObject \*kwds\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_call definition missing" +body = match.group(1) +assert re.search(r"if \(type == &PyType_Type\) \{\s*Py_ssize_t nargs;", body), ( + "type_call: nargs must be declared at block entry before assertions (C89)" +) +assert len(re.findall(r"\bPy_ssize_t\s+nargs\b", body)) == 1, ( + "type_call: declare nargs exactly once" +) +expected = """ + if (type == &PyType_Type) { + Py_ssize_t nargs; + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); + nargs = PyTuple_GET_SIZE(args); + + if (nargs == 1 && (kwds == NULL || !PyDict_GET_SIZE(kwds))) { + obj = (PyObject *) Py_TYPE(PyTuple_GET_ITEM(args, 0)); + Py_INCREF(obj); + return obj; + } + + /* SF bug 475327 -- if that didn't trigger, we need 3 + arguments. But PyArg_ParseTuple in type_new may give + a msg saying type() needs exactly 3. */ + if (nargs != 3) { + PyErr_SetString(PyExc_TypeError, + "type() takes 1 or 3 arguments"); + return NULL; + } + } +""" +special_case = body[body.index(" if (type == &PyType_Type)"):body.index(" if (type->tp_new == NULL)")] +assert special_case.split() == expected.split(), ( + "type_call: preserve nargs assignment after assertions and special-case control flow" +) +assert re.findall(r"\bnargs\s*=(?!=)\s*([^;]+);", body) == ["PyTuple_GET_SIZE(args)"], ( + "type_call: evaluate nargs exactly once" +) +print("type_call nargs C89 declaration and unchanged evaluation/control flow: PASS") diff --git a/scripts/vc6-typeobject-type-getattro-local-get-c89.test.py b/scripts/vc6-typeobject-type-getattro-local-get-c89.test.py new file mode 100644 index 0000000..679381f --- /dev/null +++ b/scripts/vc6-typeobject-type-getattro-local-get-c89.test.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Keep type_getattro's local descriptor getter declaration C89-safe.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search(r"\ntype_getattro\(PyTypeObject \*type, PyObject \*name\)\n\{(.*?)\n\}", source, re.S) +assert match, "type_getattro definition missing" +body = match.group(1) +block = re.search(r"if \(attribute != NULL\) \{(.*?)\n \}", body, re.S) +assert block, "type_getattro local attribute block missing" +assert "descrgetfunc local_get;" in block.group(1), ( + "type_getattro: local_get must be declared in the local attribute block" +) +assert block.group(1).index("descrgetfunc local_get;") < block.group(1).index("Py_INCREF(attribute);"), ( + "type_getattro: local_get must be declared before statements in the C89 block" +) +assert "local_get = Py_TYPE(attribute)->tp_descr_get;" in block.group(1), ( + "type_getattro: descriptor getter assignment must remain in place" +) +assert len(re.findall(r"\bdescrgetfunc\s+local_get\b", body)) == 1, ( + "type_getattro: declare local_get exactly once" +) diff --git a/scripts/vc6-typeobject-type-name-c89.test.py b/scripts/vc6-typeobject-type-name-c89.test.py new file mode 100644 index 0000000..9d9789a --- /dev/null +++ b/scripts/vc6-typeobject-type-name-c89.test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Check _PyType_Name's C89 declaration and preserve strrchr evaluation order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nconst char \*\n_PyType_Name\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "_PyType_Name definition missing" +body = match.group(1) +assert re.match(r"\s*const char \*s;\s*assert\b", body), ( + "_PyType_Name: const char *s; must be in the opening declaration block" +) +assert len(re.findall(r"\bconst char\s*\*\s*s\b", body)) == 1, ( + "_PyType_Name: declare s exactly once" +) +expected = """ + const char *s; + assert(type->tp_name != NULL); + s = strrchr(type->tp_name, '.'); + if (s == NULL) { + s = type->tp_name; + } + else { + s++; + } + return s; +""" +assert body.split() == expected.split(), ( + "_PyType_Name: preserve assertion before strrchr assignment, " + "fallback, suffix increment, and return" +) +print("_PyType_Name s C89 declaration and unchanged evaluation order: PASS") diff --git a/scripts/vc6-typeobject-type-new-alloc-heap-type-c89.test.py b/scripts/vc6-typeobject-type-new-alloc-heap-type-c89.test.py new file mode 100644 index 0000000..7d25ef1 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-alloc-heap-type-c89.test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Check type_new_alloc's C89 heap-type declaration and cast timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyTypeObject\*\ntype_new_alloc\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_alloc definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyTypeObject \*metatype = ctx->metatype;" + r"\s*PyTypeObject \*type;\s*PyHeapTypeObject \*et;\s*type\s*=", + body, +), "type_new_alloc: et must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyHeapTypeObject\s*\*\s*et\b", body)) == 1, ( + "declare et exactly once" +) +assert len(re.findall(r"\bet\s*=(?!=)", body)) == 1, ( + "assign et exactly once" +) +expected = """ + PyTypeObject *metatype = ctx->metatype; + PyTypeObject *type; + PyHeapTypeObject *et; + type = (PyTypeObject *)metatype->tp_alloc(metatype, ctx->nslot); + if (type == NULL) { + return NULL; + } + et = (PyHeapTypeObject *)type; +""" +prefix = body.split("type->tp_flags =", 1)[0] +assert prefix.split() == expected.split(), ( + "type_new_alloc: preserve allocation, NULL check, and heap-type cast " + "before flag initialization in their original order" +) +print("type_new_alloc heap-type C89 declaration and cast timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-args-c89.test.py b/scripts/vc6-typeobject-type-new-args-c89.test.py new file mode 100644 index 0000000..6635c68 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-args-c89.test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Check type_new argument declarations without crossing the ctx frontier.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\ntype_new\(PyTypeObject \*metatype, " + r"PyObject \*args, PyObject \*kwds\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new definition missing" +body = match.group(1) +assert re.match(r"\s*PyObject \*name, \*bases, \*orig_dict;\s*type_new_ctx ctx;\s*" + r"PyObject \*type;\s*int res;\s*assert\(", body), ( + "type_new: name, bases, orig_dict must precede statements (C89)" +) +expected_prefix = ''' + PyObject *name, *bases, *orig_dict; + type_new_ctx ctx; + PyObject *type; + int res; + + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); + + /* Parse arguments: (name, bases, dict) */ + if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", + &name, + &PyTuple_Type, &bases, + &PyDict_Type, &orig_dict)) + { + return NULL; + } + + ''' +prefix, separator, _ = body.partition("memset(&ctx, 0, sizeof(ctx));") +assert separator, "post-parse context zero-initialization frontier must remain" +assert prefix.split() == expected_prefix.split(), ( + "preserve assertion order, argument parsing, and failure return before ctx" +) +print("type_new argument declarations and evaluation order: PASS") diff --git a/scripts/vc6-typeobject-type-new-c89.test.py b/scripts/vc6-typeobject-type-new-c89.test.py new file mode 100644 index 0000000..0467d35 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-c89.test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Statically check type_new's type/res declarations and execution order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +function = re.search( + r"\ntype_new\(PyTypeObject \*metatype, PyObject \*args, PyObject \*kwds\)\n\{(.*?)\n\}", + source, re.S, +) +assert function, "type_new definition must exist" +body = function.group(1) +assert re.match( + r"\s*PyObject \*name, \*bases, \*orig_dict;\s*" + r"type_new_ctx ctx;\s*PyObject \*type;\s*int res;\s*assert\(", body, +), "type_new: PyObject *type and int res must be in the opening declaration block" +assert len(re.findall(r"\bPyObject\s*\*type\b", body)) == 1 +assert len(re.findall(r"\bint\s+res\b", body)) == 1 +expected_tail = """ + ctx.bases = bases; + type = NULL; + res = type_new_get_bases(&ctx, &type); + if (res < 0) { + assert(PyErr_Occurred()); + return NULL; + } + if (res == 1) { + assert(type != NULL); + return type; + } + assert(ctx.base != NULL); + assert(ctx.bases != NULL); + + type = type_new_impl(&ctx); + Py_DECREF(ctx.bases); + return type; +""" +assert body[body.index(" ctx.bases = bases;"):].split() == expected_tail.split(), ( + "type_new: preserve assignment locations, base resolution, branches and cleanup" +) +print("type_new type/res opening declarations and execution order: PASS (static only)") diff --git a/scripts/vc6-typeobject-type-new-classmethod-c89.test.py b/scripts/vc6-typeobject-type-new-classmethod-c89.test.py new file mode 100644 index 0000000..0eafd86 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-classmethod-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Check type_new_classmethod's C89 declaration and guarded allocation.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_classmethod\(PyTypeObject \*type, PyObject \*attr\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_classmethod definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*method;" + r"\s*PyObject \*func = PyDict_GetItemWithError\(type->tp_dict, attr\);", + body, +), "type_new_classmethod: method must be in the opening declaration block (C89)" +expected = """ + PyObject *method; + PyObject *func = PyDict_GetItemWithError(type->tp_dict, attr); + if (func == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + if (!PyFunction_Check(func)) { + return 0; + } + + method = PyClassMethod_New(func); + if (method == NULL) { + return -1; + } + if (PyDict_SetItem(type->tp_dict, attr, method) < 0) { + Py_DECREF(method); + return -1; + } + Py_DECREF(method); + return 0; +""" +assert body.split() == expected.split(), ( + "type_new_classmethod: preserve lookup, guards, allocation timing, " + "dictionary insertion, decrefs, and returns" +) +print("type_new_classmethod method C89 declaration and guarded allocation: PASS") diff --git a/scripts/vc6-typeobject-type-new-copy-slots-c89.test.py b/scripts/vc6-typeobject-type-new-copy-slots-c89.test.py new file mode 100644 index 0000000..a88da76 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-copy-slots-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Regress type_new_copy_slots C89 declarations and assignment timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject\*\ntype_new_copy_slots\(type_new_ctx \*ctx, PyObject \*dict\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_copy_slots definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*slots = ctx->slots;" + r"\s*Py_ssize_t nslot = ctx->nslot;" + r"\s*Py_ssize_t new_nslot = nslot - ctx->add_dict - ctx->add_weak;" + r"\s*PyObject \*new_slots = PyList_New\(new_nslot\);" + r"\s*Py_ssize_t j;\s*Py_ssize_t i;\s*PyObject \*tuple;\s*if\b", + body, +), "type_new_copy_slots: j, i, tuple must be in the opening declaration block (C89)" +assert re.search( + r"if \(new_slots == NULL\)\s*\{\s*return NULL;\s*\}" + r"\s*j = 0;\s*for \(i = 0; i < nslot; i\+\+\)\s*\{" + r"\s*PyObject \*slot = PyTuple_GET_ITEM\(slots, i\);\s*int r;\s*if\b", + body, +), "preserve allocation check, index initialization and loop; declare r before statements" +assert re.search( + r"slot =_Py_Mangle\(ctx->name, slot\);" + r"\s*if \(!slot\)\s*\{\s*goto error;\s*\}" + r"\s*PyList_SET_ITEM\(new_slots, j, slot\);" + r"\s*r = PyDict_Contains\(dict, slot\);\s*if \(r < 0\)", + body, +), "preserve mangling, ownership transfer, dict lookup and error-check order" +assert re.search( + r"j\+\+;\s*\}\s*assert\(j == new_nslot\);" + r"\s*if \(PyList_Sort\(new_slots\) == -1\)\s*\{\s*goto error;\s*\}" + r"\s*tuple = PyList_AsTuple\(new_slots\);\s*Py_DECREF\(new_slots\);" + r"\s*if \(tuple == NULL\)", + body, +), "preserve index increment, sorting, tuple conversion and cleanup order" +for declaration in (r"Py_ssize_t j\b", r"Py_ssize_t i\b", r"int r\b", r"PyObject \*tuple\b"): + assert len(re.findall(declaration, body)) == 1, "declare each moved local exactly once" +print("type_new_copy_slots C89 declarations and assignment timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-ctx-c89.test.py b/scripts/vc6-typeobject-type-new-ctx-c89.test.py new file mode 100644 index 0000000..8ed0035 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-ctx-c89.test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""Statically check type_new ctx declaration and post-parse initialization.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +function = re.search( + r"\ntype_new\(PyTypeObject \*metatype, PyObject \*args, PyObject \*kwds\)\n\{(.*?)\n\}", + source, re.S, +) +assert function, "type_new definition must exist" +body = function.group(1) +opening = re.match( + r"\s*PyObject \*name, \*bases, \*orig_dict;\s*type_new_ctx ctx;\s*" + r"PyObject \*type;\s*int res;\s*(?=assert\()", + body, +) +assert opening, "type_new: type_new_ctx ctx must be in the opening declaration block" +assert len(re.findall(r"\btype_new_ctx\s+ctx\b", body)) == 1 +expected_setup = """ + memset(&ctx, 0, sizeof(ctx)); + ctx.metatype = metatype; + ctx.args = args; + ctx.kwds = kwds; + ctx.orig_dict = orig_dict; + ctx.name = name; + ctx.bases = bases; +""" +expected_parse = """ + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); + + /* Parse arguments: (name, bases, dict) */ + if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", + &name, + &PyTuple_Type, &bases, + &PyDict_Type, &orig_dict)) + { + return NULL; + } +""" +prefix, separator, tail = body[opening.end():].partition("type = NULL;") +assert separator, "base-resolution frontier must remain" +assert prefix.split() == (expected_parse + expected_setup).split(), ( + "preserve parsing and failure return, then zero all ctx fields and assign inputs" +) +assert tail.lstrip().startswith("res = type_new_get_bases(&ctx, &type);"), ( + "base resolution must still follow ctx setup" +) +assert "(type_new_ctx)" not in body, "no C99 compound literal" +assert "# include " in Path("cpython/Include/Python.h").read_text() +print("type_new ctx opening declaration and post-parse zero/field setup: PASS (static only)") diff --git a/scripts/vc6-typeobject-type-new-descriptors-index-c89.test.py b/scripts/vc6-typeobject-type-new-descriptors-index-c89.test.py new file mode 100644 index 0000000..c65f37e --- /dev/null +++ b/scripts/vc6-typeobject-type-new-descriptors-index-c89.test.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Regress VC6 C89 compatibility of type_new_descriptors() loop index.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_descriptors\(const type_new_ctx \*ctx, PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_descriptors definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t i;" + r"\s*PyHeapTypeObject \*et = \(PyHeapTypeObject \*\)type;" + r"\s*Py_ssize_t slotoffset = ctx->base->tp_basicsize;", + body, +), "type_new_descriptors: loop index i must be in opening locals (C89)" +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, ( + "declare loop index i exactly once" +) +assert re.search( + r"if \(et->ht_slots != NULL\)\s*\{" + r"\s*PyMemberDef \*mp = _PyHeapType_GET_MEMBERS\(et\);" + r"\s*Py_ssize_t nslot = PyTuple_GET_SIZE\(et->ht_slots\);" + r"\s*for \(i = 0; i < nslot; i\+\+, mp\+\+\)\s*\{" + r"\s*mp->name = PyUnicode_AsUTF8\(\s*PyTuple_GET_ITEM\(et->ht_slots, i\)\);", + body, +), "preserve guarded slot setup, loop start, bound, increments, and indexing" +print("type_new_descriptors C89 loop index: PASS") diff --git a/scripts/vc6-typeobject-type-new-get-bases-base-c89.test.py b/scripts/vc6-typeobject-type-new-get-bases-base-c89.test.py new file mode 100644 index 0000000..4956cdf --- /dev/null +++ b/scripts/vc6-typeobject-type-new-get-bases-base-c89.test.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +"""Check type_new_get_bases base local is C89-compatible and assigned in place.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new_get_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t nbases = PyTuple_GET_SIZE\(ctx->bases\);" + r"\s*Py_ssize_t i;\s*PyTypeObject \*winner;\s*PyTypeObject \*base;" + r"\s*if \(nbases == 0\)", + body, +), "type_new_get_bases: base must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*base\b", body)) == 1, ( + "declare base exactly once" +) +assert re.search(r"\n\s*base = best_base\(ctx->bases\);", body), ( + "preserve best_base evaluation at its original point" +) +assert re.search( + r"base = best_base\(ctx->bases\);\s*if \(base == NULL\) \{\s*return -1;\s*\}\s*" + r"ctx->base = base;\s*ctx->bases = Py_NewRef\(ctx->bases\);\s*return 0;", + body, +), "preserve best-base validation and subsequent reference updates" +print("type_new_get_bases base C89 declaration and evaluation ordering: PASS") diff --git a/scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py b/scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py new file mode 100644 index 0000000..bbf7d2a --- /dev/null +++ b/scripts/vc6-typeobject-type-new-get-bases-index-c89.test.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +"""Regress VC6 C89 compatibility of type_new_get_bases() loop index.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new_get_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t nbases = PyTuple_GET_SIZE\(ctx->bases\);" + r"\s*Py_ssize_t i;\s*PyTypeObject \*winner;\s*PyTypeObject \*base;" + r"\s*if \(nbases == 0\)", + body, +), "type_new_get_bases: C89 loop index i must be declared before statements" +assert len(re.findall(r"\bPy_ssize_t\s+i\b", body)) == 1, "declare i exactly once" +assert re.search( + r"for \(i = 0; i < nbases; i\+\+\) \{\s*" + r"PyObject \*base = PyTuple_GET_ITEM\(ctx->bases, i\);", + body, +), "type_new_get_bases: preserve loop start, bound, increment, and base lookup" +assert not re.search(r"for\s*\(\s*Py_ssize_t\b", body), ( + "type_new_get_bases: loop initializer must reuse the declared index" +) +print("type_new_get_bases C89 loop index: PASS") diff --git a/scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py b/scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py new file mode 100644 index 0000000..f6a0c4d --- /dev/null +++ b/scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Check the mro_entries declaration and preserve base lookup ordering.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new_get_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.search( + r"for \(i = 0; i < nbases; i\+\+\) \{\s*" + r"PyObject \*base = PyTuple_GET_ITEM\(ctx->bases, i\);\s*" + r"PyObject \*mro_entries;\s*if \(PyType_Check\(base\)\)", + body, +), "type_new_get_bases: mro_entries must precede loop statements (C89)" +assert len(re.findall(r"\bPyObject\s*\*\s*mro_entries\b", body)) == 1, ( + "declare mro_entries exactly once" +) +loop = body[body.index(" for ("):body.index(" winner = _PyType_CalculateMetaclass(")] +expected = """ + for (i = 0; i < nbases; i++) { + PyObject *base = PyTuple_GET_ITEM(ctx->bases, i); + PyObject *mro_entries; + if (PyType_Check(base)) { + continue; + } + if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__), + &mro_entries) < 0) { + return -1; + } + if (mro_entries != NULL) { + PyErr_SetString(PyExc_TypeError, + "type() doesn't support MRO entry resolution; " + "use types.new_class()"); + Py_DECREF(mro_entries); + return -1; + } + } +""" +assert loop.split() == expected.split(), ( + "preserve base lookup, type skip, attribute lookup, error handling, and decref order" +) +print("type_new_get_bases mro_entries C89 declaration and lookup ordering: PASS") diff --git a/scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py b/scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py new file mode 100644 index 0000000..ead6bf7 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-get-bases-new-bases-c89.test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Check the empty-bases declaration and preserve tuple allocation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new_get_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.search( + r"if \(nbases == 0\) \{\s*PyObject \*new_bases;\s*ctx->base =", + body, +), "type_new_get_bases: new_bases must open the empty-bases block (C89)" +assert len(re.findall(r"\bPyObject\s*\*\s*new_bases\b", body)) == 1, ( + "declare new_bases exactly once" +) +assert len(re.findall(r"\bnew_bases\s*=(?!=)", body)) == 1, ( + "assign new_bases exactly once" +) +prefix = body.split("\n for (", 1)[0] +# Permit the separately tested C89 loop-index and winner declarations. +prefix = re.sub( + r"\n (?:Py_ssize_t i|PyTypeObject \*(?:winner|base));", "", prefix +) +expected = """ + Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases); + if (nbases == 0) { + PyObject *new_bases; + ctx->base = &PyBaseObject_Type; + new_bases = PyTuple_Pack(1, ctx->base); + if (new_bases == NULL) { + return -1; + } + ctx->bases = new_bases; + return 0; + } +""" +assert prefix.split() == expected.split(), ( + "preserve empty-bases guard, base assignment, tuple allocation, NULL check, " + "bases transfer, and early returns at their original evaluation points" +) +print("type_new_get_bases new_bases C89 declaration and allocation timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py b/scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py new file mode 100644 index 0000000..b4f49dc --- /dev/null +++ b/scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +"""Check winner's C89 declaration and preserve get-bases evaluation order.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new_get_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*Py_ssize_t nbases = PyTuple_GET_SIZE\(ctx->bases\);" + r"\s*Py_ssize_t i;\s*PyTypeObject \*winner;\s*PyTypeObject \*base;" + r"\s*if \(nbases == 0\)", + body, +), "type_new_get_bases: winner must be declared before statements (C89)" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*winner\b", body)) == 1, ( + "declare winner exactly once" +) +expected = """ + Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases); + Py_ssize_t i; + PyTypeObject *base; + if (nbases == 0) { + PyObject *new_bases; + + ctx->base = &PyBaseObject_Type; + new_bases = PyTuple_Pack(1, ctx->base); + if (new_bases == NULL) { + return -1; + } + ctx->bases = new_bases; + return 0; + } + + for (i = 0; i < nbases; i++) { + PyObject *base = PyTuple_GET_ITEM(ctx->bases, i); + PyObject *mro_entries; + if (PyType_Check(base)) { + continue; + } + if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__), + &mro_entries) < 0) { + return -1; + } + if (mro_entries != NULL) { + PyErr_SetString(PyExc_TypeError, + "type() doesn't support MRO entry resolution; " + "use types.new_class()"); + Py_DECREF(mro_entries); + return -1; + } + } + + + winner = _PyType_CalculateMetaclass(ctx->metatype, ctx->bases); + if (winner == NULL) { + return -1; + } + + if (winner != ctx->metatype) { + if (winner->tp_new != type_new) { + + *type = winner->tp_new(winner, ctx->args, ctx->kwds); + if (*type == NULL) { + return -1; + } + return 1; + } + + ctx->metatype = winner; + } + + + base = best_base(ctx->bases); + if (base == NULL) { + return -1; + } + + ctx->base = base; + ctx->bases = Py_NewRef(ctx->bases); + return 0; +""" +without_winner_declaration = re.sub(r"\bPyTypeObject\s*\*\s*winner;", "", body) +assert without_winner_declaration.split() == expected.split(), ( + "preserve base validation, metaclass calculation, winner dispatch, best-base " + "calculation, reference updates, and returns at their original evaluation points" +) +print("type_new_get_bases winner C89 declaration and evaluation ordering: PASS") diff --git a/scripts/vc6-typeobject-type-new-get-slots-new-slots-c89.test.py b/scripts/vc6-typeobject-type-new-get-slots-new-slots-c89.test.py new file mode 100644 index 0000000..d03fe71 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-get-slots-new-slots-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Regress type_new_get_slots' C89 local and guarded tuple conversion.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_get_slots\(type_new_ctx \*ctx, PyObject \*dict\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_get_slots definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*new_slots;\s*PyObject \*slots = PyDict_GetItemWithError\(", + body, +), "type_new_get_slots: new_slots must be in the opening declaration block (C89)" +expected = """ + PyObject *new_slots; + PyObject *slots = PyDict_GetItemWithError(dict, &_Py_ID(__slots__)); + if (slots == NULL) { + if (PyErr_Occurred()) { + return -1; + } + ctx->slots = NULL; + ctx->nslot = 0; + return 0; + } + if (PyUnicode_Check(slots)) { + new_slots = PyTuple_Pack(1, slots); + } + else { + new_slots = PySequence_Tuple(slots); + } + if (new_slots == NULL) { + return -1; + } + assert(PyTuple_CheckExact(new_slots)); + ctx->slots = new_slots; + ctx->nslot = PyTuple_GET_SIZE(new_slots); + return 0; +""" +assert body.split() == expected.split(), ( + "preserve lookup, missing-slot handling, guarded conversions, error checks, " + "and context updates" +) +print("type_new_get_slots new_slots C89 declaration and guarded conversion: PASS") diff --git a/scripts/vc6-typeobject-type-new-init-c89.test.py b/scripts/vc6-typeobject-type-new-init-c89.test.py new file mode 100644 index 0000000..dd53ad5 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-init-c89.test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Check type_new_init C89 declarations and preserve all evaluation points.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyTypeObject\*\ntype_new_init\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", + source, re.S, +) +assert match, "type_new_init definition missing" +body = match.group(1) +assert re.match( + r"\s*PyObject \*dict = PyDict_Copy\(ctx->orig_dict\);" + r"\s*PyTypeObject \*type;\s*PyHeapTypeObject \*et;\s*if\b", + body, +), "type_new_init: type and et must be in the opening declaration block (C89)" +expected = '\n PyObject *dict = PyDict_Copy(ctx->orig_dict);\n PyTypeObject *type;\n PyHeapTypeObject *et;\n if (dict == NULL) {\n goto error;\n }\n\n if (type_new_get_slots(ctx, dict) < 0) {\n goto error;\n }\n assert(!PyErr_Occurred());\n\n if (type_new_slots(ctx, dict) < 0) {\n goto error;\n }\n\n type = type_new_alloc(ctx);\n if (type == NULL) {\n goto error;\n }\n\n type->tp_dict = dict;\n\n et = (PyHeapTypeObject*)type;\n et->ht_slots = ctx->slots;\n ctx->slots = NULL;\n\n return type;\n\nerror:\n Py_CLEAR(ctx->slots);\n Py_XDECREF(dict);\n return NULL;' +assert body.split() == expected.split(), ( + "preserve dict copy, slot checks, allocation, NULL check, dict assignment, " + "heap cast, slot transfer, and error cleanup at their original evaluation points" +) +print("type_new_init C89 declarations and evaluation points: PASS") diff --git a/scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py b/scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py new file mode 100644 index 0000000..fe7a4d8 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-set-doc-doc-str-c89.test.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +"""Check only type_new_set_doc's doc_str declaration and conversion timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_set_doc\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_set_doc definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*const char \*doc_str;" + r"\s*Py_ssize_t size;" + r"\s*char \*tp_doc;" + r"\s*PyObject \*doc = PyDict_GetItemWithError" + r"\(type->tp_dict, &_Py_ID\(__doc__\)\);", + body, +), "type_new_set_doc: doc_str and size must be in the opening declaration block (C89)" +assert len(re.findall(r"\bconst\s+char\s*\*\s*doc_str\b", body)) == 1, ( + "declare doc_str exactly once" +) +assert len(re.findall(r"\bdoc_str\s*=(?!=)", body)) == 1, ( + "assign doc_str exactly once" +) +expected = """ + const char *doc_str; + Py_ssize_t size; + char *tp_doc; + PyObject *doc = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__doc__)); + if (doc == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + if (!PyUnicode_Check(doc)) { + return 0; + } + + doc_str = PyUnicode_AsUTF8(doc); + if (doc_str == NULL) { + return -1; + } + + size = strlen(doc_str) + 1; + tp_doc = (char *)PyObject_Malloc(size); + if (tp_doc == NULL) { + PyErr_NoMemory(); + return -1; + } + + memcpy(tp_doc, doc_str, size); + type->tp_doc = tp_doc; + return 0; +""" +assert body.split() == expected.split(), ( + "type_new_set_doc: preserve conversion timing, early returns, allocation, " + "and docstring copy; leave other declarations unchanged" +) +print("type_new_set_doc doc_str C89 declaration and conversion timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-set-doc-size-c89.test.py b/scripts/vc6-typeobject-type-new-set-doc-size-c89.test.py new file mode 100644 index 0000000..d1825e7 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-set-doc-size-c89.test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Check only type_new_set_doc's size declaration and calculation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_set_doc\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_set_doc definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +opening = body.split("if (doc == NULL)", 1)[0] +assert re.search(r"\bPy_ssize_t\s+size\s*;", opening), ( + "type_new_set_doc: size must be in the opening declaration block (C89)" +) +assert len(re.findall(r"\bPy_ssize_t\s+size\b", body)) == 1, ( + "declare size exactly once" +) +assert len(re.findall(r"\bsize\s*=(?!=)", body)) == 1, ( + "assign size exactly once" +) +expected = """ + const char *doc_str; + char *tp_doc; + PyObject *doc = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__doc__)); + if (doc == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + if (!PyUnicode_Check(doc)) { + return 0; + } + doc_str = PyUnicode_AsUTF8(doc); + if (doc_str == NULL) { + return -1; + } + size = strlen(doc_str) + 1; + tp_doc = (char *)PyObject_Malloc(size); + if (tp_doc == NULL) { + PyErr_NoMemory(); + return -1; + } + memcpy(tp_doc, doc_str, size); + type->tp_doc = tp_doc; + return 0; +""" +without_size_declaration = re.sub(r"\bPy_ssize_t\s+size\s*;", "", body) +assert without_size_declaration.split() == expected.split(), ( + "type_new_set_doc: preserve size calculation timing, early returns, " + "allocation and copy; leave other declarations unchanged" +) +print("type_new_set_doc size C89 declaration and calculation timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-set-doc-tp-doc-c89.test.py b/scripts/vc6-typeobject-type-new-set-doc-tp-doc-c89.test.py new file mode 100644 index 0000000..8810a12 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-set-doc-tp-doc-c89.test.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Check type_new_set_doc's tp_doc declaration and allocation timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_set_doc\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_set_doc definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*const char \*doc_str;" + r"\s*Py_ssize_t size;" + r"\s*char \*tp_doc;" + r"\s*PyObject \*doc = PyDict_GetItemWithError" + r"\(type->tp_dict, &_Py_ID\(__doc__\)\);", + body, +), "type_new_set_doc: tp_doc must be in the opening declaration block (C89)" +assert len(re.findall(r"\bchar\s*\*\s*tp_doc\b", body)) == 1, ( + "declare tp_doc exactly once" +) +assert len(re.findall(r"(?)\btp_doc\s*=(?!=)", body)) == 1, ( + "assign local tp_doc exactly once" +) +assert len(re.findall(r"\bPyObject_Malloc\s*\(", body)) == 1, ( + "allocate exactly once" +) +assert re.search( + r"size = strlen\(doc_str\) \+ 1;\s*" + r"tp_doc = \(char \*\)PyObject_Malloc\(size\);\s*" + r"if \(tp_doc == NULL\)", + body, +), "preserve allocation after size calculation and before the NULL check" +print("type_new_set_doc tp_doc C89 declaration and allocation timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py b/scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py new file mode 100644 index 0000000..56a832a --- /dev/null +++ b/scripts/vc6-typeobject-type-new-set-module-globals-c89.test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Check type_new_set_module's globals declaration and lookup timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_set_module\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_set_module definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*globals;" + r"\s*PyObject \*module;" + r"\s*int r = PyDict_Contains\(type->tp_dict, &_Py_ID\(__module__\)\);", + body, +), "type_new_set_module: globals must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyObject\s*\*\s*globals\b", body)) == 1, ( + "declare globals exactly once" +) +assert len(re.findall(r"\bglobals\s*=(?!=)", body)) == 1, ( + "assign globals exactly once" +) +expected = """ + PyObject *globals; + PyObject *module; + int r = PyDict_Contains(type->tp_dict, &_Py_ID(__module__)); + if (r < 0) { + return -1; + } + if (r > 0) { + return 0; + } + + globals = PyEval_GetGlobals(); + if (globals == NULL) { + return 0; + } + + module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + if (module == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + + if (PyDict_SetItem(type->tp_dict, &_Py_ID(__module__), module) < 0) { + return -1; + } + return 0; +""" +assert body.split() == expected.split(), ( + "type_new_set_module: preserve lookup/assignment order, early returns, " + "and the distinct module declaration" +) +print("type_new_set_module globals C89 declaration and lookup timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-set-module-module-c89.test.py b/scripts/vc6-typeobject-type-new-set-module-module-c89.test.py new file mode 100644 index 0000000..367cf06 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-set-module-module-c89.test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Check type_new_set_module's module declaration and lookup timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_set_module\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_set_module definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*globals;" + r"\s*PyObject \*module;" + r"\s*int r = PyDict_Contains\(type->tp_dict, &_Py_ID\(__module__\)\);", + body, +), "type_new_set_module: module must be in the opening declaration block (C89)" +assert len(re.findall(r"\bPyObject\s*\*\s*module\b", body)) == 1, ( + "declare module exactly once" +) +assert len(re.findall(r"\bmodule\s*=(?!=)", body)) == 1, ( + "assign module exactly once" +) +expected = """ + PyObject *globals; + PyObject *module; + int r = PyDict_Contains(type->tp_dict, &_Py_ID(__module__)); + if (r < 0) { + return -1; + } + if (r > 0) { + return 0; + } + + globals = PyEval_GetGlobals(); + if (globals == NULL) { + return 0; + } + + module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + if (module == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + + if (PyDict_SetItem(type->tp_dict, &_Py_ID(__module__), module) < 0) { + return -1; + } + return 0; +""" +assert body.split() == expected.split(), ( + "type_new_set_module: preserve lookup/assignment order, early returns, " + "and module consumption" +) +print("type_new_set_module module C89 declaration and lookup timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-slots-bases-base-c89.test.py b/scripts/vc6-typeobject-type-new-slots-bases-base-c89.test.py new file mode 100644 index 0000000..acc6b9c --- /dev/null +++ b/scripts/vc6-typeobject-type-new-slots-bases-base-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Check type_new_slots_bases's C89 declaration and post-skip cast timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic void\ntype_new_slots_bases\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_slots_bases definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +loop = body.split("for (i = 0; i < nbases; i++) {", 1)[1] +assert re.match( + r"\s*PyObject \*obj = PyTuple_GET_ITEM\(ctx->bases, i\);" + r"\s*PyTypeObject \*base;\s*if\b", + loop, +), "type_new_slots_bases: base must be in the loop's opening declaration block (C89)" +assert len(re.findall(r"\bPyTypeObject\s*\*\s*base\b", body)) == 1, ( + "declare base exactly once" +) +assert len(re.findall(r"\bbase\s*=(?!=)", body)) == 1, ( + "assign base exactly once" +) +expected = """ + PyObject *obj = PyTuple_GET_ITEM(ctx->bases, i); + PyTypeObject *base; + if (obj == (PyObject *)ctx->base) { + continue; + } + base = _PyType_CAST(obj); +""" +prefix = loop.split("if (ctx->may_add_dict", 1)[0] +assert prefix.split() == expected.split(), ( + "type_new_slots_bases: preserve item retrieval, primary-base skip, and " + "cast assignment before the first base use in their original order" +) +print("type_new_slots_bases base C89 declaration and post-skip cast timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-slots-bases-index-c89.test.py b/scripts/vc6-typeobject-type-new-slots-bases-index-c89.test.py new file mode 100644 index 0000000..66f8ca6 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-slots-bases-index-c89.test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +"""Regress VC6 C89 compatibility of type_new_slots_bases() loop index.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic void\ntype_new_slots_bases\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_slots_bases definition missing" +body = match.group(1) +assert re.match( + r"\s*Py_ssize_t nbases = PyTuple_GET_SIZE\(ctx->bases\);" + r"\s*Py_ssize_t i;\s*if\s*\(", + body, +), "type_new_slots_bases: C89 loop index i must be declared before statements" +assert re.search( + r"for\s*\(\s*i\s*=\s*0\s*;\s*i\s*<\s*nbases\s*;\s*i\+\+\s*\)", + body, +), "type_new_slots_bases: preserve loop start, bound, and increment" +assert not re.search(r"for\s*\(\s*Py_ssize_t\b", body), ( + "type_new_slots_bases: loop initializer must reuse the declared index" +) +print("type_new_slots_bases C89 loop index: PASS") diff --git a/scripts/vc6-typeobject-type-new-slots-impl-c89.test.py b/scripts/vc6-typeobject-type-new-slots-impl-c89.test.py new file mode 100644 index 0000000..2160f7a --- /dev/null +++ b/scripts/vc6-typeobject-type-new-slots-impl-c89.test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +"""Regress type_new_slots_impl C89 declaration and assignment timing.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_slots_impl\(type_new_ctx \*ctx, PyObject \*dict\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_slots_impl definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*new_slots;\s*if \(ctx->nslot > 0 && ctx->base->tp_itemsize != 0\)", + body, +), "type_new_slots_impl: new_slots must be in the opening declaration block (C89)" +assert re.search( + r'PyErr_Format\(PyExc_TypeError,\s*' + r'"nonempty __slots__ not supported for subtype of \'%s\'",\s*' + r"ctx->base->tp_name\);\s*return -1;\s*\}" + r"\s*if \(type_new_visit_slots\(ctx\) < 0\) \{\s*return -1;\s*\}" + r"\s*new_slots = type_new_copy_slots\(ctx, dict\);" + r"\s*if \(new_slots == NULL\) \{\s*return -1;\s*\}" + r"\s*assert\(PyTuple_CheckExact\(new_slots\)\);" + r"\s*Py_XSETREF\(ctx->slots, new_slots\);" + r"\s*ctx->nslot = PyTuple_GET_SIZE\(new_slots\);" + r"\s*type_new_slots_bases\(ctx\);\s*return 0;\s*$", + body, +), "preserve validation, copying, error checks, ownership transfer and secondary-base order" +assert len(re.findall(r"PyObject \*new_slots\b", body)) == 1, "declare new_slots exactly once" +print("type_new_slots_impl C89 declaration and assignment timing: PASS") diff --git a/scripts/vc6-typeobject-type-new-staticmethod-c89.test.py b/scripts/vc6-typeobject-type-new-staticmethod-c89.test.py new file mode 100644 index 0000000..04eb108 --- /dev/null +++ b/scripts/vc6-typeobject-type-new-staticmethod-c89.test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Check type_new_staticmethod's C89 declaration and guarded allocation.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_staticmethod\(PyTypeObject \*type, PyObject \*attr\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_staticmethod definition missing" +body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) +assert re.match( + r"\s*PyObject \*static_func;" + r"\s*PyObject \*func = PyDict_GetItemWithError\(type->tp_dict, attr\);", + body, +), "type_new_staticmethod: static_func must be in the opening declaration block (C89)" +expected = """ + PyObject *static_func; + PyObject *func = PyDict_GetItemWithError(type->tp_dict, attr); + if (func == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + if (!PyFunction_Check(func)) { + return 0; + } + + static_func = PyStaticMethod_New(func); + if (static_func == NULL) { + return -1; + } + if (PyDict_SetItem(type->tp_dict, attr, static_func) < 0) { + Py_DECREF(static_func); + return -1; + } + Py_DECREF(static_func); + return 0; +""" +assert body.split() == expected.split(), ( + "type_new_staticmethod: preserve lookup, guards, allocation timing, " + "dictionary insertion, decrefs, and returns" +) +print("type_new_staticmethod static_func C89 declaration and guarded allocation: PASS") diff --git a/scripts/vc6-typeobject-type-new-visit-slots-index-c89.test.py b/scripts/vc6-typeobject-type-new-visit-slots-index-c89.test.py new file mode 100644 index 0000000..465fe6b --- /dev/null +++ b/scripts/vc6-typeobject-type-new-visit-slots-index-c89.test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Regress VC6 C89 compatibility of type_new_visit_slots() loop index.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic int\ntype_new_visit_slots\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_new_visit_slots definition missing" +body = match.group(1) +assert re.match(r"\s*PyObject \*slots = ctx->slots;\s*Py_ssize_t nslot = ctx->nslot;", body), ( + "type_new_visit_slots opening locals changed unexpectedly" +) +assert re.search(r"\bPy_ssize_t i;", body), ( + "type_new_visit_slots: C89 loop index i must be declared before statements" +) +assert re.search(r"for\s*\(\s*i\s*=\s*0\s*;\s*i\s*<\s*nslot\s*;\s*i\+\+\s*\)", body), ( + "type_new_visit_slots: preserve loop start, bound, and increment" +) +print("type_new_visit_slots C89 loop index: PASS") diff --git a/scripts/vc6-typeobject-type-repr-c89.test.py b/scripts/vc6-typeobject-type-repr-c89.test.py new file mode 100644 index 0000000..e499ec5 --- /dev/null +++ b/scripts/vc6-typeobject-type-repr-c89.test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Check type_repr's C89 locals and preserve assignment/evaluation/control flow.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\ntype_repr\(PyTypeObject \*type\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_repr definition missing" +body = match.group(1) +assert re.match(r"\s*PyObject \*mod, \*name, \*rtn;\s*if\b", body), ( + "type_repr: PyObject *mod, *name, *rtn; must be in the opening declaration block" +) +assert body.count("PyObject *mod, *name, *rtn;") == 1, ( + "type_repr: declare mod, name, and rtn exactly once" +) +expected = """ + PyObject *mod, *name, *rtn; + if (type->tp_name == NULL) { + // type_repr() called before the type is fully initialized + // by PyType_Ready(). + return PyUnicode_FromFormat("", type); + } + + mod = type_module(type, NULL); + if (mod == NULL) + PyErr_Clear(); + else if (!PyUnicode_Check(mod)) { + Py_DECREF(mod); + mod = NULL; + } + name = type_qualname(type, NULL); + if (name == NULL) { + Py_XDECREF(mod); + return NULL; + } + + if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins))) + rtn = PyUnicode_FromFormat("", mod, name); + else + rtn = PyUnicode_FromFormat("", type->tp_name); + + Py_XDECREF(mod); + Py_DECREF(name); + return rtn; +""" +assert body.split() == expected.split(), ( + "type_repr: preserve all assignments, evaluation order, and control flow" +) +print("type_repr locals C89 declaration and unchanged assignment/evaluation/control flow: PASS") diff --git a/scripts/vc6-typeobject-type-vectorcall-nargs-c89.test.py b/scripts/vc6-typeobject-type-vectorcall-nargs-c89.test.py new file mode 100644 index 0000000..04f4981 --- /dev/null +++ b/scripts/vc6-typeobject-type-vectorcall-nargs-c89.test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Keep type_vectorcall's nargs declaration separate and evaluation first.""" +import re +import sys +from pathlib import Path + +source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\ntype_vectorcall\(PyObject \*metatype, PyObject \*const \*args,\n" + r"\s*size_t nargsf, PyObject \*kwnames\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_vectorcall definition missing" +body = match.group(1) +assert re.match(r"\s*Py_ssize_t nargs;\s*PyThreadState \*tstate;\s*nargs = PyVectorcall_NARGS\(nargsf\);", body), ( + "type_vectorcall: declare nargs at block entry and assign at the original first statement position" +) +assert len(re.findall(r"\bPy_ssize_t\s+nargs\b", body)) == 1, ( + "type_vectorcall: declare nargs exactly once" +) +assert re.findall(r"\bnargs\s*=(?!=)\s*([^;]+);", body) == ["PyVectorcall_NARGS(nargsf)"], ( + "type_vectorcall: evaluate nargs exactly once" +) +expected = """ + Py_ssize_t nargs; + PyThreadState *tstate; + + nargs = PyVectorcall_NARGS(nargsf); + if (nargs == 1 && metatype == (PyObject *)&PyType_Type){ + if (!_PyArg_NoKwnames("type", kwnames)) { + return NULL; + } + return Py_NewRef(Py_TYPE(args[0])); + } + /* In other (much less common) cases, fall back to + more flexible calling conventions. */ + tstate = _PyThreadState_GET(); + return _PyObject_MakeTpCall(tstate, metatype, args, nargs, kwnames); +""" +assert body.split() == expected.split(), ( + "type_vectorcall: preserve evaluation order, fast path, and fallback unchanged" +) +print("type_vectorcall nargs declaration and unchanged evaluation/control flow: PASS") diff --git a/scripts/vc6-typeobject-type-vectorcall-tstate-c89.test.py b/scripts/vc6-typeobject-type-vectorcall-tstate-c89.test.py new file mode 100644 index 0000000..e2e3d9c --- /dev/null +++ b/scripts/vc6-typeobject-type-vectorcall-tstate-c89.test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Keep type_vectorcall tstate C89-safe and its lookup on the fallback path.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\ntype_vectorcall\(PyObject \*metatype, PyObject \*const \*args,\n" + r"\s*size_t nargsf, PyObject \*kwnames\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "type_vectorcall definition missing" +body = match.group(1) +assert re.match( + r"\s*Py_ssize_t nargs;\s*PyThreadState \*tstate;" + r"\s*nargs = PyVectorcall_NARGS\(nargsf\);", + body, +), "type_vectorcall: tstate must precede statements in the opening declaration block (C89)" +expected = """ + Py_ssize_t nargs; + PyThreadState *tstate; + + nargs = PyVectorcall_NARGS(nargsf); + if (nargs == 1 && metatype == (PyObject *)&PyType_Type){ + if (!_PyArg_NoKwnames("type", kwnames)) { + return NULL; + } + return Py_NewRef(Py_TYPE(args[0])); + } + /* In other (much less common) cases, fall back to + more flexible calling conventions. */ + tstate = _PyThreadState_GET(); + return _PyObject_MakeTpCall(tstate, metatype, args, nargs, kwnames); +""" +assert body.split() == expected.split(), ( + "type_vectorcall: preserve fallback-only tstate assignment, evaluation order, and control flow" +) +print("type_vectorcall tstate C89 declaration and same-point fallback assignment: PASS") diff --git a/scripts/vc6-typeobject-vectorcall-maybe-c89.test.py b/scripts/vc6-typeobject-vectorcall-maybe-c89.test.py new file mode 100644 index 0000000..8ab5b17 --- /dev/null +++ b/scripts/vc6-typeobject-vectorcall-maybe-c89.test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Keep vectorcall_maybe declarations C89-safe and evaluation order intact.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nvectorcall_maybe\(PyThreadState \*tstate, PyObject \*name,\n" + r"\s*PyObject \*const \*args, Py_ssize_t nargs\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "vectorcall_maybe definition missing" +body = match.group(1) +assert re.match( + r"\s*int unbound;\s*PyObject \*self;\s*PyObject \*func;" + r"\s*PyObject \*retval;\s*assert\(nargs >= 1\);", + body, +), "vectorcall_maybe: all locals must precede assert in the opening declaration block (C89)" +expected = """ + int unbound; + PyObject *self; + PyObject *func; + PyObject *retval; + + assert(nargs >= 1); + + self = args[0]; + func = lookup_maybe_method(self, name, &unbound); + if (func == NULL) { + if (!PyErr_Occurred()) + Py_RETURN_NOTIMPLEMENTED; + return NULL; + } + retval = vectorcall_unbound(tstate, unbound, func, args, nargs); + Py_DECREF(func); + return retval; +""" +assert body.split() == expected.split(), ( + "vectorcall_maybe: preserve all assignments, evaluation order, and control flow" +) +print("vectorcall_maybe C89 declarations and unchanged assignment/evaluation/control flow: PASS") diff --git a/scripts/vc6-typeobject-vectorcall-method-c89.test.py b/scripts/vc6-typeobject-vectorcall-method-c89.test.py new file mode 100644 index 0000000..589c5c5 --- /dev/null +++ b/scripts/vc6-typeobject-vectorcall-method-c89.test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Keep vectorcall_method declarations C89-safe and evaluation order intact.""" +import re +from pathlib import Path + +source = Path("cpython/Objects/typeobject.c").read_text() +match = re.search( + r"\nstatic PyObject \*\nvectorcall_method\(PyObject \*name, PyObject \*const \*args, Py_ssize_t nargs\)\n\{(.*?)\n\}", + source, + re.S, +) +assert match, "vectorcall_method definition missing" +body = match.group(1) +assert re.match( + r"\s*PyThreadState \*tstate;\s*int unbound;\s*PyObject \*self;" + r"\s*PyObject \*func;\s*PyObject \*retval;\s*assert\(nargs >= 1\);", + body, +), "vectorcall_method: all locals must precede assert in the opening declaration block (C89)" +expected = """ + PyThreadState *tstate; + int unbound; + PyObject *self; + PyObject *func; + PyObject *retval; + + assert(nargs >= 1); + + tstate = _PyThreadState_GET(); + self = args[0]; + func = lookup_method(self, name, &unbound); + if (func == NULL) { + return NULL; + } + retval = vectorcall_unbound(tstate, unbound, func, args, nargs); + Py_DECREF(func); + return retval; +""" +assert body.split() == expected.split(), ( + "vectorcall_method: preserve all assignments, evaluation order, and control flow" +) +print("vectorcall_method C89 declarations and unchanged assignment/evaluation/control flow: PASS")