Skip to content

fix(update): keep restart notice and brew upgrades clear of the live session - #174

Merged
elkaix merged 2 commits into
mainfrom
fix/update-notice-and-brew-hardening
Jun 20, 2026
Merged

fix(update): keep restart notice and brew upgrades clear of the live session#174
elkaix merged 2 commits into
mainfrom
fix/update-notice-and-brew-hardening

Conversation

@elkaix

@elkaix elkaix commented Jun 20, 2026

Copy link
Copy Markdown
Member

What & why

Two update-flow UX fixes reported together.

1. Restart notice no longer crowds the prompt

The persistent "Restart to apply" / "Update available" footer line rendered directly under the input box (between the input and the status line). It now renders as the last footer row — below the status/clock line — in both toolbar layouts (_render_bottom_toolbar and _render_card_bottom_toolbar), so it stays clear of the input area. The notice reflows in at the very bottom, leaving the input and status line visually stable when it appears.

_append_update_notice now prepends its own newline and adds no trailing one (no blank bottom row), and is called last in both renderers.

2. Homebrew self-upgrade can't disrupt the live session

A silent startup self-upgrade ran brew upgrade in place mid-session. brew installs side-by-side, but its post-upgrade cleanup can delete the in-use Cellar version that the running process resolves sys.executable through — risking a crash before the user restarts. The upgrade now runs with HOMEBREW_NO_INSTALL_CLEANUP=1 and HOMEBREW_NO_AUTO_UPDATE=1 (gated to brew commands in the single _run_upgrade_command chokepoint), so the new build installs side-by-side and goes live on restart without touching the live session. The redundant implicit brew update is skipped (_refresh_brew_metadata already refreshes the tap explicitly).

Changes

  • src/pythinker_code/ui/shell/prompt.py — move notice to last footer row
  • src/pythinker_code/ui/shell/update.py — brew self-upgrade env guards
  • tests/ui_and_conv/test_prompt_tips.py — pin new notice position
  • tests/ui_and_conv/test_shell_update.py — pin brew guard env (and that non-brew upgrades are untouched)
  • CHANGELOG.md + synced docs/en/release-notes/changelog.md — two ## Unreleased entries

Verification

  • make check-pythinker-code (ruff + format + pyright + ty) — green
  • make test-pythinker-code (tests + tests_e2e) — green

Summary by CodeRabbit

  • New Features

    • Update notices now render as the final footer row below status and clock information for better visibility and layout consistency.
  • Bug Fixes

    • Homebrew self-upgrades now safely stage new builds alongside the running version and switch only on restart, protecting your active session from potential disruption during the upgrade process.

elkaix added 2 commits June 20, 2026 14:48
…session

Two update-flow UX fixes reported together.

- TUI: the persistent "Restart to apply" / "Update available" footer line
  rendered directly under the input box. It now renders as the last footer row,
  below the status/clock line, in both toolbar layouts, clear of the input.

- Homebrew: a silent self-upgrade ran `brew upgrade` in place mid-session, where
  brew's cleanup can delete the in-use Cellar version the running process resolves
  through. The upgrade now runs with HOMEBREW_NO_INSTALL_CLEANUP and
  HOMEBREW_NO_AUTO_UPDATE, so the new build installs side-by-side and goes live on
  restart without touching the live session.
CI runners export HOMEBREW_NO_AUTO_UPDATE (and sometimes
HOMEBREW_NO_INSTALL_CLEANUP), which leaked into the inherited subprocess
env and made the non-brew assertions fail. Clear them up front so the
test asserts the guard delta the code adds, not ambient state.
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e1c7a3a4-d183-4d21-a58e-5743ffa7bb31

📥 Commits

Reviewing files that changed from the base of the PR and between db323e6 and 34ce910.

⛔ Files ignored due to path filters (1)
  • docs/en/release-notes/changelog.md is excluded by !docs/**
📒 Files selected for processing (5)
  • CHANGELOG.md
  • src/pythinker_code/ui/shell/prompt.py
  • src/pythinker_code/ui/shell/update.py
  • tests/ui_and_conv/test_prompt_tips.py
  • tests/ui_and_conv/test_shell_update.py

📝 Walkthrough

Walkthrough

Repositions the "Restart to apply" / "Update available" footer notice to render as the final row in both standard and card toolbar layouts by relocating _append_update_notice call sites and changing the fragment prepend/append order. Separately, _run_upgrade_command now injects HOMEBREW_NO_INSTALL_CLEANUP and HOMEBREW_NO_AUTO_UPDATE env vars when the upgrade command starts with brew.

Changes

Update notice footer reflow

Layer / File(s) Summary
_append_update_notice fragment order and test
src/pythinker_code/ui/shell/prompt.py, tests/ui_and_conv/test_prompt_tips.py, CHANGELOG.md
Docstring updated; fragment assembly changed from appending (style, line) + trailing newline to prepending "\n" + (style, line) with no trailing blank row. Regression test replaced to assert the new last-row, bold-styled, no-trailing-newline semantics.
Call site relocation in both toolbar renderers
src/pythinker_code/ui/shell/prompt.py
Early _append_update_notice calls removed from _render_bottom_toolbar and _render_card_bottom_toolbar; new calls added after each renderer's line-2 fragment assembly completes.

Homebrew self-upgrade guard

Layer / File(s) Summary
Homebrew env injection in _run_upgrade_command
src/pythinker_code/ui/shell/update.py, tests/ui_and_conv/test_shell_update.py
_run_upgrade_command precomputes env = get_clean_env() and conditionally sets HOMEBREW_NO_INSTALL_CLEANUP=1 and HOMEBREW_NO_AUTO_UPDATE=1 before spawning the subprocess when command starts with brew. New test stubs Popen and asserts guard vars appear only for the brew invocation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • Pythoughts-labs/pythinker-code#172: Directly changes the same _append_update_notice call sites in prompt.py to render the update notice as the final footer line below the separator.

Suggested labels

bug

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows conventional commits format with valid type 'fix', clear scope 'update', and accurately describes the main changes: relocating the restart notice and adding Homebrew upgrade safety guards.
Description check ✅ Passed The description covers all required sections: related issue context, detailed explanation of both fixes, file changes, and verification results. The checklist structure is followed with clear rationale for each fix.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/update-notice-and-brew-hardening

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@elkaix
elkaix merged commit e847808 into main Jun 20, 2026
34 checks passed
@elkaix
elkaix deleted the fix/update-notice-and-brew-hardening branch June 20, 2026 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant