Skip to content

[foundation] activator skips reinstall when a module's source changes, so a repointed module keeps running the old editable checkout #398

Description

@Joi

Summary

amplifier_foundation/modules/activator.py skips the editable install of a module whenever a distribution with the same name is already installed in the tool venv (Package '<name>' already installed from wheels, skipping editable install from <path>). The check keys only on the distribution name. It does not compare the requested module path with where the installed distribution actually lives. So after a module's source is repointed (a sources.modules.<id> override in settings, a bundle behavior's source: line, or a removed pin), the old editable checkout keeps running on every host that installed the module before the change. Nothing in a run's output says so.

Repro

  1. amplifier with a bundle whose hooks-routing source is fork A. Run once. The venv now has _editable_impl_amplifier_module_hooks_routing.pth -> ~/.amplifier/cache/<fork-A>/modules/hooks-routing.
  2. Change the source to upstream B (settings sources.modules.hooks-routing, or the bundle file). Run again.
  3. uv pip list --python ~/.local/share/uv/tools/amplifier/bin/python | grep hooks-routing still shows the fork-A path. Log: Package 'amplifier-module-hooks-routing' already installed from wheels, skipping editable install from ~/.amplifier/cache/<upstream-B>/modules/hooks-routing.
  4. uv pip uninstall --python <venv python> amplifier-module-hooks-routing, run again. Now the .pth points at upstream B.

Versions: amplifier 2026.09.08-dfa56a7, amplifier-core 1.6.1, amplifier-foundation 1.0.0 (activator.py around lines 596-612, the _distribution_installed(pkg_name) guard; the same guard exists at ~397 in activate_bundle_package).

What it cost us

One Mac ran a fork of hooks-routing from June for three months after the fork override was superseded. That fork predates the model_role_resolver capability, so every recipe step with model_role: and every delegate(model_role=...) logged "no model_role_resolver capability is registered" and fell back to the default provider. The bundle and settings both said upstream. The same happened to tool-recipes after a fork pin was removed; the recipes engine's own provenance guard (engine_provenance.py, "editable install ... points at X but this engine was imported from Y") is what finally made it visible.

Suggestion

Keep the name-based skip for packages that came from PyPI wheels (that is the #326 case). For editable installs, compare the installed distribution's direct_url.json / .pth target with the module path being activated and reinstall when they differ. At minimum, log at WARNING when the requested path and the installed editable location disagree, so a repointed source is not silent.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions