[BUG] update/compile must reconcile deployed_files when the target universe contracts#2144
Closed
danielmeppiel wants to merge 3 commits into
Closed
[BUG] update/compile must reconcile deployed_files when the target universe contracts#2144danielmeppiel wants to merge 3 commits into
danielmeppiel wants to merge 3 commits into
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR makes apm update and apm compile reconcile on-disk deployed artifacts and lockfile deployed_files ownership against the currently declared target universe (so contracting targets: removes removed-target artifacts/rows), reusing install's hash/user-edit gated deletion path.
Changes:
- Adds shared reconciliation helpers in
install/manifest_reconcile.pyand routes install lockfile/local blocks through them. - Invokes post-success reconciliation from
apm update(including successful no-op updates) andapm compile(non-dry-run). - Adds unit + hermetic integration regressions for contracted-target cleanup and “no declared universe preserves siblings”, and updates command/reference docs.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/install/phases/test_lockfile_union.py | Adds regression ensuring reconciliation preserves legacy multi-target state when no declared universe exists. |
| tests/integration/test_inactive_target_ghost_e2e.py | Adds hermetic end-to-end tests asserting update/compile remove contracted-target artifacts and lock entries. |
| src/apm_cli/install/phases/targets.py | Delegates declared-universe resolution to shared manifest reconciliation helper. |
| src/apm_cli/install/phases/post_deps_local.py | Switches local lockfile deployed-files union logic to shared reconcile helper. |
| src/apm_cli/install/phases/lockfile.py | Switches per-dep deployed-files union logic to shared reconcile helper and threads diagnostics. |
| src/apm_cli/install/manifest_reconcile.py | Introduces declared-universe resolution + shared deployed-block/state reconciliation and persistence helper. |
| src/apm_cli/commands/update.py | Runs reconciliation after successful updates, including successful no-op updates. |
| src/apm_cli/commands/compile/cli.py | Runs reconciliation after successful non-dry-run compilation. |
| packages/apm-guide/.apm/skills/apm-usage/commands.md | Updates command reference blurbs to mention post-success reconciliation behavior. |
| docs/src/content/docs/reference/cli/update.md | Documents that successful updates reconcile target contraction even without dep ref changes. |
| docs/src/content/docs/reference/cli/compile.md | Documents post-success compile reconciliation semantics. |
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 1
- Review effort level: Low
Comment on lines
+184
to
+192
| from apm_cli.core.apm_yml import CANONICAL_TARGETS, parse_targets_field | ||
| from apm_cli.integration.targets import KNOWN_TARGETS | ||
| from apm_cli.utils.yaml_io import load_yaml | ||
|
|
||
| try: | ||
| data = load_yaml(project_root / "apm.yml") | ||
| names = parse_targets_field(data) if isinstance(data, dict) else None | ||
| except (AttributeError, KeyError, OSError, TypeError, ValueError): | ||
| return None |
apm-spec-waiver: Deployment reconciliation gives update/compile the parity install already has; enforces existing lockfile ownership semantics, no new OpenAPM wire behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Collaborator
Author
|
Superseded by #2155. The reliability campaign consolidated all 13 point fixes into a single architectural cure PR that re-homes each fix under its canonical owner module and adds owner-invariant guards. The fix for #2139 is folded into #2155 and re-verified there (full CI green). Closing this point PR in favor of the consolidated cure; the branch is preserved and this can be reopened if #2155 is not merged. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(reconciliation): remove deployments for contracted targets
TL;DR
apm updateandapm compilenow reconcile deployed files and lockfile ownership against the current declared target universe, including no-op dependency updates. The implementation shares install's target governance and hash-gated deletion path.Fixes #2139. This is the update/compile sibling to #2059 and #2114.
Problem (WHY)
copilot,windsurf, then contractapm.ymltocopilot.apm update --yes --target copilotexited 0 while.windsurf/rules/demo.mdand its lockfile entries survived.apm compile --target copilothad the same false-success state.apm installrepaired disk and lockfile state.Approach (WHAT)
manifest_reconcile.py.TargetProfilegovernance and preserve legacy multi-target state when no target universe is declared.remove_stale_deployed_files()so path, hash, and user-edit gates remain unchanged.Implementation (HOW)
--root.Legend: the dashed stage is the shared behavior introduced by this change.
flowchart LR U[apm update] --> R[ReconcileDeployedState] C[apm compile] --> R I[apm install] --> R R --> G[TargetProfile governance] G --> D[Hash-gated disk cleanup] G --> L[Lockfile reconciliation] classDef new stroke-dasharray: 5 5; class R new;Trade-offs
apm.ymldeclares no target universe, preserving existing multi-target state rather than inferring contraction from stale directories.Benefits
Validation evidence
TDD regression
The two new command scenarios failed on base at the stale-file assertion:
After the fix:
Scenario evidence
test_materializing_command_reconciles_contracted_target[update-args0]test_materializing_command_reconciles_contracted_target[compile-args1]test_state_reconcile_without_declared_universe_preserves_siblingLint
How to test
apm install --target copilot,windsurf --no-policy.windsurffromapm.ymland runapm update --yes --target copilot..windsurf/rules/<name>.mdand itsdeployed_files/deployed_file_hashesrows are gone.apm compile --target copilotand confirm the same result.uv run --extra dev python -m pytest tests/integration/test_inactive_target_ghost_e2e.py.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com