feat(install): reject bare base version instead of normalizing to -1

Merged
PI
4mo ago
+9-8

What

A packaging release is always <base>-<N> (e.g. 1.17.9-1). Previously the installer silently normalized a bare base version (1.17.9) to <base>-1. This rejects it loudly instead:

Error: version '1.17.9' needs a packaging patch suffix (did you mean 1.17.9-1?)
Pin an exact release tag: https://github.com/replohq/replopencode/releases

Why

A legacy v1.17.9 tag also exists on the fork, so a bare 1.17.9 is genuinely ambiguous — silently picking -1 guesses which artifact the caller meant. This makes the resolver consistent with the missing-tag behavior (also a hard error, no fallback): what you pin is what you get, or a loud error — no silent inference.

Blast radius

None for our paths. Every real caller already passes the full pin:

  • Daytona Dockerfile → VERSION=${OPENCODE_VERSION} = 1.17.9-1
  • sandbox-upgrader converge entry → 1.17.9-1

Only an interactive --version/VERSION= pin of a bare base is affected, and that now gets a helpful error. The no-arg curl|bash (latest) path is untouched.

Verification

  • bare 1.17.9 and v1.17.9 (via VERSION= and --version) → exit 1, loud error, no download
  • 1.17.9-1, 1.17.9-rc.1 → proceed
  • bash -n clean

Summary by cubic

Installer now rejects bare base versions (e.g. 1.17.9) instead of normalizing to -1, requiring exact pins like 1.17.9-1 to avoid ambiguous tags. Shows a clear error with a “did you mean …-1?” hint; scripted callers that already pass full pins are unaffected.