fix(update): untrack the python/tetra3 symlink so git pull can update fielded units - #640
Merged
Merged
Conversation
… fielded units Tracking the symlink (v2.6.0, 0a8262f) made `git pull` refuse to update any unit that already had an untracked python/tetra3 on disk: the absolute symlink created by migration_source/v2.1.0.sh, or a plain folder left over from the 2.2.2 era. git's refusal is path-level — even a byte-identical symlink blocks the pull — so every unit upgraded in place stalled at <= 2.5.1, while pifinder_update.sh ignored the exit code and printed "update complete" anyway. A stuck unit runs its old copy of pifinder_update.sh, so the fix has to make the pull itself succeed; the only new code such a unit executes is pifinder_post_update.sh, sourced fresh from disk after the pull. - Untrack + gitignore python/tetra3. pifinder_setup.sh, CI (nox.yml, web-integration-tests.yml) and fresh clones create it explicitly; `import tetra3` resolves the solver package through it. - pifinder_post_update.sh moves anything else at that path aside to ~/tetra3_old_<timestamp> (kept, not deleted) and (re)creates the relative link on every update. The `ln -s` in v2.1.0.sh — source of the absolute links — is removed. - pifinder_update.sh exits non-zero on a failed pull and says FAILED; sys_utils.update_software() catches it and returns False, making the UI's existing "Error on Upd" branch reachable. - ADR 0035 records the decision (0034 is reserved by PR #639). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RbVpv53CQuxiNF9JHzDQtz
brickbots
marked this pull request as ready for review
August 28, 2026 16:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The failure
Units upgraded in place cannot update past 2.5.1, and every attempt reports success. Chain of events:
migration_source/v2.1.0.shcreatedpython/tetra3on every updated unit as an absolute symlink via bareln -s(on 2.2.2-era cards with a plain tetra3 folder already there, the link landed inside the folder instead).0a8262fa) started tracking the symlink (relative form) so CI could import tetra3.git pullrefuses to write a tracked path over any untracked file — verified empirically, even a byte-identical symlink blocks it. So the pull to ≥ 2.6.0 aborts on every in-place-upgraded unit. Only fresh clones/images updated cleanly.pifinder_update.shignored the exit code and printed "PiFinder software update complete" anyway.The trap: a stuck unit runs its old
pifinder_update.sh, so no new pre-pull guard can reach it. The only new-release code it executes ispifinder_post_update.sh, sourced fresh from disk after a successful pull. The pull must therefore succeed first — which means git has to stop needing to writepython/tetra3.The fix
python/tetra3. The release tree no longer touches the path, so whatever a unit has there can't block the pull.pifinder_post_update.showns the symlink: anything at that path that isn't the relative link is moved aside to~/tetra3_old_<timestamp>(kept, not deleted — same philosophy as the manual SSH fix), then the link is (re)created. Runs on every update, so it also self-heals. Theln -sinv2.1.0.sh(source of the absolute links) is removed.pifinder_update.shexits non-zero with a FAILED message on a failed pull;sys_utils.update_software()catches it and returnsFalse, so the UI shows its (previously unreachable) "Error on Upd" instead of "Ok! Restarting".import tetra3resolves the package through it; thesys.pathappend only exposes the package contents), so every tree-materialising path now creates it:pifinder_setup.sh,nox.yml,web-integration-tests.yml, and by hand in dev clones (CLAUDE.md updated).Once this ships in a release, a stuck unit is rescued by one ordinary menu update — no SSH: the old script's pull succeeds against the new tree, it sources the new post-update from disk, and the repair block replaces the leftover folder/absolute link.
Verification
pifinder_update.shwith an unreachable remote: exits 1, prints FAILED, never prints "complete".set -ein all four states.pytest -m smoke(5 passed),pytest -m unit(1526 passed),ruff check/format,mypy PiFinder/sys_utils.pyclean.import tetra3finds the innertetra3.pymodule and collection fails — hence the setup/CI creation steps.🤖 Generated with Claude Code
https://claude.ai/code/session_01RbVpv53CQuxiNF9JHzDQtz