Skip to content

Bundle upgrade flow: no action, no version pinning, no reconcile #35

Description

@mgoldsborough

Problem

NimbleBrain's bundle lifecycle supports install, uninstall, start, stop — but no upgrade. Once a registry-based bundle ({name: "@nimblebraininc/foo"}) is installed in a workspace, there's no mechanism that pulls a newer version from mpak. The workspace keeps running whatever was fetched on initial install, indefinitely.

Today the only way to get a newer version is:

nb__manage action=uninstall name=@nimblebraininc/foo
nb__manage action=install name=@nimblebraininc/foo

This works but has real downsides (see below). More importantly, it's not discoverable — users don't know "upgrade = uninstall + install" is the incantation.

Why this matters

Concrete scenario from this week:

  • We cut synapse-crm v0.2.0 and synapse-todo-board v0.2.0 to fix a user-visible tool bug (agents orphaning tasks into undefined columns) and migrate to a new tool contract (flat kwargs).
  • For every tenant / local install currently running v0.1.0 of these bundles, NimbleBrain doesn't know the newer version exists. There's no "updates available" signal, no reconcile, no prompt.
  • The tenant keeps running a known-bad version until someone manually intervenes with the uninstall/install dance.

Multiply by every bundle in the registry and every tenant running them. The answer to "how do I upgrade?" shouldn't require reading the lifecycle source.

Downsides of uninstall+install as the upgrade path

  1. Not atomic: between uninstall and install, the bundle is unavailable. Any agent turn in that window fails.
  2. Loses installed state: if configure-style credentials or env allowlists live alongside the bundle entry, uninstall wipes them.
  3. Not discoverable: neither the agent nor a human user has an obvious way to express "move to latest."
  4. No rollback: if the new version is broken, getting back requires another uninstall + install pinned to an older version — and we don't support version pinning either (see below).
  5. No "check for updates": you can't ask NimbleBrain "is there a newer version than what I have?" without manually inspecting the mpak registry.

Proposed

Three independent-ish pieces. Ship in any order; each is useful alone.

1. nb__manage action=upgrade action

nb__manage action=upgrade name=@nimblebraininc/foo

Behavior:

  • Read the currently installed version from bundle metadata
  • Query mpak for the latest version (or the latest matching a pin — see Refactor identity to be per-workspace #2)
  • If newer: fetch new bundle, swap in place, preserve workspace-level config (allowedEnv, credentials refs, etc.)
  • If same or older: no-op with a clear message
  • Atomic from the agent's perspective — old tools remain callable until the new bundle is ready, then switch

Implementation notes:

  • BundleLifecycleManager gets an upgrade(name, wsId, registry) method that composes the existing installNamed + diff logic
  • Keep uninstall + install working as a fallback; upgrade is additive

2. Version pinning in workspace.json

Today:

{ "name": "@nimblebraininc/foo" }

Proposed (all valid, backward-compat):

{ "name": "@nimblebraininc/foo" }                           // implicit latest (current behavior)
{ "name": "@nimblebraininc/foo", "version": "latest" }      // explicit latest
{ "name": "@nimblebraininc/foo", "version": "^0.2" }        // semver range
{ "name": "@nimblebraininc/foo", "version": "0.2.1" }       // exact pin

On install / upgrade, resolve the spec against mpak's published versions. Matches npm / pip conventions; no surprises for consumers used to those.

Opens the door to:

  • nb__manage action=upgrade honors the pin (won't cross a major boundary unless you widen the range)
  • Future nb__manage action=rollback to previous installed version

3. Optional: "updates available" surface

Not required but cheap to add once #1 is in:

  • A read-only tool nb__updates_available (or part of existing nb__search output) that lists installed bundles whose mpak latest exceeds their installed version and respects any pin
  • Surfaces in a dashboard widget or as a notification
  • No automatic action — just visibility

Deliberately no automatic background reconcile / auto-upgrade. Upgrades should be user-triggered. Too easy to break a workspace with a silent auto-update at the wrong moment.

Out of scope for this issue

  • Path-based bundles ({path: ...}) — these are dev-mode references and intentionally have no upgrade concept. Changes are picked up on bundle-process restart. The upgrade flow here is "pull + restart the bundle server", handled at the git layer.
  • Remote-URL bundles ({url: ...}) — could support versioned URLs but treating them as always-latest is probably correct.
  • Reconcile loop / auto-upgrade — explicitly not proposed. Manual trigger only.

Related

  • Built on top of the existing BundleLifecycleManager in src/bundles/lifecycle.ts
  • Informs the agent-driven install flow in src/tools/system-tools.ts (where nb__manage is wired)
  • synapse-crm v0.2.0 and synapse-todo-board v0.2.0 (just cut) are the concrete bundles that today have no path to reach existing installs

Severity

Medium-to-high. Every bundle update beyond v0.1.0 hits this gap. As the mpak ecosystem grows, the pain scales linearly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/bundlesCode area: bundlesenhancementNew feature or requestreadyPassed the value test, at intake or as a sweep KEEP/ESCALATE; may be picked up

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions