Skip to content

fix: harden global lifecycle state handling - #2655

Open
lkshrk (lkshrk) wants to merge 7 commits into
microsoft:mainfrom
lkshrk:fix/omni-apm-blockers
Open

fix: harden global lifecycle state handling#2655
lkshrk (lkshrk) wants to merge 7 commits into
microsoft:mainfrom
lkshrk:fix/omni-apm-blockers

Conversation

@lkshrk

Copy link
Copy Markdown
Contributor

Summary

Fixes four global lifecycle correctness issues discovered during Omni's APM hard migration:

  • remove stale Antigravity and Hermes MCP entries without touching user-owned entries
  • make Hermes a stable explicit-only target
  • make global audit resolve external deployment roots without mutating them
  • serialize every lifecycle state mutator with one cross-process user lock

Closes #2608.

Safety properties

  • MCP config updates and cleanup use atomic writes and preserve mode/user entries
  • cleanup fails closed before lock ownership is discarded
  • audit replay remaps absolute Hermes/Claude roots into scratch and remains read-only
  • install/update/uninstall/prune/lock/deps/init/approve/marketplace/plugin mutations share one lifecycle lock
  • teardown, interruption, repeated completion, abandoned transactions, Windows home resolution, and lock timeout paths are covered

Validation

  • 19,879 unit tests passed
  • 75 focused integration tests passed
  • 166 architecture tests passed
  • 898 audit/drift tests passed
  • Windows compatibility gate: 153 passed
  • Ruff lint/format, mypy on touched code, test-authority checks, and diff checks passed
  • Independent code review: approved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens global (user-scope) lifecycle state correctness by (1) making audit/CI checks understand deployment roots outside ~/.apm, (2) stabilizing Hermes as an explicit-only target (not experimental-flag gated), (3) tightening MCP stale-server cleanup to fail closed and preserve user-owned config, and (4) serializing workspace mutations with a cross-process lifecycle lock.

Changes:

  • Add a cross-process lifecycle lock and apply it to most CLI state-mutating commands; make install transactions acquire/release the same lock safely across error paths.
  • Fix global audit/drift to resolve and compare against external deployment roots (e.g., ~/.agents, ~/.hermes, ~/.claude) without mutating those roots.
  • Make Hermes stable explicit-only (remove experimental flag gating) and extend MCP cleanup to cover Hermes YAML and Antigravity’s user-scope config location.

Reviewed changes

