Skip to content

refactor(upgrade): remove package-manager metadata emulation and replace its simulated tests with delegation coverage #1060

Description

@ScriptedAlchemy

Priority: P2 architectural deletion and test quality. This requests an explicit installation-ownership policy; it is not a claim that changing managed channel-switch behavior is an invisible refactor.

Verified production paths

At #707 3d955ff998eef120cd398f163c613a54e3383ccb, crates/tracedecay-cli/src/upgrade.rs has two incompatible Homebrew ownership models:

  • Ordinary run_upgrade selects run_brew_upgrade, invoking the actual manager and inspecting its installed binary.
  • switch_channel instead fetches a GitHub asset and calls perform_upgrade with the detected install method. For Brew that reaches replace_for_brew: directly replace the Cellar executable, rename the version directory, remove/recreate the stable symlink, then rewrite INSTALL_RECEIPT.json using raw text replacement. Therefore the custom Brew branch is live, not dead code safely removable without a replacement/refusal decision.

Scoop uses GitHub binary replacement even for ordinary upgrades. update_scoop_metadata copies the old version's files into a new directory, rewrites version occurrences in manifest.json, removes current, and invokes cmd /c mklink /J. It is reimplementing part of the package manager's install state. A failure after deleting a link/junction is not merely a cosmetic stale version, and rewriting version strings cannot establish a manager-authored package receipt.

Delete, do not grow another transaction framework

Use one owner for managed installation state. Delegate supported operations to that package manager through the existing bounded process/lifecycle boundary. When a requested beta/stable transition has no supported managed package/channel, return an explicit pre-mutation unsupported outcome, or provide a separately authorized direct installation outside the manager-owned tree. Preserve the documented supported operation where a native manager path exists; do not silently switch distribution ownership.

Remove the Cellar/Scoop directory reconstruction, global receipt string replacement, link/junction emulation and fallback branches once every real entry point follows the chosen contract. Do not replace them with a generic package-manager provider registry, a new install database, broad path heuristics or a second rollback journal. The direct-install bundle contract belongs to #1058, and scratch creation to #1059. Do not make package-managed installations use those paths merely because they can copy an executable.

Keep exact outcome distinctions (already current, installed, failed/unsupported, installed-version unknown), installed path/version verification and the existing held-service restoration policy (#858). A successful process exit alone does not prove the requested release was installed.

Tests that can actually be deleted

The large symlink_upgrade_regression module includes many cases that call only std::fs, not TraceDecay's installer:

  • canonicalize_is_identity_for_non_symlink compares binary.canonicalize() to a second binary.canonicalize(); it does not compare with an independently expected original path.
  • symlink_survives_rename_replacement performs fs::write, not a rename or the production replacement helper.
  • our_fix_pattern_handles_all_cases recreates a guessed control-flow pattern instead of invoking it.
  • Several other tests prove read_link is relative, canonicalize follows links, a temporary parent exists, and fs::rename changes target bytes. They continue to pass if the production strategy is disconnected.
  • The Brew flow tests simulate directory/receipt operations and infer that Brew would recognize the result; they do not exercise package-manager state.

Delete those standard-library/self-simulation copies and obsolete self_update/Move::to_dest narration when the production emulation is removed. Keep tests that really call the surviving direct-install helper, plus one scoped delegation/ownership suite at the real orchestration boundary. Do not delete necessary supported-path, permissions, checksum, cancellation or rollback negatives simply because they use temporary files.

Acceptance

  • A managed install upgrade and supported channel change invoke the admitted manager command, not direct writes into Cellar/Scoop receipts or links.
  • Unsupported channel changes, missing managers, failed commands and ambiguous ownership fail before mutation; no silent ownership conversion or unsolicited daemon start.
  • The actual installed executable/path/version is checked through bounded execution; a no-op does not trigger the installed refresh path.
  • A manager failure leaves TraceDecay from this operation making no independent receipt/junction/version-directory edits.
  • Direct/manual installation still exercises real verified-bundle publication and failure preservation through fix(upgrade): install the complete release runtime bundle, not only the executable #1058/refactor(upgrade): stream verified archives into owned staging instead of whole-archive Vecs and PID paths #1059.
  • Replace duplicated stdlib tests with fewer falsifiable tests of these paths. Report deleted authored implementation/test code separately from any new coverage; do not claim all symlink behavior is redundant.

Primary native contract: https://docs.brew.sh/Manpage. Verify the actual supported Scoop/managed-channel command semantics before implementing; no invented command or unsupported channel promise is prescribed here.

Source review only. No package-manager command, repository test, install or release was executed. Keep #707 draft.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions