From 777666bf0e396e2e3d902dfbe41287ceb7c0eb99 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 8 Aug 2026 17:30:34 +0000 Subject: [PATCH 1/2] Close Item 29: chainPass confirmed true via real CI (PR #421 merge) self.layered_e2e.chain's cache-lane run against PR #421's merge (dcfce1d, run 31264219121) shows the full designed sequence firing: first hidden-import pass adds numpy then pyproj; the second dll_bundle_recover pass (Item 29's own new code) locates and bundles proj_9.dll; with HP_DLL_REPAIRED set, the second hidden_import_recover pass reaches and fixes colorama's own gap; the EXE verifies clean and exits 0. mech1Pass/mech2Pass/mech3Pass/mech4Pass and chainPass all read true for the first time -- the acceptance criterion this item was filed against, and the culmination of three successive items (24, 28, 29) each handing off to the next exactly as designed. Moves Item 29 from CLAUDE.md's Active Backlog to docs/agent-closed-backlog.md (keeping its number), and updates the now-stale "not yet confirmed" language in docs/agent-interconnect.md, docs/agent-ndjson.md, and docs/agent-lessons-learned.md. Also confirms the base HP_PYSPEC_WRITEBACK drop-to-unconstrained fix via the same run's pinDropped:true/condaSelected:true fields. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW --- CLAUDE.md | 136 ---------------------------------- docs/agent-closed-backlog.md | 91 +++++++++++++++++++++++ docs/agent-interconnect.md | 38 ++++++---- docs/agent-lessons-learned.md | 5 +- docs/agent-ndjson.md | 15 ++-- 5 files changed, 127 insertions(+), 158 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a5f8bbd4..a76121dc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -530,142 +530,6 @@ Once an item is fully resolved it is removed from here entirely and archived (ke original number) in `docs/agent-closed-backlog.md`, which is why the numbering below does not start at 1 and has gaps. -- **Item 29: `:dll_bundle_recover` never re-scans for native-DLL warnings surfaced by a LATER - `:hidden_import_recover` rebuild -- only the very first build, before any hidden-import - iteration, is ever checked.** Found via the first real CI confirmation of Item 28's own fix - (merge commit `bd5d4df3`, `cache`-lane run `31256064576`, - `~selftest_layered_e2e/~layered_e2e_bootstrap.log` and `~setup.log`). Item 28's fix is confirmed - working exactly as designed: this run's hidden-import loop correctly added - `--hidden-import=numpy --collect-submodules=numpy` (iter 1/3), then, after the next smoke run - failed with a genuine `ModuleNotFoundError: No module named 'pyproj'`, correctly added - `--hidden-import=pyproj --collect-submodules=pyproj` (iter 2/3) -- the paired-flag mechanism - fired for real, for a target (`pyproj`) never previously observed in this chain, which is - stronger evidence for the fix's general correctness than reproducing the original - `packaging.version` case verbatim (which this run did not hit at all -- plausibly because a - package-version difference in the conda solve changed pygrib's own import order; not - independently confirmed, and not important to the fix's own correctness either way). - **The NEW blocker this run hits**: the iteration-2 rebuild's own PyInstaller build log shows 9 - fresh `WARNING: Library not found: could not resolve 'proj_9.dll'` lines, one for each of - `pyproj`'s compiled extensions (`list`, `database`, `_version`, `_transformer`, `_sync`, - `_network`, `_geod`, `_crs`, `_context`) -- these `.pyd` files were never part of the bundle - before this run's `--collect-submodules=pyproj` (Item 28's own fix) pulled them in for the first - time, so this native-DLL gap could not have been detected any earlier than this exact rebuild. - The final EXE's own captured stderr confirms the runtime consequence: - `ImportError: DLL load failed while importing _context: The specified module could not be - found.` -- `mech3Pass` (`hiddenAdding`/`hiddenRecovered`, scoped specifically to `colorama`'s own - hidden-import gap) stays `false` because the chain never reaches colorama at all; `chainPass` - stays `false` for the same reason. `mech4Pass` (the `eccodes.dll` bundling Item 24 fixed) is - unaffected and still passes -- confirming this is a genuinely NEW, one-level-deeper gap, not a - regression of anything already fixed. - **Root cause**: `:dll_bundle_recover` is called exactly once, from `:run_entry_smoke` right - before the FIRST `:run_exe_smokerun` call (see `docs/agent-interconnect.md`'s "Conda native-DLL - bundling repair loop" section) -- a deliberate design choice at the time (react to a build-time - warning instead of waiting for a runtime failure, see that section's "Detects at BUILD time, not - runtime" note), but it did not anticipate a LATER rebuild -- one triggered by - `:hidden_import_recover`'s own loop, itself reacting to a runtime `ModuleNotFoundError` -- ever - introducing a NEW native-DLL warning of its own. `proj_9.dll` was never checked because the - single `:dll_bundle_recover` call already ran and exited (having found and bundled `eccodes.dll`) - long before `pyproj` was ever added to the build. - **Not yet confirmed whether `proj_9.dll` is actually locatable** the way `eccodes.dll` was - (`locate_dll()`'s double-gate requires the DLL to genuinely exist under the conda env's - `Library\bin`, searched recursively) -- very likely yes, following the same conda-forge Windows - packaging convention `eccodes.dll` already confirmed (a conda-forge `proj` package missing its - own runtime DLL would mean `pyproj` is broken for every user, not just under PyInstaller), but - the CI artifact captured for this run only covers the test's own app directory, not the shared - Miniconda installation tree, so this is inference from convention, not direct confirmation. - **Implemented 2026-08-08, option (a)**: `:run_exe_smokerun`'s flow now calls - `:dll_bundle_recover` a SECOND time immediately after `:hidden_import_recover`'s first call - returns, and, if that second call actually bundled something (a new `HP_DLL_REPAIRED` flag, - reset at `:dll_bundle_recover`'s own entry and set only in its genuine "repaired" branch -- - `HP_DLL_ITER` alone was considered and rejected as the signal, since an early "nothing - detected" return never resets it, so a stale value from an EARLIER call could look like fresh - repair activity), gives `:hidden_import_recover` one more bounded pass too -- needed because a - DLL fix can unblock a package whose OWN hidden-import gap was previously unreachable (exactly - `self.layered_e2e.chain`'s own shape: colorama's gap is only reached once `pyproj`'s DLL is - fixed). Deliberately not chained further than this one extra round each: a third pass risks an - unbounded repair cascade for a pathological dependency tree, and a case ever found needing more - is its own future backlog item, not solved speculatively here. - **Two real, cross-call state-leak bugs found and fixed while implementing this** -- both are the - same class of bug this subsystem has hit before (a fix silently dropped by a LATER rebuild that - doesn't carry it forward), just now occurring ACROSS two calls to the SAME subroutine rather - than between two DIFFERENT ones: - 1. `:dll_bundle_recover` unconditionally reset `HP_PYI_DLLBIND=` at the top of its own - per-call bundling section -- harmless for a single call, but a second call would silently - wipe the FIRST call's own accumulated `--add-binary` flags (e.g. `eccodes.dll`'s binding, - from Item 24) before the second call's rebuild ever runs. Fixed by moving this reset out to - `:run_entry_smoke`'s own fresh-build-attempt initialization (alongside the pre-existing - `HP_NUITKA_FALLBACK_USED`/`HP_DEP_MAYBE_INCOMPLETE` resets there) -- once per fresh build - attempt, not once per call. - 2. `:hidden_import_recover` had the IDENTICAL bug for `HP_PYI_HIDDEN_IMPORTS`/ - `HP_PYI_HID_COLLECT`, at BOTH its entry AND its own exit trailer -- a second call (post-DLL- - fix) would reset these to empty before its own rebuild for the NEXT hidden-import target - (e.g. colorama), silently regressing the FIRST call's own numpy/pyproj fixes back to - `ModuleNotFoundError`. Fixed the same way -- moved to the same once-per-fresh-build-attempt - reset point. - Also threaded `%HP_PYI_HIDDEN_IMPORTS% %HP_PYI_HID_COLLECT%` into `:dll_bundle_recover`'s OWN - rebuild command (previously only `%HP_PYI_DLLBIND%` reached `:hidden_import_recover`'s rebuild, - never the reverse) -- the mirror-image of the fix Item 28 already applied in the other - direction. Static regression guard added: `tests/harness.ps1`'s new - `batch.dll_bundle.second_pass` check asserts both new call sites exist, the flag-threading is - present, and -- specifically to catch a REINTRODUCED per-call reset -- the bare - `set "HP_PYI_DLLBIND="` line appears in the file EXACTLY twice (the fresh-build-attempt reset - plus `:run_entry_smoke`'s own pre-existing end-of-pass trailer) and the `HP_PYI_HIDDEN_IMPORTS`/ - `HP_PYI_HID_COLLECT` bare resets appear EXACTLY once each. - **Refined same day per a CodeRabbit review round on PR #421 (both findings addressed, both - genuinely improved the design even though the described failure mode did not reproduce in the - traced real scenario):** (1) the second `:dll_bundle_recover` call is now gated on a new - `HP_HIDDEN_REPAIRED` flag (same reset-at-entry/set-only-on-genuine-rebuild shape as - `HP_DLL_REPAIRED`) -- if `:hidden_import_recover`'s first call did NOT actually rebuild - anything, the build log has not grown since the FIRST `:dll_bundle_recover` call already - scanned it, so the second call is skipped entirely instead of always paying for a pointless - re-scan. (2) `:hidden_import_recover`'s own loop now advances `HP_LOG_SIZE_BEFORE` to right - before EACH of its own rebuilds, mirroring `:dll_bundle_loop`'s identical pattern -- narrows - the second pass's own scan window to just the LAST hidden-import rebuild's output, rather than - everything since the first DLL-bundle pass (which also covered earlier, already-resolved - rebuilds). Traced whether the ORIGINAL wider window could actually cause the failure CodeRabbit - described (re-detecting and re-bundling an already-fixed DLL, spuriously setting - `HP_DLL_REPAIRED`): confirmed it could not, in the observed real scenario -- an already-bundled - DLL's own warning does not reappear in a later rebuild that still carries its `--add-binary` - flag, and `HP_DLL_REPAIRED` is scoped strictly to a genuine "found on disk and rebuilt - successfully" branch, never to a mere re-detection. Implemented both refinements anyway since - they are still objectively more precise and defensive, and directly close a "Major" review - finding cleanly. - **A THIRD CodeRabbit finding on the same PR #421 review round, this one a genuine functional - bug (not a defense-in-depth refinement like the two above): the second `:dll_bundle_recover` - pass could never actually run when the first `:hidden_import_recover` call happened to fix the - smoke run.** The caller had `if "%HP_EXE_EXIT%"=="0" goto :smokerun_ok` immediately after the - first `call :hidden_import_recover` -- so whenever that call's own rebuild made the EXE exit 0, - execution jumped straight to `:smokerun_ok`, skipping the entire Item 29 block (the second - `:dll_bundle_recover` call and its own conditional second `:hidden_import_recover` pass) before - it ever ran. This defeats the whole premise of build-time DLL detection for exactly the - scenario Item 29 exists to catch: a hidden-import rebuild's own `--collect-submodules=X` can - surface a NEW native-DLL warning in the build log even when the CURRENT smoke run's own code - path happens not to load the DLL-needing part of `X` -- the smoke run passing does not mean the - build log has nothing left to flag, and a real user hitting a different code path later could - still crash with a `DLL load failed` error the build already warned about. Fixed by removing - that early goto entirely -- the block is already correctly self-gating (skipped when - `HP_HIDDEN_REPAIRED` is undefined, i.e. the first call did no rebuild at all) and the genuine - final success check already exists right after the whole block (`if "%HP_EXE_EXIT%"=="0" goto - :smokerun_ok`, unchanged) -- so no other logic needed to change. A companion Minor finding on - the same review caught that `tests/harness.ps1`'s own `$hiLogSizeAdvance` check (added for the - second refinement above) was a whole-file `-match`, which stayed true even if the new - `HP_LOG_SIZE_BEFORE` line inside `:hidden_import_recover` were deleted entirely, since the - identical text already exists in `:run_entry_smoke`'s initial snapshot and in - `:dll_bundle_loop` -- fixed by scoping the check to a regex-extracted `:hidden_import_recover` - body (bounded by the next label, `:warn_user_code_launch`), verified locally to flip from - true to false when the new line is removed (confirming the check is no longer vacuous). - **NOT YET CONFIRMED in real CI** -- same status this repo requires before treating a fix like - this as settled (see the Item 24/28 precedent: implemented, then confirmed via a real - `cache`-lane run before being considered closed). The next `self.layered_e2e.chain` run should - show the second `:dll_bundle_recover` pass locating and bundling `proj_9.dll`, then a second - `:hidden_import_recover` pass reaching and fixing colorama's own gap, finally flipping - `chainPass` to `true` for the first time. If it doesn't, capture the same kind of raw - per-attempt artifact this and Item 28's own investigations used - (`dist/~layered_e2e_exe.log` plus `~setup.log`'s own `WARNING: Library not found` lines) before - guessing further -- there is no guarantee a 4th layer doesn't exist beneath this one. Low - urgency either way: only affects the `cache`-lane, non-gating `self.layered_e2e.chain` test; - does not block any lane that gates PR merges. - ## Cold Storage (promising ideas, deliberately shelved -- revisit only if a named trigger fires) Moved to `docs/agent-cold-storage.md` (2026-07-31, to reduce this file's per-session context diff --git a/docs/agent-closed-backlog.md b/docs/agent-closed-backlog.md index 775191a2..b64c8817 100644 --- a/docs/agent-closed-backlog.md +++ b/docs/agent-closed-backlog.md @@ -1654,6 +1654,97 @@ this belongs to). than reopening this one, mirroring the exact same "each fix reveals the next layer" pattern that originally produced this item out of Item 24's own closure. +### Item 29 (closed 2026-08-08) + +- **`:dll_bundle_recover` never re-scanned for native-DLL warnings surfaced by a LATER + `:hidden_import_recover` rebuild -- only the very first build, before any hidden-import + iteration, was ever checked.** Found via the first real CI confirmation of Item 28's own fix + (merge commit `bd5d4df3`, `cache`-lane run `31256064576`, + `~selftest_layered_e2e/~layered_e2e_bootstrap.log` and `~setup.log`). Item 28's fix was confirmed + working exactly as designed: that run's hidden-import loop correctly added + `--hidden-import=numpy --collect-submodules=numpy` (iter 1/3), then, after the next smoke run + failed with a genuine `ModuleNotFoundError: No module named 'pyproj'`, correctly added + `--hidden-import=pyproj --collect-submodules=pyproj` (iter 2/3) -- the paired-flag mechanism + fired for real, for a target (`pyproj`) never previously observed in this chain. + **The NEW blocker that run hit**: the iteration-2 rebuild's own PyInstaller build log showed 9 + fresh `WARNING: Library not found: could not resolve 'proj_9.dll'` lines, one for each of + `pyproj`'s compiled extensions (`list`, `database`, `_version`, `_transformer`, `_sync`, + `_network`, `_geod`, `_crs`, `_context`) -- these `.pyd` files were never part of the bundle + before `--collect-submodules=pyproj` (Item 28's own fix) pulled them in for the first time, so + this native-DLL gap could not have been detected any earlier than that exact rebuild. The final + EXE's own captured stderr confirmed the runtime consequence: + `ImportError: DLL load failed while importing _context: The specified module could not be + found.` -- `mech3Pass` (`hiddenAdding`/`hiddenRecovered`, scoped specifically to `colorama`'s own + hidden-import gap) stayed `false` because the chain never reached colorama at all; `chainPass` + stayed `false` for the same reason. `mech4Pass` (the `eccodes.dll` bundling Item 24 fixed) was + unaffected and still passed -- confirming this was a genuinely NEW, one-level-deeper gap, not a + regression of anything already fixed. + **Root cause**: `:dll_bundle_recover` was called exactly once, from `:run_entry_smoke` right + before the FIRST `:run_exe_smokerun` call (see `docs/agent-interconnect.md`'s "Conda native-DLL + bundling repair loop" section) -- a deliberate design choice at the time (react to a build-time + warning instead of waiting for a runtime failure, see that section's "Detects at BUILD time, not + runtime" note), but it did not anticipate a LATER rebuild -- one triggered by + `:hidden_import_recover`'s own loop, itself reacting to a runtime `ModuleNotFoundError` -- ever + introducing a NEW native-DLL warning of its own. `proj_9.dll` was never checked because the + single `:dll_bundle_recover` call had already run and exited (having found and bundled + `eccodes.dll`) long before `pyproj` was ever added to the build. + **Implemented 2026-08-08, option (a)**: `:run_exe_smokerun`'s flow now calls + `:dll_bundle_recover` a SECOND time immediately after `:hidden_import_recover`'s first call + returns, and, if that second call actually bundled something (a new `HP_DLL_REPAIRED` flag, + reset at `:dll_bundle_recover`'s own entry and set only in its genuine "repaired" branch), + gives `:hidden_import_recover` one more bounded pass too -- needed because a DLL fix can unblock + a package whose OWN hidden-import gap was previously unreachable (exactly + `self.layered_e2e.chain`'s own shape: colorama's gap is only reached once `pyproj`'s DLL is + fixed). Deliberately not chained further than this one extra round each: a third pass risks an + unbounded repair cascade for a pathological dependency tree, and a case ever found needing more + is its own future backlog item, not solved speculatively here. + **Two real, cross-call state-leak bugs were found and fixed while implementing this** -- both + are the same class of bug this subsystem has hit before (a fix silently dropped by a LATER + rebuild that doesn't carry it forward), just now occurring ACROSS two calls to the SAME + subroutine rather than between two DIFFERENT ones: (1) `:dll_bundle_recover` unconditionally + reset `HP_PYI_DLLBIND=` at the top of its own per-call bundling section, which would have + silently wiped an EARLIER call's own accumulated `--add-binary` flags before a second call's + rebuild ever ran; fixed by moving the reset to `:run_entry_smoke`'s own once-per-fresh-build- + attempt initialization. (2) `:hidden_import_recover` had the IDENTICAL bug for + `HP_PYI_HIDDEN_IMPORTS`/`HP_PYI_HID_COLLECT`, at both its entry and its own exit trailer; fixed + the same way. Also threaded `%HP_PYI_HIDDEN_IMPORTS% %HP_PYI_HID_COLLECT%` into + `:dll_bundle_recover`'s OWN rebuild command (the mirror-image of the fix Item 28 already applied + in the other direction). Static regression guard added: `tests/harness.ps1`'s + `batch.dll_bundle.second_pass` check. + **Refined the same day per a CodeRabbit review round on PR #421** (three findings, all + addressed): (1) the second `:dll_bundle_recover` call is gated on a new `HP_HIDDEN_REPAIRED` + flag (same reset-at-entry/set-only-on-genuine-rebuild shape as `HP_DLL_REPAIRED`), skipping a + pointless re-scan when the first `:hidden_import_recover` call did no rebuild at all; (2) + `:hidden_import_recover`'s own loop now advances `HP_LOG_SIZE_BEFORE` right before EACH of its + own rebuilds, mirroring `:dll_bundle_loop`'s identical pattern, narrowing the second pass's scan + window to just the LAST hidden-import rebuild's output; (3) a genuine functional bug -- the + caller had `if "%HP_EXE_EXIT%"=="0" goto :smokerun_ok` immediately after the first + `call :hidden_import_recover`, which skipped the entire second-pass block whenever that call's + own rebuild happened to make the EXE exit 0, defeating the whole premise of build-time DLL + detection for exactly the scenario this item exists to catch. Fixed by removing that early + goto entirely (the block below is already correctly self-gated on `HP_HIDDEN_REPAIRED`, and the + genuine final success check is unchanged right after the whole block). A companion Minor + finding fixed `tests/harness.ps1`'s own `$hiLogSizeAdvance` check, which was a whole-file + `-match` that stayed `true` even if the new line inside `:hidden_import_recover` were deleted + (the identical text already exists elsewhere in the file) -- scoped to a regex-extracted + `:hidden_import_recover` body instead. + **CONFIRMED via real CI evidence (PR #421 merge commit `dcfce1d`, `cache`-lane run + `31264219121`, `~selftest_layered_e2e/~layered_e2e_bootstrap.log`), closing this item.** The + exact designed sequence fired for real, in order, all in the same run: the first + `:hidden_import_recover` call added `--hidden-import=numpy --collect-submodules=numpy` + (iter 1/3) then `--hidden-import=pyproj --collect-submodules=pyproj` (iter 2/3); the SECOND + `:dll_bundle_recover` pass (this item's own new call site) then located and bundled + `proj_9.dll` (`Bundling native DLL dependency: proj_9.dll (found at ...\Library\bin\proj_9.dll)`); + with `HP_DLL_REPAIRED` set, the SECOND `:hidden_import_recover` pass then reached and fixed + colorama's own hidden-import gap (`Adding --hidden-import=colorama --collect-submodules=colorama`); + the EXE finally verified clean (`EXE verified after hidden-import recovery`, `EXE smokerun: + exited 0 (ok)`, `[STATUS] Run Status: SUCCESS (Exit Code: 0)`). `self.layered_e2e.chain`'s + `chainPass` read `true` for the first time (`mech1Pass`/`mech2Pass`/`mech3Pass`/`mech4Pass` all + `true`), closing the acceptance criterion this item was filed against -- the full uv-to-conda + cascade, warnfix repair, hidden-import recovery, and native-DLL bundling chain all fired for + real in one run, each mechanism handing off to the next exactly as designed across three + successive items (24, 28, 29). + ## Closed Backlog - **Cascade-vs-postexec fix (Active Backlog item 9), 2026-07-25, owner-directed follow-up to a diff --git a/docs/agent-interconnect.md b/docs/agent-interconnect.md index 36c2d015..af989145 100644 --- a/docs/agent-interconnect.md +++ b/docs/agent-interconnect.md @@ -489,10 +489,11 @@ real CI run is what actually confirmed it. **Also confirmed the mech3 prediction right but not the whole story**: the EXE does get further now, but hits a NEW, deeper gap first (`pygrib`'s own extension needs `numpy`/`packaging` as hidden imports before colorama's own gap is ever reached) -- see `docs/agent-closed-backlog.md`'s Item 28 entry for the full trace of this -separately-scoped finding (closed 2026-08-08; its own fix uncovered a further, deeper gap now -tracked as CLAUDE.md's Item 29). +separately-scoped finding (closed 2026-08-08; its own fix uncovered a further, deeper gap tracked +as `docs/agent-closed-backlog.md`'s Item 29, also closed 2026-08-08). -**CLAUDE.md Item 29 (implemented 2026-08-08, not yet CI-confirmed): `:dll_bundle_recover` now +**CLAUDE.md Item 29 (implemented 2026-08-08, CONFIRMED via real CI the same day -- see +`docs/agent-closed-backlog.md`): `:dll_bundle_recover` now runs a SECOND time per fresh build attempt, after `:hidden_import_recover`'s own loop finishes -- `:run_exe_smokerun`'s flow calls it again right there, and, if that second call actually bundles something, gives `:hidden_import_recover` one more bounded pass too.** Root cause: a @@ -629,11 +630,15 @@ matching only within it, immediately preceding its `PyInstaller` rebuild line -- (via a simulated removal of the new line) that the scoped check correctly flips from `true` to `false` when the line is missing, confirming it is no longer vacuous. -**NOT YET CONFIRMED in real CI** -- needs a fresh `cache`-lane `self.layered_e2e.chain` run -showing the second `:dll_bundle_recover` pass locate and bundle `proj_9.dll`, then a second -`:hidden_import_recover` pass reach and fix colorama's own gap, before `chainPass` can be -considered proven `true` for the first time (see CLAUDE.md's Item 29 entry for the current -status). +**CONFIRMED via real CI (PR #421 merge commit `dcfce1d`, `cache`-lane run `31264219121`, +`~selftest_layered_e2e/~layered_e2e_bootstrap.log`), closing CLAUDE.md's Item 29 (now in +`docs/agent-closed-backlog.md`).** The fresh `self.layered_e2e.chain` run showed the exact +designed sequence: the first `:hidden_import_recover` call added `numpy` then `pyproj` as hidden +imports; the second `:dll_bundle_recover` pass located and bundled `proj_9.dll` +(`found at ...\Library\bin\proj_9.dll`); with `HP_DLL_REPAIRED` set, the second +`:hidden_import_recover` pass reached and fixed colorama's own gap; the EXE verified clean and +exited 0. `chainPass` read `true` for the first time (`mech1Pass`/`mech2Pass`/`mech3Pass`/ +`mech4Pass` all `true`). --- @@ -1003,13 +1008,16 @@ together: The two-variable split (`HP_PYSPEC_WRITEBACK` set once at write-back time; `HP_CONDA_PYSPEC_USE`/ `HP_CONDA_PYSPEC_SKIP` computed once at `:try_conda_create` entry, reused by both the initial -attempt and the REQ-022 transient retry) avoids re-deriving the same decision twice. **NOT YET -CONFIRMED in real CI** -- same status as the base `HP_PYSPEC_WRITEBACK` fix; needs a fresh -`cache`-lane `self.layered_e2e.chain` run to confirm `chainPass:true` before this can be considered -settled (that test's own fixture uses a Tier 3/no-constraint pyproject, so it does not by itself -exercise the `HP_PYSPEC_ORIGINAL` range-preservation path -- only the base drop-to-unconstrained -behavior; the range-preservation and quoting fix are verified by reasoning and local tooling only -so far, not a real-CI-observed range-constrained cascade). +attempt and the REQ-022 transient retry) avoids re-deriving the same decision twice. **The base +`HP_PYSPEC_WRITEBACK` drop-to-unconstrained behavior is now CONFIRMED via real CI** (PR #421 +merge commit `dcfce1d`, `cache`-lane run `31264219121`): that run's `self.layered_e2e.chain` row +shows `pinDropped:true` and `condaSelected:true` alongside `chainPass:true`, confirming the +uv-to-conda cascade re-entry genuinely dropped the write-back-derived exact pin rather than +forwarding it unconstrained to `conda create`. **The `HP_PYSPEC_ORIGINAL` range-preservation path +remains unconfirmed**, since that test's own fixture uses a Tier 3/no-constraint pyproject, so it +does not exercise a genuine user-authored range surviving the cascade -- the range-preservation +and quoting fix are still verified by reasoning and local tooling only, not a real-CI-observed +range-constrained cascade. **Why this doesn't (yet) need the same fix for the embed tier's own PYSPEC-driven version lookup**: `tools/embed_pyver_check.py` also reads `PYSPEC` to pick which pinned table entry to diff --git a/docs/agent-lessons-learned.md b/docs/agent-lessons-learned.md index df3d97e7..fd5ada04 100644 --- a/docs/agent-lessons-learned.md +++ b/docs/agent-lessons-learned.md @@ -509,10 +509,11 @@ substitute for a hazard that is Windows-only by construction. **Confirmed via re `45ec269`, `cache`-lane run `31208498606`): the fresh bootstrap log shows `eccodes.dll` genuinely located and bundled for the first time (`[REPAIR][DLL_BUNDLE] Bundling native DLL dependency: eccodes.dll (found at ...\Library\bin\eccodes.dll)...` -> `Native-DLL bundling complete`), -closing CLAUDE.md's Item 24. `chainPass` itself is still `false` on that same run, but for a +closing CLAUDE.md's Item 24. `chainPass` itself was still `false` on that same run, but for a separately-scoped reason now that this fix let the EXE get further -- see `docs/agent-closed-backlog.md`'s Item 28 entry (closed 2026-08-08, its own fix in turn uncovered -CLAUDE.md's Item 29). +Item 29, also closed 2026-08-08 -- `chainPass` was finally confirmed `true` for the first time +once Item 29's own fix merged; see that entry for the full trace). --- diff --git a/docs/agent-ndjson.md b/docs/agent-ndjson.md index b4de809e..7b85288a 100644 --- a/docs/agent-ndjson.md +++ b/docs/agent-ndjson.md @@ -305,7 +305,9 @@ close -- the bare `set "HP_PYI_DLLBIND="` line appears EXACTLY twice in the file fresh-build-attempt reset plus `:run_entry_smoke`'s own pre-existing end-of-pass trailer) and the bare `HP_PYI_HIDDEN_IMPORTS`/`HP_PYI_HID_COLLECT` resets appear EXACTLY once each. Static wiring guard only, same as `batch.dll_bundle.ndjson` -- runtime proof is `self.layered_e2e.chain`'s own -`chainPass` (`cache` lane, non-gating), not yet confirmed `true` in real CI as of this writing. +`chainPass` (`cache` lane, non-gating), CONFIRMED `true` for the first time via real CI (PR #421 +merge commit `dcfce1d`, `cache`-lane run `31264219121`) -- see `docs/agent-closed-backlog.md`'s +Item 29 entry for the full trace. ## selfapps-ux-hardening NDJSON rows (selfapps_ux_hardening.ps1, non-conda-full lanes) @@ -498,10 +500,13 @@ Item 22 for the full research trail. `eccodes.dll`-not-bundled failure this loop exists to repair, so this same test (no new flags, no new fixtures) is also this loop's Requirement 4 regression test -- see `docs/agent-interconnect.md`'s "Conda native-DLL bundling repair loop" section for the full -mechanism trace. `$mech4Pass` (`dllWarningSeen`/`dllBundling`/`dllBundleComplete`) is now required -for `$chainPass`, alongside the original three mechanisms -- this is the acceptance criterion that -should finally flip `chainPass` to `True` for the first time. NOT YET CONFIRMED in real CI as of -this note (see CLAUDE.md's Item 24 entry for current status). +mechanism trace. `$mech4Pass` (`dllWarningSeen`/`dllBundling`/`dllBundleComplete`) is required for +`$chainPass`, alongside the original three mechanisms. Item 24 (this mechanism's own first +confirmation, `eccodes.dll`) and its two successors, Item 28 (`--collect-submodules` pairing) and +Item 29 (a second `:dll_bundle_recover`/`:hidden_import_recover` pass for a DLL gap a hidden-import +rebuild surfaces later), are all closed in `docs/agent-closed-backlog.md` -- `chainPass` was +finally confirmed `True` for the first time via PR #421's merge (`cache`-lane run `31264219121`), +closing the last of the three. Asserts, mostly against `$combined` (the bootstrap stdout log plus `~setup.log`, concatenated) -- except the exact cascade COUNT (`$uvToConda`) and the warnfix-round evidence (`$warnfixRoundCount`/ From 24c634229fd164c6041f562e716bebfb221d6901 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 8 Aug 2026 17:35:10 +0000 Subject: [PATCH 2/2] Address CodeRabbit review: clarify HP_PYSPEC_WRITEBACK confirmation wording "rather than forwarding it unconstrained to conda create" was confusing -- a pin is by definition a constraint, so "forwarding it unconstrained" muddled what actually happened. Clarified to "rather than forwarding that exact pin to conda create", matching the mechanism: the fix drops the write-back-derived exact pin instead of forwarding it as-is. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW --- docs/agent-interconnect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/agent-interconnect.md b/docs/agent-interconnect.md index af989145..19e085f5 100644 --- a/docs/agent-interconnect.md +++ b/docs/agent-interconnect.md @@ -1013,7 +1013,7 @@ attempt and the REQ-022 transient retry) avoids re-deriving the same decision tw merge commit `dcfce1d`, `cache`-lane run `31264219121`): that run's `self.layered_e2e.chain` row shows `pinDropped:true` and `condaSelected:true` alongside `chainPass:true`, confirming the uv-to-conda cascade re-entry genuinely dropped the write-back-derived exact pin rather than -forwarding it unconstrained to `conda create`. **The `HP_PYSPEC_ORIGINAL` range-preservation path +forwarding that exact pin to `conda create`. **The `HP_PYSPEC_ORIGINAL` range-preservation path remains unconfirmed**, since that test's own fixture uses a Tier 3/no-constraint pyproject, so it does not exercise a genuine user-authored range surviving the cascade -- the range-preservation and quoting fix are still verified by reasoning and local tooling only, not a real-CI-observed