Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 0 additions & 136 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading