You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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.
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.rshas two incompatible Homebrew ownership models:run_upgradeselectsrun_brew_upgrade, invoking the actual manager and inspecting its installed binary.switch_channelinstead fetches a GitHub asset and callsperform_upgradewith the detected install method. For Brew that reachesreplace_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_metadatacopies the old version's files into a new directory, rewrites version occurrences in manifest.json, removescurrent, and invokescmd /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_regressionmodule includes many cases that call only std::fs, not TraceDecay's installer:canonicalize_is_identity_for_non_symlinkcomparesbinary.canonicalize()to a secondbinary.canonicalize(); it does not compare with an independently expected original path.symlink_survives_rename_replacementperformsfs::write, not a rename or the production replacement helper.our_fix_pattern_handles_all_casesrecreates a guessed control-flow pattern instead of invoking it.Delete those standard-library/self-simulation copies and obsolete
self_update/Move::to_destnarration 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
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.