Skip to content

Retroactive spec: self-upgrade subcommand (agent-init upgrade) #76

Description

@Lillevang

Retroactive spec for the work in PR #73, which was implemented without an up-front issue. This captures the goal, the design decisions the implementing agent made, and the assumptions baked into the code so the decision trail exists.

Goal

Add agent-init upgrade — update the installed CLI binary in place from the latest GitHub release. Opt-in and manual; normal commands make no network calls.

What was implemented (PR #73)

  • New internal/selfupdate/ package (github.go, selfupdate.go), wired into internal/cli/cli.go, documented in docs/cli.md and README.md.
  • Flags: --check (report if a newer release exists, no download), --dry-run (download + verify checksum, don't swap), --force (reinstall when current, or upgrade a dev build).
  • Reads releases/latest via the GitHub API (uses GITHUB_TOKEN/GH_TOKEN if set to lift the anonymous rate limit), selects the asset matching host OS/arch, downloads it plus checksums.txt, verifies SHA-256 before touching anything, extracts from tar.gz/zip, resolves the real install path via os.Executable() + symlink resolution, and swaps via atomic write-temp-then-rename with a move-aside fallback. Checksum mismatch aborts and leaves the existing binary untouched.
  • Stdlib-only, no new go.mod dependencies. Hermetic tests cover semver compare, asset/binary naming, checksum match/mismatch/missing, tar.gz + zip extraction, and full flows.

Confirmed design decisions (see decisions.md)

  1. Manual-only, no automatic update check, ever. No background checks, no per-invocation network call, no nag. You opt in by running the command. Preserves the offline-first stance.
  2. In-place binary replacement as the update model (vs. telling the user to re-run the install script or go install), with checksum-before-swap and atomic replace.

Assumptions baked into the code (verify / track)

  • Release assets are named agent-init-<os>-<arch>.tar.gz/.zip with a sibling checksums.txt. True today against release.yml, but now a silent coupling — any change to the release workflow's asset naming breaks upgrade.
  • The supported platform set is exactly the release matrix (linux amd64/arm64, darwin arm64, windows amd64). Intel Macs (darwin/amd64) hit a "no asset for platform" error. Decide whether that's acceptable or needs a clearer message / matrix change.
  • dev builds refuse to upgrade without --force. Reasonable, but a behavior choice made by the agent.

Out of scope / separate items

  • Go 1.26.4 toolchain bump to clear the stdlib vuln (GO-2026-5037/5039) surfaced by the new net/http path — separate issue.
  • darwin/amd64 (Intel Mac) release coverage, if wanted — separate change to the release matrix.

Pre-merge cleanups for PR #73

  • Reconcile the .agent/CODEBASE.md drift (the regenerated codemap removes three internal/scaffold/color_test.go entries with no matching source change in the diff).
  • Confirm the check.sh / CI gate runs green on the PR head.

Milestone: CI/Release Hardening.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliCLI surface, flags, help outputarea:securitySecrets, credentials, sandbox postureenhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions