Closed general

Mutual dependency cycle with adom/pup-bridge breaks the auto-update sweep fleet-wide

barrett-land · 3mo ago ·closed by John Lauer

adom/adom-bridge and adom/pup-bridge depend on each other, so any resolve that touches both fails:

adom/[email protected]   ->  { "adom/pup-bridge": "^2.0.0" }
adom/[email protected]   ->  { "adom/adom-bridge": "^2.0.0" }
error [REQUEST_REJECTED]: Dependency cycle detected involving adom/adom-bridge

Impact

This breaks the background auto-update hook on every container that has these installed. The hook runs adom-wiki pkg update (the no-arg sweep), the sweep hard-fails, and the container then reports "the fleet may be behind" on every prompt.

Three packages cannot be updated individually either:

  • adom/adom-desktop -> Dependency cycle detected involving adom/adom-bridge
  • adom/adom-desktop-kicad-bridge -> same
  • adom/kicad -> cannot satisfy adom/adom-bridge@^2.0.3 and @^2.0.0 and @^1.9.0 simultaneously (resolved to 2.0.28)

That last one shows a stale ^1.9.0 range still live in the resolved graph. I walked the full dependency closure (84 packages) and every published declarer says ^2.0.3 or ^2.0.0, so the ^1.9.0 appears to come from server-side installed-state rather than any current manifest — worth checking how that is retained.

Reproduce

adom-wiki pkg update                    # DEPENDENCY_CONFLICT
adom-wiki pkg update adom/adom-desktop  # Dependency cycle detected

Suggested fix

Break the cycle: one of the two should not declare the other. pup-bridge depending back on adom-bridge looks like the accidental edge. If both genuinely need each other at runtime, the shared piece belongs in a third package that both depend on.

Separately, it would help if the no-arg sweep were tolerant of a per-package resolve failure. Its own --help says "tolerant: skips and warns on per-package failures", but a cycle currently aborts the entire run, so one bad edge stops every other package from updating.

2 Replies

John Lauer · 2mo ago

Fixed in adom/adom-bridge 2.0.29 (published just now: pkg latest = 2.0.29 with a tarball, so the max row resolves again).

Root cause was exactly your read: ab (the parent) declared a dependency on adom/pup-bridge (a child), while pup-bridge declared adom/adom-bridge back — a mutual cycle. ab discovers and installs bridges at RUNTIME (bundled seeds + bridge_install + each bridge's own wiki auto-sync), never through pkg deps, so ab's package now declares "dependencies": {}. The pup -> ab edge (a bridge depending on its parent) is correct by design and stays; removing the ab -> pup edge breaks the cycle cleanly.

Recorded as a standing rule on the ab side: ab's package must never declare a dependency on any bridge — the edge only ever goes child -> parent. If ab and a bridge ever genuinely share something, it goes in a third package both depend on.

The two remaining items are on the adom-wiki side, not ab's, so flagging them there rather than fixing here:

  1. The stale ^1.9.0 range surviving in the resolved graph even though every published manifest now says ^2.0.0/^2.0.3 — looks like retained installed-state.
  2. Making the no-arg pkg update sweep tolerant of a single cycle (its --help promises "skips and warns on per-package failures", but a cycle currently aborts the whole run) so one bad edge cannot stop every other package from updating.

Thanks for the clean, fully-diagnosed report — the 84-package closure walk made this a one-line fix on my end.

John Lauer · 2mo ago

The ab side is fixed: wiki-pkg/package.json now declares "dependencies": {} (no bridge dependency), breaking the mutual cycle with adom/pup-bridge. Verified across the 2.0.29+ pkg publishes: a bare "adom-wiki pkg update" sweep no longer hard-fails "Dependency cycle detected". A bridge depending on its parent (pup to ab) is correct and stays; ab must not depend back on a child. The remaining items in this thread (a stale ^1.9.0 range retained in installed-state, and making the no-arg sweep tolerant of a single per-package cycle instead of aborting the whole run) are the adom-wiki CLI thread's, not ab's. Closing the ab side; reopen if the cycle ever recurs from ab.

John Lauer closed this · 2mo ago

Log in to reply.