Skip to content

session: the uv-tool repair belongs to the hook, not the bootstrap - #363

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/organ-remote-block-and-uv-hook-repair
Aug 27, 2026
Merged

session: the uv-tool repair belongs to the hook, not the bootstrap#363
Jammy2211 merged 1 commit into
mainfrom
feature/organ-remote-block-and-uv-hook-repair

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

Two halves of the 2026-08-27 mobile-workflow pass that were, by construction, only half-rolled-out — the session that shipped them could attach only two of the four organs. Closes the second half here; the first half (Heart and Hands opting into the generated remote-session block) ships in their own PRs.

repair_uv_tools shipped in scripts/session_bootstrap.sh. That is the wrong home. The bootstrap is what a multi-repo session runs, because that session registers no SessionStart hook and has no other door. A single-repo session is the mirror image: the hook fires, nothing calls the bootstrap. It got leg 2's breakage — the /usr/local/bin/python3 wrapper that every uv tool env symlinks to — and none of the repair, so mypy, flake8, black, poetry and pyright all died with ModuleNotFoundError naming themselves, in the ordinary single-repo case.

Moved into policy/session_start_hook.sh as leg 3b, called right after retool_uv_tools. Two paths reach that breakage, not one: leg 3 rebuilds a 3.11 tool and hands the new env the hijacked path, and leg 2 separately breaks every pre-existing tool env that already pointed there and that leg 3 skips (is_py312 … && continue). Running after leg 3 covers both, because leg 2 runs before it.

API Changes

None — no public Python API is touched. Two shell contracts change, both internal to the session machinery:

  • policy/session_start_hook.sh gains a --repair-uv-tools argv seam (previously took no arguments) and calls repair_uv_tools in its main flow.
  • scripts/session_bootstrap.sh no longer defines repair_uv_tools; its own --repair-uv-tools seam and its trailing call now forward to the hook as subprocesses. The --check leg is unchanged.

See full details below.

Test Plan

  • python3 -m pytest -q in PyAutoMind — 271 passed
  • The four new tests fail on exactly the bug when the flow call is removed:
    assert '/tmp/…/session' == '/tmp/…/tools/widget'
  • repos_sync.py --check --root <four-organ scope> — all 14 legs OK
  • All four organs' hook copies byte-identical to the canonical
  • Sibling suites green: PyAutoBrain 584, PyAutoHeart 656, PyAutoHands 430

Hardening the move required

The hook runs set -euo pipefail; the bootstrap ran set -u only. Three things would have failed the whole session start, silently, in a script whose contract is that every leg "degrades to a logged warning":

  • base="$(… 2>/dev/null)" — a failing command substitution in an assignment aborts under set -e
  • the post-repair prefix="$(…)" — same
  • ln -sfn itself, on an unwritable tools dir — now warns and continues

Scope: this does not clean up the long tail

write_session_hooks iterates the whole manifest, so the hook is generated into 34 repos, not four. Thirty of those copies are a pass behind and two carry none at all — a state that predates this PR and that no gate sees, because firewall_gate.yml checks out exactly the four organs and skips absent repos. Heart sees it (manifest drift: session-start hooks (generated) — 34 mismatch(es)), CI does not.

This PR regenerates the four organs — the set CI actually gates — and leaves the count where it found it. The propagation is filed separately as draft/maintenance/organs/session_hook_reaches_only_four_of_thirty_four_repos.md, since it would mean PRs against every library, workspace, HowTo and assistant repo.

Full API Changes (for automation & release notes)

Added

  • policy/session_start_hook.sh --repair-uv-tools — runs leg 3b alone, without a session start. Honours PYAUTO_UV_TOOLS_DIR and PYAUTO_SESSION_VENV.
  • repair_uv_tools() in policy/session_start_hook.sh (leg 3b), called from the main flow after retool_uv_tools.

Removed

  • repair_uv_tools() from scripts/session_bootstrap.sh — moved, not deleted.

Migration

  • None for callers. bash PyAutoMind/scripts/session_bootstrap.sh --repair-uv-tools still works and still repairs; it now forwards to the hook.

Closes part 2 of #360.

Generated by the PyAutoLabs agent workflow.

`repair_uv_tools` shipped in scripts/session_bootstrap.sh, which is what a
MULTI-repo session runs — that session registers no SessionStart hook, so the
bootstrap is its only door. A SINGLE-repo session is the mirror image: the hook
fires and nothing calls the bootstrap. It got leg 2's breakage (the
/usr/local/bin/python3 wrapper every uv tool env symlinks to) and none of the
repair, so mypy, flake8, black, poetry and pyright all answered
ModuleNotFoundError naming themselves, in the ordinary case.

Moved to policy/session_start_hook.sh as leg 3b, called right after
retool_uv_tools. Two paths reach the breakage, not one: leg 3 rebuilds a 3.11
tool and hands the new env the hijacked path, and leg 2 separately breaks every
pre-existing tool env that already pointed there and that leg 3 skips. Running
after leg 3 covers both, because leg 2 runs before it.

Hardened for the move: the hook runs `set -euo pipefail` and the bootstrap only
`set -u`, so two command substitutions would have aborted the session start, and
a failing `ln -sfn` on an unwritable tools dir would have killed it outright.
Every leg here is contractually non-fatal; these are now too.

The bootstrap keeps both call sites, forwarding to the hook as a subprocess so
the hook's `set -e` never leaks into a script that is a bootstrap and never a
gate. Its --check leg is unchanged.

Tests: the section-7 tests keep driving the bootstrap seam, which is now a
forward — that is what proves the forward works. Four new: the leg through the
hook, the healthy-env no-op, the unwritable-dir warning path, and an end-to-end
run of the hook as the harness runs it, which fails on exactly this bug when the
flow call is removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pending-release Awaiting coordinated release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant