Skip to content

fix(update): self-update never updated the package for shell-invoked global installs#170

Merged
madarco merged 5 commits into
nightlyfrom
fix/exec-method-global-bin
Jul 8, 2026
Merged

fix(update): self-update never updated the package for shell-invoked global installs#170
madarco merged 5 commits into
nightlyfrom
fix/exec-method-global-bin

Conversation

@madarco

@madarco madarco commented Jul 8, 2026

Copy link
Copy Markdown
Owner

What

agentbox self-update answered the question "does it download the latest version?" with no for the common case. A global bin invoked straight from the shell carries no npm_config_user_agent, and argv[1] is the bin symlink (/usr/local/bin/agentbox) — so detectExecutionMethod returned direct and self-update printed "skipped (running from source — no global install to update)" without ever running npm install -g @madarco/agentbox@latest. The old unit test masked this by passing a user-agent that only exists when the CLI is invoked through npm (npx / npm exec / scripts). The new daily nudge (#165) made it worse: it pointed exactly these users at a self-update that skips.

Fix

  • detectExecutionMethod now resolves the bin symlink's realpath when no user-agent is present: npm globals live under <prefix>/lib/node_modules/, pnpm globals inside a /.pnpm/ store. A dev checkout (or the pnpm register symlink into one) still classifies direct.
  • nudgeEligible tightened to npm/pnpm only — the nudge never points at a self-update that would skip the package step.

Verification

  • New unit tests: real symlink fixtures for the npm-global and pnpm-global layouts (no user-agent), plus the literal-path fallback; full suite 713 passing.
  • End-to-end: ran the real built dist through a simulated global layout (.tmp-fake/bin/agentbox symlink → lib/node_modules/@madarco/agentbox/dist/index.js, no user-agent) — self-update --dry-run now plans npm install -g @madarco/agentbox@latest. The dev symlink (/opt/homebrew/bin/agentbox → checkout) still reports direct/skip.

https://claude.ai/code/session_0156d47n9hxNTCAuyjX7rEch


Note

Medium Risk
Changes how the CLI classifies launch context for self-update and update nudges; wrong path heuristics could mis-run global installs or skip dev checkouts, but scope is limited to exec detection and eligibility gates with new symlink tests.

Overview
Fixes agentbox self-update and update nudges for the usual case: running a globally installed binary from the shell with no npm_config_user_agent, where argv[1] is only the bin symlink.

detectExecutionMethod now realpathSyncs argv[1] when user-agent checks do not apply, then treats resolved paths under /.pnpm/ as pnpm and /lib/node_modules/ as npm; missing paths still use the literal path (tests). Dev checkouts and other launches stay direct.

nudgeEligible is narrowed to npm / pnpm only (plus a non-dev version), so direct and npx users are not told to run self-update when the package step would be skipped.

Tests add temp symlink fixtures for npm and pnpm global layouts without user-agent, plus updated expectations for nudgeEligible.

Reviewed by Cursor Bugbot for commit aaaa7ca. Configure here.

A global bin run straight from the shell carries no npm_config_user_agent,
and argv[1] is the bin symlink — detectExecutionMethod classified the common
case as 'direct', so agentbox self-update skipped the package update entirely
('running from source — no global install to update') and never downloaded
the latest version. The old unit test masked it by passing a user-agent that
only exists when invoked through npm.

Resolve the bin symlink's realpath: npm globals live under
<prefix>/lib/node_modules/, pnpm globals inside a /.pnpm/ store; a dev
checkout (or the pnpm-register symlink) stays 'direct'. The update nudge is
tightened to npm/pnpm only so it never points at a self-update that would
skip.

Verified end-to-end: the real dist run via a simulated global layout
(bin symlink, no user-agent) now plans 'npm install -g @madarco/agentbox@latest';
the dev symlink still classifies direct.

Claude-Session: https://claude.ai/code/session_0156d47n9hxNTCAuyjX7rEch
@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
agentbox-web Skipped Skipped Jul 8, 2026 8:15am

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit aaaa7ca. Configure here.

// the literal path instead.
}
if (real.includes('/.pnpm/')) {
return 'pnpm';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Local pnpm store misclassified global

Medium Severity

After symlink resolution, any path containing /.pnpm/ is treated as a pnpm global install. Project-local pnpm layouts use the same store segment under node_modules/.pnpm, so launches without npm_config_user_agent (e.g. via node_modules/.bin) can be misclassified and self-update may run pnpm add -g instead of skipping the package step.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit aaaa7ca. Configure here.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in e66229d — good catch, and it was wrong in both directions: pnpm's global dir is itself project-shaped (<PNPM_HOME>/global/5/node_modules/.pnpm/...), so the .pnpm store marker matched local layouts and my global fixture didn't match reality. Detection now matches the /pnpm/global/ dir segment; project-local stores (and unrecognized custom PNPM_HOME layouts) classify as direct, where self-update skips the package step instead of running a global add.

…tall

pnpm's global dir is project-shaped (<PNPM_HOME>/global/5/node_modules/.pnpm),
so matching the .pnpm store segment also matched project-local layouts and a
node_modules/.bin launch could have triggered 'pnpm add -g' over a local dep.
Match the /pnpm/global/ dir instead; local installs (and unrecognized custom
PNPM_HOME layouts) classify as direct, where self-update skips the package
step.

Claude-Session: https://claude.ai/code/session_0156d47n9hxNTCAuyjX7rEch
The tray app publishes separately (tray-latest GitHub release, sha-compared
by install tray / self-update / the update nudge), so /release-notes now
always checks ../agentbox-tray for commits since its last tag, tells the
user alongside the changelog entry, and documents the publish flow incl.
the load-bearing AGENTBOX_NOTARY_PROFILE and the VERSION-bump commit.

Claude-Session: https://claude.ai/code/session_01JKGc7YWFuXVJvXKNHYnHeB
… 40ms)

The positive assertions gave the 10ms queue loop a fixed 40ms window; on
loaded CI runners the first tick can land after it — this failed three CI
runs across PRs #165 and #170 (different tests in the same describe each
time). Poll for the condition (2s cap) instead; negative assertions keep the
short sleep.

Claude-Session: https://claude.ai/code/session_0156d47n9hxNTCAuyjX7rEch
@madarco madarco merged commit 6fdd34b into nightly Jul 8, 2026
3 checks passed
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.

1 participant