Copilot reviewed 56 out of 56 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/unit/test_windows_compat_gate_workflow.py Updates Windows compat gate contract to include one integration lock test path.
tests/unit/test_uninstall_engine_helpers.py Adds failure-mode regression tests ensuring MCP cleanup failures don’t drop lock ownership.
tests/unit/test_uninstall_dev_dependencies.py Updates expected uninstall output to reflect fail-closed MCP cleanup behavior.
tests/unit/test_prune_command.py Adds prune regression test for MCP cleanup failure preserving lock/config bytes.
tests/unit/test_mcp_integrator_remove_stale.py Adds coverage for atomic-failure preservation, Hermes YAML cleanup, and strict malformed shapes.
tests/unit/test_cli_consistency.py Updates compile help assertions for explicit-only Hermes exclusion from all.
tests/unit/integration/test_targets.py Updates Hermes target invariants and removes experimental-flag gating.
tests/unit/integration/test_antigravity_target.py Adds Windows-compat atomic-write/mode preservation coverage for Antigravity MCP config.
tests/unit/install/test_workspace_locking.py Unit contracts for lifecycle lock behavior and error-path release.
tests/unit/install/test_install_transaction.py Adds multi-process serialization tests + interruption/abandonment/repeat-completion lock release coverage.
tests/unit/core/test_target_resolution_v2.py Updates target filtering expectations to keep stable Hermes.
tests/unit/core/test_target_detection.py Removes Hermes from experimental target set characterization.
tests/unit/core/test_target_catalog.py Updates target-set characterization and Hermes profile expectations.
tests/unit/commands/test_uninstall_atomic_selection.py Adds uninstall regression test ensuring MCP cleanup failure preserves lock/config bytes.
tests/integration/test_mcp_install_flow.py Adds global manifest removal + prune flows validating Antigravity MCP cleanup semantics.
tests/integration/test_lifecycle_workspace_lock.py Cross-command subprocess regression test ensuring lifecycle serialization across commands/scope.
tests/integration/test_hermes_target.py Updates Hermes E2E tests for stable explicit-only behavior and MCP selection changes.
tests/integration/test_global_audit_deploy_root.py New integration coverage: global audit resolves external roots read-only and detects drift.
src/apm_cli/policy/ci_checks.py Resolves deployed-file paths for global scope and audits external target roots read-only.
src/apm_cli/integration/targets.py Documentation tweak reflecting Hermes stable explicit-only status.
src/apm_cli/integration/mcp_integrator.py Adds strict config-shape validation, atomic writes, and Hermes YAML MCP stale cleanup.
src/apm_cli/integration/mcp_integrator_install.py Removes Hermes from auto-discovery/experimental opt-in gating.
src/apm_cli/install/transaction.py Makes install transactions acquire/release lifecycle lock safely across failure paths.
src/apm_cli/install/phases/targets.py Removes Hermes experimental enable-hint gate.
src/apm_cli/install/locking.py New lifecycle locking module (FileLock-based) + decorator for command serialization.
src/apm_cli/install/drift.py Adds user-scope replay and external-root drift comparisons with absolute-claim rebasing.
src/apm_cli/install/audit_target_roots.py New helpers to project external target roots into audit scratch + rebase claims.
src/apm_cli/install/audit_replay.py Threads user-scope into CI audit replay preparation and target resolution.
src/apm_cli/core/target_detection.py Adds Hermes to accepted target vocabulary and updates description text.
src/apm_cli/core/target_catalog.py Marks Hermes capability as explicit-only rather than experimental-flag gated.
src/apm_cli/core/scope.py Adds helper to resolve workspace deploy root for user-scope metadata workspaces.
src/apm_cli/core/experimental.py Removes Hermes experimental flag registration.
src/apm_cli/commands/update.py Serializes apm update via lifecycle lock.
src/apm_cli/commands/uninstall/engine.py Broadens stale MCP server set derivation and fails closed on cleanup write errors.
src/apm_cli/commands/uninstall/cli.py Serializes uninstall and fails closed when MCP cleanup fails (prevents persisting dropped ownership).
src/apm_cli/commands/prune.py Serializes prune and integrates MCP cleanup into prune-before-lock-write flow.
src/apm_cli/commands/plugin/init.py Serializes plugin init via lifecycle lock.
src/apm_cli/commands/marketplace/plugin/remove.py Serializes marketplace plugin remove via lifecycle lock.
src/apm_cli/commands/marketplace/plugin/add.py Serializes marketplace plugin add via lifecycle lock.
src/apm_cli/commands/marketplace/init.py Serializes marketplace init via lifecycle lock.
src/apm_cli/commands/marketplace/init.py Serializes marketplace add/update/remove via lifecycle lock.
src/apm_cli/commands/lock.py Serializes lock command execution via lifecycle lock.
src/apm_cli/commands/install.py Serializes install and hardens root-redirect/transaction teardown ordering.
src/apm_cli/commands/init.py Serializes project init via lifecycle lock.
src/apm_cli/commands/deps/cli.py Serializes deps clean/update via lifecycle lock.
src/apm_cli/commands/approve.py Serializes approve/deny via lifecycle lock.
src/apm_cli/adapters/client/gemini.py Switches Gemini config writes to atomic writes with secure permissions.
docs/src/content/docs/reference/targets-matrix.md Updates Hermes status and compilation guidance in targets matrix docs.
docs/src/content/docs/reference/manifest-schema.md Reclassifies Hermes as stable in manifest schema docs.
docs/src/content/docs/reference/environment-variables.md Updates HERMES_HOME semantics for explicit-only Hermes.
docs/src/content/docs/reference/cli/experimental.md Removes Hermes from experimental-flag list.
docs/src/content/docs/reference/cli/deps.md Updates deps target docs for Hermes stable explicit-only behavior and all exclusion.
docs/src/content/docs/producer/compile.md Removes Hermes from experimental-target list in compile docs.
docs/src/content/docs/integrations/hermes.md Updates Hermes integration page to stable explicit-only and MCP behavior.
docs/astro.config.mjs Renames Hermes nav label to non-experimental.
.github/workflows/ci.yml Expands Windows compat gate to include lifecycle subprocess integration contract.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/apm_cli/commands/prune.py Outdated
Comment thread src/apm_cli/integration/mcp_integrator.py Outdated
Comment thread src/apm_cli/commands/marketplace/plugin/add.py
@lkshrk

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

lkshrk (lkshrk) and others added 3 commits August 23, 2026 12:31
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
lkshrk (lkshrk) added a commit to lkshrk/omni that referenced this pull request Aug 28, 2026
Vanilla apm has no lifecycle serialization of its own (microsoft/apm#2655), so concurrent global installs corrupt the shared workspace.
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.

[BUG] apm audit cannot validate global user-scope installations

2 participants