Skip to content

fix: close uninstall host integration recovery gaps - #2226

Merged
backnotprop merged 7 commits into
backnotprop:mainfrom
utpalsinghdev:fix/1179-uninstall-host-recovery
Oct 31, 2026
Merged

backnotprop merged 7 commits into
backnotprop:mainfrom
utpalsinghdev:fix/1179-uninstall-host-recovery

Conversation

@utpalsinghdev

Copy link
Copy Markdown
Contributor

Summary

Uninstall can miss hooks customized with options such as plannotator --browser Safari, leaving them pointing at a deleted binary. Recovery guidance for a missing host CLI also assumes the host will be installed again.

This change:

  • Recognizes supported hook options without removing unrelated or composite user commands.
  • Blocks binary removal while recognized hook or Inbox MCP references remain, with the exact file, field, and cleanup instructions.
  • Offers both recovery routes for a missing host CLI: restore it, or manually remove the detected Plannotator entry and retry.
  • Reports deterministic blockers during dry-run using the original configuration locations.
  • Checks VS Code registration separately from extension directories left behind after a successful uninstall.

Unrelated hooks and settings are preserved. Normal uninstall still keeps review data, and purge retains its existing deletion boundary.

Closes #1179.

Verification

Latest full test run on Bun 1.4.4:

  • bun test: 10,565 passed, 2,841 skipped, 8 failed.

This branch does not yet include the companion compatibility changes merged in #2215. The failures cover filesystem watching, tailnet behavior, session shutdown, port handling, and event streams; the full run is not green.

Before the runtime upgrade:

  • Focused uninstall, Inbox connection, CLI, and auto-update tests passed: 210 passed, 2 Windows-only tests skipped.
  • bun run typecheck passed.
  • bun run build:review && bun run build:hook && bun run build:opencode passed.
  • Linux, macOS arm64, and Windows x64 CLI builds passed.
  • Compiled CLI checks verified cleanup, blocked removal, manual cleanup and retry, dry-run locations, permission failures, and data preservation.
  • Compiled Inbox integration tests passed: 34 tests.
  • Verified the macOS binary against VS Code 1.104.1 using isolated configuration. Uninstall succeeded while the unregistered extension directory remained.

Those focused checks and builds have not been rerun on Bun 1.4.4. The earlier full DOM run had one rich-copy timing failure; the affected test file passes alone. Native Windows execution and Docker-backed security checks remain unverified.

utpalsinghdev and others added 6 commits October 27, 2026 07:46
Keeps both the host-recovery checks and the Qwen Code uninstall work
(backnotprop#2271-backnotprop#2275). The Qwen extension action uses the new references form.
Follows up on utpal singh's fix for backnotprop#1179.

- A config uninstall can't read still keeps the CLI, but the error names
  the file, the tool that owns it, why it couldn't be read, that
  Plannotator did not change it, and what to do next (over the size cap:
  quit the tool, move the file aside, rerun, move it back). Each file is
  reported once.
- A plannotator-inbox entry no record says Plannotator added is a
  warning again, never a reason to keep the CLI, with how to remove it
  (`claude mcp remove plannotator-inbox -s user` for ~/.claude.json).
- Claude Code and Droid: only the user scope decides. A project's or a
  managed install is named with its own uninstall command, never waited
  for, so a retry never asks the host to remove a user install that is
  gone.
- An unquoted install path with spaces (install.sh's Codex hook) matches
  exactly again.
- Vibe's hooks.toml parse errors say what is wrong; surviving hooks are
  one error per file.
- The dry-run test writes its Vibe path as a TOML string, which fixes the
  Windows job.
- Test groups are named after what they test; docs describe the new
  blocking cases.
- Vibe's hooks.toml is parsed before anything is written, in a real run
  too: one that is not valid TOML is left byte for byte, block included.
- A user enabledPlugins key with no user install in installed_plugins.json
  never asks the host to uninstall (it would refuse every run); it is
  named, with `claude plugin disable ... --scope user` for Claude Code.
- An agent file over the Inbox's size cap is read in full once: one that
  never names plannotator-inbox passes, ~/.claude.json is parsed and
  checked as usual (its entry is a warning), another agent's that names
  it says how to remove the entry. No more "move the file aside".
…big agent files in full

- Reverts the a07b912 shortcut that skipped `claude plugin uninstall`
  for a user enabledPlugins key with no user install: Claude Code
  installs (or rescopes) the plugin for the user from that key at its
  next start, so it keeps the CLI. If the host refuses, the error names
  the key to remove by hand, and the retry passes.
- The uninstall check reads each agent file with its own parser up to
  512 MiB instead of the Inbox's 1 MiB / 32 MiB caps, so a big file is
  checked like any other and never blocks for its size.
@backnotprop backnotprop added the ci:full Run the heavy CI tier on this PR (added by the merge script) label Oct 31, 2026
… scan; working Copilot command

- The after-cleanup hook check runs in every real run, even after another
  error, so one run names every blocker. A file uninstall could not rewrite
  or remove is said once (its write error), not also as a surviving hook.
- The plannotator-inbox scan writes nothing, so it reads every agent's JSON
  with comments and trailing commas (Cursor, Kiro, the Claude app). A
  commented mcp.json the person never connected no longer keeps the CLI.
- A file over 1 MiB is searched raw, a chunk at a time, for
  "plannotator-inbox" before anything is decoded; without it, it is skipped.
  With it, it is parsed up to 64 MiB; a bigger one is a warning that says
  so, never a blocker. Replaces the 512 MiB full read.
- Copilot: `copilot plugin uninstall plannotator-copilot@plannotator`
  (Copilot CLI 1.0.68 refuses `plugins remove ... --plugin`), run and printed.
- An unreadable Codex config.toml / hooks.json, OpenCode config, Gemini
  settings.json, Kiro agent or Amp plugin gets the same wording as the
  others: file, owning tool, why, that Plannotator did not change it, and
  what to do next.

Follow-up to utpalsinghdev's backnotprop#2226.
@backnotprop
backnotprop merged commit 017d71e into backnotprop:main Oct 31, 2026
56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full Run the heavy CI tier on this PR (added by the merge script)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Close remaining uninstall host-integration recovery gaps

2 participants