Summary
Running apm install -g <pkg>#<ref> --update against ~/.apm/apm.yml mutates the lockfile in two unwanted ways:
- Duplicate entries in
deployed_files for packages whose deployment path is currently double-walked. Same package's deployed_hashes map has only one entry per path -- so the asymmetry shows the dedup is half-implemented.
- Unrelated-dep churn: passing
--update for one named CLI package re-resolves and re-writes lockfile entries for other packages too, even when their refs haven't changed upstream.
Together this makes apm install -g ... --update non-deterministic for state-correctness review (e.g. git diff ~/.apm/apm.lock.yaml) and inflates the diff a maintainer has to scan to confirm a change was safe.
Repro
State: ~/.apm/apm.yml lists obra/superpowers (unpinned), github/awesome-copilot/plugins/azure-cloud-development (unpinned), and a few others. ~/.apm/apm.lock.yaml already at HEAD for all.
$ apm install -g 'danielmeppiel/genesis#main' --update
[*] Installed 6 APM dependencies in 29.9s.
Lockfile diff (obra/superpowers entry only -- I did not touch it):
+ - .copilot/hooks/scripts/superpowers/hooks/run-hook.cmd
+ - .copilot/hooks/scripts/superpowers/hooks/run-hook.cmd # ← dup
+ - .copilot/hooks/superpowers-hooks-cursor.json
+ - .copilot/hooks/superpowers-hooks-cursor.json # ← dup
+ - .copilot/hooks/superpowers-hooks.json
+ - .copilot/hooks/superpowers-hooks.json # ← dup
The corresponding deployed_hashes: block has one entry per path:
deployed_hashes:
.copilot/hooks/scripts/superpowers/hooks/run-hook.cmd: sha256:d3d9c619...
.copilot/hooks/superpowers-hooks-cursor.json: sha256:53d8ceb3...
.copilot/hooks/superpowers-hooks.json: sha256:a510fbce...
So deployed_files is the only field with the dup; the integrity-tracking field is consistent. That's smoking-gun evidence the duplicate is a list-append bug in whatever populates deployed_files, not a legitimate per-target deployment.
Separately, awesome-copilot got + .codex/agents/azure-*.toml lines added -- not because Codex deployment changed, but because the prior lockfile predates the dep's Codex coverage and --update re-walked all integrators across all deps.
Why this matters
- State-correctness review hygiene. A maintainer running
apm install -g <one-pkg> --update reasonably expects the lockfile diff to scope to that one package + its transitives. Scope creep across unrelated deps makes "did this CLI invocation do what I expected?" much harder to verify.
apm doctor-style consistency checks that compare deployed_files to actual on-disk files will tolerate dups today but degrade reliably over time -- bug surface is one rename / one normalization away.
- Reproducibility of
--frozen installs depends on lockfile content being canonical; duplicate entries break "two valid lockfiles for the same state are byte-identical".
Suggested fix
- Dedup
deployed_files at write time -- mirror the dedup that's already happening in deployed_hashes. Likely a single sorted(set(...)) at lockfile-serialization time.
- Scope
--update re-walk to packages whose ref or content actually changed (or to the explicit CLI arg list when one is passed) -- don't re-emit lockfile entries for unrelated deps just because they share an integrator.
- Add a regression test that runs
apm install -g <pkg> --update twice with no upstream changes and asserts git diff apm.lock.yaml is empty after the second run.
Environment
Related
Summary
Running
apm install -g <pkg>#<ref> --updateagainst~/.apm/apm.ymlmutates the lockfile in two unwanted ways:deployed_filesfor packages whose deployment path is currently double-walked. Same package'sdeployed_hashesmap has only one entry per path -- so the asymmetry shows the dedup is half-implemented.--updatefor one named CLI package re-resolves and re-writes lockfile entries for other packages too, even when their refs haven't changed upstream.Together this makes
apm install -g ... --updatenon-deterministic for state-correctness review (e.g.git diff ~/.apm/apm.lock.yaml) and inflates the diff a maintainer has to scan to confirm a change was safe.Repro
State:
~/.apm/apm.ymllistsobra/superpowers(unpinned),github/awesome-copilot/plugins/azure-cloud-development(unpinned), and a few others.~/.apm/apm.lock.yamlalready at HEAD for all.Lockfile diff (
obra/superpowersentry only -- I did not touch it):The corresponding
deployed_hashes:block has one entry per path:So
deployed_filesis the only field with the dup; the integrity-tracking field is consistent. That's smoking-gun evidence the duplicate is a list-append bug in whatever populatesdeployed_files, not a legitimate per-target deployment.Separately,
awesome-copilotgot+ .codex/agents/azure-*.tomllines added -- not because Codex deployment changed, but because the prior lockfile predates the dep's Codex coverage and--updatere-walked all integrators across all deps.Why this matters
apm install -g <one-pkg> --updatereasonably expects the lockfile diff to scope to that one package + its transitives. Scope creep across unrelated deps makes "did this CLI invocation do what I expected?" much harder to verify.apm doctor-style consistency checks that comparedeployed_filesto actual on-disk files will tolerate dups today but degrade reliably over time -- bug surface is one rename / one normalization away.--frozeninstalls depends on lockfile content being canonical; duplicate entries break "two valid lockfiles for the same state are byte-identical".Suggested fix
deployed_filesat write time -- mirror the dedup that's already happening indeployed_hashes. Likely a singlesorted(set(...))at lockfile-serialization time.--updatere-walk to packages whose ref or content actually changed (or to the explicit CLI arg list when one is passed) -- don't re-emit lockfile entries for unrelated deps just because they share an integrator.apm install -g <pkg> --updatetwice with no upstream changes and assertsgit diff apm.lock.yamlis empty after the second run.Environment
apm 0.16.0 (e94af4a)on macOS Darwinapm installsummary reports "Installed N APM dependencies" even when no files changed #1557.Related
apm install -g <pkg>#<ref>) -- this issue is a sibling state-correctness bug exposed by the same repro path.apm installsummary reports "Installed N APM dependencies" even when no files changed #1557 (misleading "Installed N" summary) -- same--updateinvocation, different surface.