Closed bug report

Bridge lifecycle: (1) re-run npm install when a bridge's lockfile changes on re-sync [blocks fleet dep bumps], (2) cap/rotate bridge stdout logs, (3) bridge_log_read mixes AD lifecycle lines with bridge output

John Lauer · 17d ago ·closed by John Lauer

Three AD-core bridge-lifecycle gaps, all hit live 2026-07-24 while shipping a puppeteer bump (24.39.1 -> 24.43.1) to move the fleet's Chrome-for-Testing off the stale 146 onto 148. The bump is correct and verified on one box, but it will NOT reach the fleet until item 1 is fixed AD-side.

(Filed here on adom/adom-desktop, not on the pup bridge page: these are AD-core's to fix, so they belong on AD's issue list. Originally mis-filed as pup bridge issue #18, now moved here.)

1. (BLOCKER) Re-run npm install on re-sync when the lockfile changed

preserve_client_deps() (added AD 1.9.169 to stop the MODULE_NOT_FOUND loop by carrying node_modules across a source-only bridge re-sync) also preserves node_modules when a bridge's DEPENDENCIES change, so a dependency bump silently never applies. Measured: bridge code re-synced to the new version (BRIDGE_VERSION + package.json both updated to ^24.43.1), but the running bridge kept puppeteer 24.39.1 and Chrome 146. The only way to apply it was to manually bridge_kill, delete node_modules, and respawn to force a fresh npm install (which then correctly installed 24.43.1 / CfT 148). This is the exact edge flagged when 1.9.169 shipped: "a preserved node_modules is stale if a future bridge version changes its deps."

Ask: on re-sync, hash-compare the incoming package-lock.json against the installed one.

  • unchanged -> preserve node_modules (today's fast path; the MODULE_NOT_FOUND fix stays intact)
  • changed -> run npm install/npm ci against the new lock, THEN continue npm install is incremental, so an unchanged tree stays cheap. Without this, a bridge author cannot ship ANY dependency upgrade to the fleet: the CfT-148 bump reached exactly one machine.

2. Cap + rotate the bridge's captured stdout logs

AD captures each bridge's stdout into bridge-stdout.log / bridge-stderr.log with no visible size cap (AD's own startup.log was already ~725 KB). A long-running bridge grows them unbounded. This must live in AD: a bridge cannot rotate a file another process opened and holds, and every bridge (including third-party) needs bounded logs. Suggest a size cap + rotation (e.g. 5 MB, keep 2-3). We deliberately did NOT have pup write its own parallel log (two sources of truth, double the disk).

3. bridge_log_read interleaves AD lifecycle lines with the bridge's own output

bridge_log_read {name:"puppeteer"} returns the bridge's stdout MIXED with AD lifecycle lines like [AD 2026-07-21 15:00:41] spawned process pid 16220 (node.exe). Reading "the puppeteer log" should return the puppeteer bridge's output. Debugging repeatedly meant filtering AD's lines out of a bridge log, and the tail was often ALL AD lifecycle lines, hiding the bridge output entirely. Either scope the read to that bridge's stream, or return the two as separate labelled sections. (The v1.9.93 <name>.ad.log split helps for lifecycle events; the ask is to keep the two streams cleanly separable in the read output.)

  • On AD self-update / a user clicking "Install now", force a re-check of every installed bridge's updateManifestUrl rather than waiting for the periodic poll.
  • Surface bridge staleness: status / footer should show per-bridge installed-vs-latest + a stale flag; a bridge_check_updates verb to force it.

Not an AD bug, noting to avoid conflation: the puppeteer/CfT choice and the freeze diagnostics are ours (pup bridge). Only the three lifecycle items above are AD-core.

1 Reply

John Lauer · 17d ago

All three items shipped in AD 1.9.177; the two nice-to-haves turned out to already exist since 1.9.154.

  1. (BLOCKER) Dep bumps reach the fleet. ensure_node_modules is lock-hash-gated: a preserved node_modules is trusted only while node_modules/.ad-installed-lock-hash matches the sha256 of the current package-lock.json. A mismatch runs an INCREMENTAL npm install and re-records the hash (the bundled-seed NODE_PATH shortcut is skipped in that case). The hash lives inside node_modules so the 1.9.169 preserve carries it for free.
  2. Logs bounded. Bridge stdout handles are append-mode and AD rotates any live log over 8 MB (last 2 MB to <name>.log.1) on its health tick.
  3. Streams separated. bridge_log_read returns log (the bridge's output only) and adLifecycle (AD's spawn/reap audit) as distinct fields.

Nice-to-haves, already present since v1.9.154: the on-launch sync_all (3s into every launch) IS the post-self-update bridge re-check, and refresh_staleness_cache is what feeds status.bridgeUpdates / the footer, with bridge_check_updates as the on-demand force.

Closing - the duplicate on the puppeteer page (#18 there) carries the same detail.

Log in to reply.