Skip to content

Conversation

@colombod
Copy link
Contributor

@colombod colombod commented Jan 28, 2026

Summary

Adds consolidation API to InstallStateManager for proper dependency verification and state management, enabling users stuck in stale install state to auto-recover.

Problem

After operations like uv tool install --force or amplifier update, the Python venv is recreated but install-state.json persists. This causes:

Failed to load module 'tool-web': Module 'tool-web' failed validation: 
FAILED: 0/1 checks passed (1 errors, 0 warnings). 
Errors: module_importable: Failed to import module: No module named 'aiohttp'

Users had no automatic recovery path and had to manually delete ~/.amplifier/install-state.json.

Solution

Three new capabilities added to InstallStateManager:

Method Purpose
invalidate_modules_with_missing_deps() Surgical invalidation - removes only modules with missing deps
clear() Full state reset for complete reinstall scenarios
is_installed() (enhanced) Proactive verification - checks deps are actually present

Evidence of Improvement

Before (stale state causes crash)

# User updates amplifier (venv recreated, install-state.json preserved)
$ amplifier update

# Next session fails - aiohttp missing but state claims tool-web installed
$ amplifier run "fetch https://example.com"
Failed to load module 'tool-web': No module named 'aiohttp'
ModuleValidationError: Module 'tool-web' failed validation

After (auto-healing on startup)

# Same scenario - but now is_installed() detects missing deps
$ amplifier run "fetch https://example.com"
INFO: Module tool-web has missing dependencies: ['aiohttp']. Will reinstall.
# ... aiohttp automatically reinstalled ...
🔧 Using tool: web_fetch
   url: https://example.com
✅ Tool result: web_fetch
   content: Example Domain...

Shadow Test Results

Test Result
Uninstall aiohttp → run amplifier ✅ Auto-healed, web_fetch worked
invalidate_modules_with_missing_deps() API ✅ 27 checked, 1 invalidated (surgical)
Modules with all deps present ✅ Not reinstalled (fast startup preserved)

Unit Test Coverage

35 new tests added covering:
- _extract_dependencies_from_pyproject() - 7 tests
- _check_dependency_installed() - 4 tests  
- InstallStateManager core - 5 tests
- is_installed() with dep verification - 6 tests
- mark_installed(), save(), invalidate() - 6 tests
- clear(), invalidate_modules_with_missing_deps() - 7 tests

Total: 290 passed (255 existing + 35 new)

API for app-cli Integration

This enables follow-up work in microsoft/amplifier#195 to replace direct JSON manipulation:

# In update_executor.py (after self-update)
from amplifier_foundation.modules.install_state import InstallStateManager
mgr = InstallStateManager(cache_dir)
checked, invalidated = mgr.invalidate_modules_with_missing_deps()

# In reset.py (when clearing cache)
mgr = InstallStateManager(cache_dir)
mgr.clear()
mgr.save()

Files Changed

  • amplifier_foundation/modules/install_state.py - New API methods + dependency verification
  • tests/test_install_state.py - Comprehensive test coverage (new file)

🤖 Generated with Amplifier

colombod and others added 2 commits January 27, 2026 23:56
…(issue #193)

Addresses microsoft/amplifier#193 - Consolidate install-state.json manipulation.

Adds to InstallStateManager:
- invalidate_modules_with_missing_deps() - Surgical invalidation checking
  each tracked module's dependencies against what's actually installed.
  Returns (checked, invalidated) tuple for reporting.
- clear() - Convenience method for full state reset.

Also enhances is_installed() to proactively verify dependencies are present,
catching stale state after operations like `uv tool install --force` that
wipe the venv but don't clear install-state.json.

Module-level helpers added:
- _extract_dependencies_from_pyproject() - Parses pyproject.toml for deps
- _check_dependency_installed() - Uses importlib.metadata for reliable
  package detection with PEP 503 name normalization

This enables amplifier-app-cli to use InstallStateManager instead of
direct JSON manipulation in update_executor.py and reset.py.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Adds 35 tests covering:
- _extract_dependencies_from_pyproject() helper
  - Simple deps, version specifiers, extras, namespace packages
  - Edge cases: nonexistent file, empty deps, invalid TOML

- _check_dependency_installed() helper
  - Installed/uninstalled packages
  - Case insensitivity and hyphen/underscore normalization

- InstallStateManager core functionality
  - Fresh state creation, loading existing state
  - Version mismatch and Python executable change handling
  - Invalid JSON recovery

- is_installed() with dependency verification
  - Fingerprint matching
  - Dependency presence checking
  - Auto-invalidation on missing deps

- mark_installed(), save(), invalidate()

- New methods: clear(), invalidate_modules_with_missing_deps()
  - Surgical invalidation of modules with missing deps
  - Mixed module handling (valid + invalid)
  - Persistence verification

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
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.

[foundation] Add consolidation API to InstallStateManager

1 participant