Repository navigation
fix(launcher): read deps entry owners from the scratch RECORD files (#575) - #577
Conversation
…575) The idempotence guard derived an entry's distribution from its name, so every entry named differently from its distribution (yaml, sklearn, google, bin, the shared __pycache__, ...) was replaced on every install. It now reads each entry's owners from the scratch install's RECORD files and skips the entry only when every owner is already at the resolved version and the entry is still present (ADR-1064). Measured on an APFS clone of a live 4.22.0 deps directory: 27 of 213 entries replaced before, 0 after, tree byte-identical to the original. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
91ee077 to
17dcc87
Compare
|
ZETETIC-REVIEW: REQUEST_CHANGES Stakes: High (PR size 514 additions/16 deletions across 9 files, over the 400-line threshold; touches the bootstrap installer path every Blocking
Verified correct (no defect found)
Non-blocking
Minimum change to unblock mergeExtract enough of |
…ved_entries (#575) The owners lookup pushed _commit_resolved_entries to 43 AST lines, over the craftsmanship gate's 40-line method limit when run with --base origin/main. The dist-info and foreign-ABI pruning now lives in _prune_after_full_commit, called at the same point, behaviour unchanged. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
|
ZETETIC-REVIEW: APPROVE Re-review of commit 8764e29 on top of the previously reviewed 17dcc87 (review comment #5688590477, REQUEST_CHANGES, blocking on the craftsmanship method-size gate). Diff since 17dcc87Only Gate: craftsmanship (the blocking finding from the prior review)Matches the expectation exactly: 17dcc87 fails with the same Gate: ruffGate: tests_py/scriptsBase currency
Other
Verdict: the previously-blocking craftsmanship violation is resolved without weakening the gate or moving logic off the failure-safe path. APPROVE. |
Closes #575.
Problem
_entry_already_satisfied(scripts/launcher_deps_install.py) derived an entry's distribution from the entry's name. Any entry named differently from its distribution had no version, so every install replaced it:yaml,_yaml,sklearn,attr,dateutil,jwt,fitz,google,functorch,torchgen, the shared__pycache__,bin,include,share. Since #576 both installers take this path.Change
scripts/launcher_deps_record.py(new, stdlib only):entry_owners(dir)maps each top-level entry to the dist keys whoseRECORDlists a path under it.pip --targetrecords console scripts as../../bin/<name>, and those rows count forbin(pip 26.0.1_handle_target_dir,posix_homepurelib{base}/lib/python)._entry_already_satisfiednow needs all of these to hold: at least one owner; every owner indeps/at the resolved version; the entry still present indeps/; no foreign-ABI extension (ADR-1061, unchanged). An entry that noRECORDlists is always replaced.docs/adrmirror + manifest) and a CHANGELOG entry.Evidence
Measured on an APFS clone of the maintainer's live 4.22.0 deps directory (213 top-level names, Python 3.14.4, macOS 26), running
python3 scripts/launcher_deps.py --requirement requirements/setup.txt <clone>:.pycentry_ownerson that directory: 36–38 ms over five warm runs. Every one of its 211 entries has at least oneRECORDowner. The only names without one are the two.cortex-deps-stamp-*.jsonfiles.Tests:
tests_py/scripts/test_installer_rerun_keeps_entries.pyruns real pip offline through the installers' entry point against locally built wheels.cortexprobe-yamlshipsprobeyamlplus a console script, andcortexprobe-ns-a/-ns-bshare theprobensnamespace. It asserts four things: a same-version re-run keeps every inode; bumpingns-breplacesprobens(keeping both halves) but notprobeyamlorbin; bumpingcortexprobe-yamlreplacesprobeyamlandbinbut notprobens; and a deleted entry is restored under matching metadata.lexistscheck removed, the three restore cases fail.tests_py/scripts/test_launcher_deps_record.py:record_top_levelrow shapes, multiple owners, missing or undecodableRECORD, guard truth table._make_dist_infointest_launcher_deps.pynow writes aRECORD, as pip always does.Local gates: full suite 8661 passed / 8 skipped,
ruff checkandruff format --checkat 0.16.6,check_craftsmanship.py --base origin/main(the first head, 17dcc87, failed it:_commit_resolved_entriesspanned 43 lines; 8764e29 moves the post-commit pruning into_prune_after_full_commit),check_project_wiki.py,check_no_deps_invariant.py.Not changed (recorded in ADR-1064): when a shared entry is not satisfied, its scratch copy still replaces the whole entry. A partial launcher install whose scratch does not include every owner in
deps/therefore drops those owners' files. The old guard did this on every run; this one does it only when a scratch owner changed.🤖 Generated with Claude Code