fix(cli): rebuild on stale dist, not just SHA advance, in ao update#2058
fix(cli): rebuild on stale dist, not just SHA advance, in ao update#2058suraj-markup wants to merge 4 commits into
Conversation
`ao update` only rebuilt when `git fetch` advanced the local SHA. If dist fell out of sync with src at the *same* commit — a manual `git pull`, a branch switch, an interrupted earlier build, or a manual `pnpm clean` — the script printed "Already on latest version" and skipped the rebuild, leaving the running binary built from stale source. Gate the rebuild on whether the compiled output is actually in sync with HEAD instead. A gitignored `node_modules/.ao-build-sha` marker records the commit dist was last built from (written only after a fully successful build + launcher refresh), and a build-output existence check catches a wiped dist even when the marker still matches. Add `ao update --force-rebuild` to rebuild on demand. Mirrored in the PowerShell port and wired through update.ts (rejected on non-git installs, like the other build-only flags). Updates the already-latest test to require a fresh build and adds stale-marker and --force-rebuild coverage. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Greptile SummaryThis PR fixes
Confidence Score: 5/5Safe to merge — the rebuild-gate logic is correct in both the bash and PowerShell scripts, cross-platform marker reads/writes interoperate correctly, and the new flag is properly validated and plumbed through the TypeScript command layer. The change is well-scoped: it replaces a single SHA-advance condition with a three-condition check, writes the marker only after a fully successful build+link+clean sequence, and the PowerShell port mirrors the bash changes faithfully. Bash command substitution correctly strips trailing newlines so SHA comparisons are reliable; the PowerShell .Trim() handles both LF and no-newline variants. The new tests cover the key new scenarios and all existing tests continue to pass per the PR description. No files require special attention.
|
| Filename | Overview |
|---|---|
| packages/cli/src/assets/scripts/ao-update.sh | Adds BUILD_SHA_FILE marker, 28-path sentinel array, rebuild-decision logic, and write_built_sha (called only after fully successful build). Logic is correct: bash command substitution strips trailing newlines so SHA comparisons are safe, and all_build_outputs_present |
| packages/cli/src/assets/scripts/ao-update.ps1 | PowerShell port mirrors the bash changes: adds $ForceRebuild flag, Read-BuiltSha/Write-BuiltSha helpers, Get-MissingBuildOutput, and the same three-condition rebuild gate. Cross-reads are handled correctly in both directions. |
| packages/cli/src/commands/update.ts | Adds --force-rebuild Commander option, correctly rejects it for non-git installs alongside --skip-smoke and --smoke-only, extends handleGitUpdate opts type, and pushes the flag into the script args array. |
| packages/cli/tests/scripts/update-script.test.ts | Existing process.platform === 'win32' inline checks replaced with isWindows() (cross-platform guide compliant). Three new tests cover: fresh-build skip, stale-marker rebuild, and --force-rebuild override. |
| .github/workflows/ci.yml | All action references pinned to full commit SHAs, eliminating mutable tag risk. No functional workflow changes. |
| .changeset/ao-update-rebuild-staleness.md | Correct patch-level changeset for @aoagents/ao-cli describing the staleness fix accurately. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[ao update invoked] -->|non-git install + flag| B[Error: flag only applies to git installs]
A -->|git install| C[git fetch origin main]
C --> D{local SHA == remote SHA?}
D -->|No| E[git pull --ff-only\nupdate local_sha]
D -->|Yes| F[Skip pull]
E --> G
F --> G[Read node_modules/.ao-build-sha]
G --> H{--force-rebuild?}
H -->|Yes| I[rebuild_reason = forced via --force-rebuild]
H -->|No| J{Any sentinel\nmissing?}
J -->|Yes| K[rebuild_reason = build output missing]
J -->|No| L{built_sha == local_sha?}
L -->|No| M[rebuild_reason = build is stale]
L -->|Yes| N[Already on latest version;\nbuild is up to date]
I --> O[pnpm install + clean + build\nnpm link --force]
K --> O
M --> O
O --> P[ensure_repo_clean]
P -->|clean| Q[write_built_sha HEAD]
P -->|dirty| R[Error: update modified tracked files]
Q --> S[Run smoke tests]
N --> S
Reviews (3): Last reviewed commit: "Address ao update script review nits" | Re-trigger Greptile
What
ao update(git / source installs) only rebuilt whengit fetchadvanced the local SHA. Ifdist/was out of sync withsrc/at the same commit, the script printedAlready on latest versionand skipped the rebuild — so the running binary kept executing stale compiled code.Causes of a stale
dist/at HEAD:git pullbeforeao update(HEAD already matches remote → no rebuild)pnpm cleanCloses #2057.
How
Gate the rebuild on whether the compiled output is in sync with HEAD, not on the SHA advancing:
node_modules/.ao-build-sharecords the commitdist/was last built from, written only after a fully successful build + launcher refresh.dist/), or--force-rebuildis passed.ao update --force-rebuildforces a rebuild on demand.Mirrored in the PowerShell port (
ao-update.ps1) and wired throughupdate.ts(rejected on non-git installs, like the other build-only flags).Tests
--force-rebuildwhen the build is already fresh.ao-cliupdate suite green (192 passed, 4 Windows-only skipped); prettier + typecheck clean.🤖 Generated with Claude Code