Skip to content

chore(upstream): sync upstream main#1

Merged
stwgabriel merged 60 commits into
mainfrom
codex/sync-upstream-main
May 13, 2026
Merged

chore(upstream): sync upstream main#1
stwgabriel merged 60 commits into
mainfrom
codex/sync-upstream-main

Conversation

@stwgabriel

Copy link
Copy Markdown
Owner

Summary

  • Merge upstream/main into the fork sync branch
  • Resolve conflicts while keeping Moleui-specific README and stwgabriel/moleui release URLs
  • Bring over upstream cleanup, uninstall, checksum, and test updates

Tests

  • ./scripts/test.sh
    • shellcheck skipped: not installed
    • bats skipped: not installed or no tests found
    • Go, module loading, integration, and installation checks passed

sebastianbreguel and others added 30 commits May 9, 2026 21:58
…w93#854)

* feat(uninstall): add per-file deselect at confirm prompt (tw93#852)

Press R at the uninstall confirm prompt to open a review picker that lets
you opt OUT of individual paths -- preferences, caches, system plists, or
the .app bundle itself. Deselecting the .app keeps the bundle on disk and
only cleans the leftover files. Reuses the existing paginated_multi_select
UI; no new flag, no new command, no config knob.

Closes tw93#852.

* style(uninstall): re-indent keep_app block, drop bandage comment

Pure indentation cleanup of the `if [[ "$keep_app" != "true" ]]` block
introduced for tw93#852. Body now indents one level inside the gate so future
readers see the scope correctly. Drops the `# end if keep_app != true`
comment that was masking the missing indent.

Zero behavior change. All uninstall tests green.

* test(uninstall): satisfy shellcheck SC2016/SC2181 in review_files bats
Route sudo-required uninstall paths into the invoking user's Trash without calling sudo trash. The trash location follows the effective user, so running the trash CLI under sudo moves large app bundles into /var/root/.Trash, where macOS accounts for them as System Data instead of the real user's Trash.

For paths that need admin rights, resolve the invoking user's home defensively, reject unsafe root homes, create or reuse ~/.Trash with user ownership and 700 permissions, refuse symlinked or non-directory Trash paths before privileged writes, sanitize destination names, handle conflicts with timestamp/PID/suffix names, and use sudo mv -n for the single privileged operation. After a successful move, repair ownership on the moved item on a best-effort basis so restored Trash items behave like user files.

Keep the existing permanent-delete fallback when Trash routing fails, so uninstall still completes instead of silently skipping selected files. Normal user-owned paths continue to prefer the trash CLI and then Finder/AppleScript.

Add regression tests with fake trash, sudo, and osascript binaries to verify sudo-required Trash deletes use sudo mv -n into the invoking user's Trash, reject symlinked Trash directories, handle destination conflicts with unique names, and never call sudo trash, trash, or osascript for sudo-required paths.

Validation: bash -n lib/core/file_ops.sh; bats tests/file_ops_mole_delete.bats; scripts/test.sh passed with 756 tests, 0 failures, 15 skipped. Go tests were skipped because Go is not installed; shellcheck was skipped because shellcheck is not installed.
Pin stable updates to the resolved release tag and require downloaded Go helpers to match the release SHA256SUMS before installing.
Record optimize sudo availability once and make sudo-required tasks skip cleanly when access is denied or tests run in no-auth mode.
Avoid collecting sensitive developer data, validate bundle identifiers before path matching, and keep user-owned ByHost cleanup off sudo.
Collapse the seven-emoji icon zoo into two: 📁 for top-level
directories, 👀 for hidden-space insights. The previous mix of
📋 💾 🔨 📲 🐳 📱 📥 varied in render width across terminals
and added no information. A broom (🧹) was tried first but
mis-signalled "all of these are cleanable", which is wrong for
Xcode Archives, iOS Backups, and Old Downloads.

Rename App Library to User Library to mirror System Library
and avoid confusion with /Applications. Path unchanged.
write_install_channel_metadata used `[[ -n "$h" ]] && printf ...` to
optionally append the commit hash. On the stable channel the hash is
always empty, so the conditional returned 1 and propagated as the
exit code of the surrounding `{ ... } > "$tmp_file"` block, which the
caller then read as an I/O failure and warned "Could not write install
channel metadata". The metadata file was never written.

Switch to a plain `if [[ -n "$h" ]]; then printf ...; fi` so only an
actual write failure can trip the warning. Add a regression test in
tests/install_checksum.bats covering both the stable empty-hash path
and the nightly hash-present path.
tw93 and others added 27 commits May 11, 2026 19:07
Co-authored-by: unnipv <unnimonpv@gmail.com>
Adds per-file selection before uninstall removal and preserves deletion-side effects only for files the user kept selected.\n\nMaintainer patch: rebuild sudo/brew prompts after selection and cover leftover-only deselection.
Discovers app-related Group Containers through the signed Team ID plus bundle-domain prefix, keeps same-Team unrelated containers out, and broadens diagnostic report matching.\n\nMaintainer patch: rebased on the file selector flow and narrowed Team ID discovery before merge.
Preserve Gradle DSL hash cache integrity by normalizing file-level cleanup targets to the containing hash directory.

Verification:
- ./scripts/check.sh --format
- MOLE_TEST_NO_AUTH=1 bats tests/regression.bats tests/clean_dev_caches.bats
- MOLE_TEST_NO_AUTH=1 MOLE_TEST_JOBS=2 BATS_FORMATTER=tap ./scripts/test.sh
Harden uninstall scanning against PATH stat shims, avoid GUI-app-owned dotdir false positives, and add explicit zero-size purge artifact visibility.

Also relax the normalize_paths_for_cleanup performance regression test threshold to avoid CI runner timing noise while still catching O(n²) regressions.

Verification:
- ./scripts/check.sh --format
- MOLE_TEST_NO_AUTH=1 bats tests/uninstall_scan_bash32.bats tests/clean_hints.bats tests/purge.bats tests/completion.bats
- MOLE_TEST_NO_AUTH=1 bats tests/regression.bats
- go test ./cmd/...
- MOLE_TEST_NO_AUTH=1 MOLE_TEST_JOBS=2 BATS_FORMATTER=tap ./scripts/test.sh
… or cask exists (tw93#872) (tw93#879)

* fix(clean): skip orphan hint for dotdirs owned by GUI app or cask (tw93#872)

`show_orphan_dotdir_hint_notice` now adds a fifth ownership gate that
exempts a hidden home directory when an installed `.app` bundle or a
Homebrew cask shares a name token with it.

Without this, `~/.bridge` (Proton Mail Bridge live data) is flagged as
orphan because there is no `bridge` binary on PATH and no LaunchAgent
referencing it. The existing gates (allowlist, whitelist, `command -v`,
LaunchAgents grep) only cover CLI-style owners.

New helper `dotdir_has_owning_gui_app NAME`:

  - Scans `.app` filenames in /Applications, /Applications/Setapp,
    \$HOME/Applications, plus `brew list --cask` output.
  - Tokenizes both sides on non-alphanumeric chars, lowercases.
    `Proton Mail Bridge.app` -> proton, mail, bridge.
    `proton-mail-bridge`     -> proton, mail, bridge.
  - Requires token length >= 4 on both sides to avoid matching
    `.ai-old` against `AI.app`.
  - Caches the token list at
    \$HOME/.cache/mole/installed_app_tokens_cache (5-minute TTL,
    same pattern as scan_installed_apps).

The new gate is inserted between the LaunchAgents grep and the size
calculation in `show_orphan_dotdir_hint_notice`.

Tests in tests/clean_hints.bats cover:

  - dotdir matched by fake .app -> not flagged
  - dotdir matched by fake brew cask -> not flagged
  - dotdir with no matching app/cask -> still flagged
  - short app tokens (<4 chars) do not exempt the dotdir

* fix(clean): use POSIX character classes in tr (shellcheck SC2018/SC2019)

Replace `tr 'A-Z' 'a-z'` with `tr '[:upper:]' '[:lower:]'` in the
helpers added by the previous commit. The locale-aware form is what
shellcheck and the repo's check.sh require.
- merge upstream/main into origin main sync branch
- resolve fork-specific Moleui URLs and README conflicts
- preserve upstream uninstall and checksum fixes

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf9d61fa39

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/uninstall/batch.sh

MOLE_SFR_USER_FILES="$_fs_all_user"
MOLE_SFR_SYSTEM_FILES="$_fs_sys"
if ! select_files_for_removal "$_fs_an"; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bypass file picker for non-interactive uninstall

When uninstall is launched without a TTY, this new selector still runs before the later dry-run/non-interactive confirmation bypass. The desktop app calls mole uninstall --dry-run --yes ... and mole uninstall --yes ... from apps/desktop/main.js via spawn, which provides a piped stdin and no terminal; _sfr_multi_select then waits in read_key for input that never arrives, so the desktop dry-run/execute flow hangs before removing or previewing anything. Non-interactive callers with closed stdin instead skip all selected apps. Please auto-select the preselected files or skip this menu when ! -t 0 || ! -t 1/--yes/dry-run GUI mode is in effect.

Useful? React with 👍 / 👎.

@stwgabriel stwgabriel merged commit 767ccab into main May 13, 2026
2 checks passed
@stwgabriel stwgabriel deleted the codex/sync-upstream-main branch May 13, 2026 19:22
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.

9 participants