Skip to content

fix(daemon): restart stale devkitd after CLI upgrades #376

Open

Description

@codeaholicguy

Summary

agent list can keep using an older devkitd process after AI DevKit is upgraded. The CLI treats any daemon answering on ~/.ai-devkit/daemon.sock as authoritative, without checking whether it matches the currently installed daemon package.

This makes daemon fixes appear ineffective until the old process is manually stopped. It is a follow-up to #371 / #372, not a duplicate: the parser fix is released, but an already-running pre-fix daemon continues serving the socket.

Reproduction

  1. Run AI DevKit 0.70.0 (@ai-devkit/daemon-client / platform daemon 0.1.1) and let it start devkitd.
  2. Upgrade to or invoke AI DevKit 0.70.1, which depends on daemon packages 0.1.2 containing fix(devkitd): parse ps rows with padded columns on Linux #372.
  3. Keep the original daemon process running.
  4. With four interactive Codex processes active, compare:
npx ai-devkit@latest agent list --json
AI_DEVKIT_NO_DAEMON=1 npx ai-devkit@latest agent list --json

Actual behavior

  • Daemon-backed discovery returns 1 interactive agent.
  • Direct discovery returns all 4 interactive agents.
  • The live socket is still owned by the old global installation:
ai-devkit: 0.70.0
@ai-devkit/devkitd-darwin-arm64: 0.1.1
  • The invoking CLI is 0.70.1.
  • The host process table contains four interactive Codex processes, but daemon.db contains only one of them.
  • The one persisted row has unpadded five-digit PID/PPID fields; the three missing rows contain alignment padding. This matches the pre-fix(devkitd): parse ps rows with padded columns on Linux #372 parser behavior exactly.

Expected behavior

After upgrading or invoking a newer AI DevKit version, daemon-backed discovery should use a compatible/current devkitd and return the same live agents as direct discovery.

Root cause

ensureDaemon() returns immediately when DaemonClient.tryConnect() succeeds. It does not compare the running daemon build with the resolved platform package. A detached daemon therefore survives CLI/package upgrades indefinitely and remains authoritative.

daemon.status currently reports the Rust crate version (0.1.0 in this reproduction), which is not sufficient to distinguish platform package releases 0.1.1 and 0.1.2.

Suggested direction

  1. Embed a daemon build identifier compatible with the platform package release (package version and/or git SHA) in daemon.status.
  2. Have ensureDaemon() compare the running daemon identity with the resolved daemon expected by the client.
  3. On mismatch, safely request shutdown, wait for socket removal, then start the resolved binary. If automatic replacement is unsafe, surface a clear warning and provide an explicit daemon restart command.
  4. Add an integration test that starts an older/fake daemon, invokes the current client, and verifies that it replaces or rejects the stale daemon instead of silently accepting it.

Environment

  • macOS ARM64
  • Node.js 26.x
  • Invoking CLI: AI DevKit 0.70.1
  • Running daemon origin: AI DevKit 0.70.0 / platform daemon 0.1.1
  • Fixed platform daemon available: 0.1.2

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions