Skip to content

add verified updates and rollback for compiled installs - #2166

Open
kevinjosethomas wants to merge 8 commits into
feat/eng-6046-native-migrationfrom
feat/eng-6047-native-updates
Open

add verified updates and rollback for compiled installs#2166
kevinjosethomas wants to merge 8 commits into
feat/eng-6046-native-migrationfrom
feat/eng-6047-native-updates

Conversation

@kevinjosethomas

@kevinjosethomas kevinjosethomas commented Sep 9, 2026

Copy link
Copy Markdown
Member

This is part of the PR stack migrating us to use Bun to compile Prime Agent for releases. This makes supported installations self-contained, removing the need to download and install Node.js and npm packages separately.

This PR adds updates and rollback for compiled installations. Users update through the usual command, downloads are checked before activation, and restarted sessions use the new version. Prime Agent keeps the previous compiled release so users can switch back without downloading it again.

Tested updates between simulated Bun-compiled releases, offline rollback, corrupt downloads, simultaneous updates, and interrupted updates. The combined stack passed 109 of 110 scenarios; the remaining case was the existing npm 12 restriction, with tested recovery. Forced termination can require manual recovery. The final release-metadata fix passed 44 targeted tests.

ENG-6047 · Stack: #2140#2165#2166.

Note

Add verified updates and offline rollback for compiled installs

  • getNativeUpdatePlan resolves the latest release, selects matching native artifacts, and produces a verified install command or offline rollback command.
  • prime_agent_native_rollback validates the retained previous release directory and assets, then activates it without downloading.
  • prime_agent_install_native aborts the download if the release manifest checksum does not match the planner-supplied checksum.
  • getLatestPiRelease isolates malformed native artifact metadata, dropping it so npm updates still work while native update planning rejects the release.
  • Risk: Native artifacts with non-lowercase 64-character hex checksums or duplicate platforms are rejected by getLatestPiRelease, falling back to npm metadata only.

Macroscope summarized ee33a74.


Note

Medium Risk
Changes the self-update and release-activation path for compiled installs, including checksum gates and symlink swapping, but failed validation leaves the active release unchanged and rollback is limited to managed installs.

Overview
Adds managed compiled self-update and offline rollback so prime-agent update no longer depends on npm when running from an installer-owned Bun binary.

Compiled updates resolve the channel release, require a validated platform entry in the manifest (binaries with matching SHA-256), and invoke the bundled install.sh with guards like PRIME_AGENT_EXPECTED_CURRENT and PRIME_AGENT_EXPECTED_SHA256. update --rollback switches back to the retained bin/previous release without downloading; the installer validates the previous directory and assets before activation. install.sh --rollback implements the same path for non-interactive use.

The CLI wires --rollback through public commands and package self-update, routes Bun installs through getNativeUpdatePlan, and uses createUpdatedCliSubprocessLaunchSpec so interactive updates and daemon restart coordinators relaunch via the stable managed launcher after activation. getLatestPiRelease now parses optional native artifact metadata but drops the whole binaries list when any entry is invalid, so bad compiled metadata does not block npm updates while native planning still rejects unverified archives.

Documentation and regression tests cover verified updates, offline rollback, manifest/checksum failures, interrupted rollback, and end-to-end flows on real archives.

Reviewed by Cursor Bugbot for commit ee33a74. Bugbot is set up for automated code reviews on this repo. Configure here.

@kevinjosethomas
kevinjosethomas changed the base branch from main to feat/eng-6046-native-migration September 9, 2026 22:32
Comment thread install.sh
@kevinjosethomas
kevinjosethomas changed the base branch from feat/eng-6046-native-migration to main September 9, 2026 22:41
@kevinjosethomas
kevinjosethomas changed the base branch from main to feat/eng-6046-native-migration September 9, 2026 22:43
@kevinjosethomas
kevinjosethomas changed the base branch from feat/eng-6046-native-migration to main September 9, 2026 23:07
kevinjosethomas added a commit that referenced this pull request Sep 9, 2026
@kevinjosethomas
kevinjosethomas changed the base branch from main to feat/eng-6046-native-migration September 9, 2026 23:11
@kevinjosethomas
kevinjosethomas changed the base branch from feat/eng-6046-native-migration to main September 9, 2026 23:30
@kevinjosethomas
kevinjosethomas changed the base branch from main to feat/eng-6046-native-migration September 9, 2026 23:30
@kevinjosethomas
kevinjosethomas changed the base branch from feat/eng-6046-native-migration to main September 9, 2026 23:32
kevinjosethomas added a commit that referenced this pull request Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Prime Agent performance — completed

PR ee33a74a compared with main 1eee2938.

Overall: 0 regressed · 0 improved · 17 no clear change.

Metric Main This PR Change
Cold startup 2,954.8 ms 2,740.8 ms ≈ -214.0 ms (-7.24%)
Warm startup 1,736.2 ms 1,652.0 ms ≈ -84.2 ms (-4.85%)
Installation 27.34 s 25.78 s ≈ -1.56 s (-5.70%)
Compressed release artifacts 11.12 MB 11.14 MB ≈ +0.02 MB (+0.21%)
Installed footprint 597.49 MB 597.58 MB ≈ +0.09 MB (+0.02%)
Idle memory, summed RSS 1,075.84 MB 1,042.45 MB ≈ -33.39 MB (-3.10%)

Python runtime

Metric Main This PR Change
Python kernel startup 124.8 ms 123.7 ms ≈ -1.1 ms (-0.88%)
Python cell round trip 0.493 ms 0.475 ms ≈ -0.019 ms (-3.76%)
Empty bash command 11.3 ms 10.4 ms ≈ -0.9 ms (-8.15%)
Bash git status 16.7 ms 15.4 ms ≈ -1.3 ms (-7.90%)
Bash 32 KiB output 12.0 ms 10.9 ms ≈ -1.1 ms (-9.03%)
35 cells / 9 shell calls 164.3 ms 159.1 ms ≈ -5.2 ms (-3.14%)
Python interrupt to done 1.490 ms 1.424 ms ≈ -0.067 ms (-4.47%)
Python state snapshot 26.3 ms 24.5 ms ≈ -1.8 ms (-6.68%)
Python state restore 357.5 ms 326.6 ms ≈ -30.9 ms (-8.65%)
Python idle RSS 35.61 MB 33.83 MB ≈ -1.78 MB (-5.01%)
Python RSS after pandas workload 97.70 MB 97.79 MB ≈ +0.09 MB (+0.09%)

Sandbox cost: ~$0.0877 — no inference calls.
Run, logs, and downloadable raw results

Methodology and samples

Main resolved at 2026-09-11T01:35:35.784512+00:00. Harness 1eee2938.
Linux x64, 4 vCPU, 8 GB RAM, 20 GB disk; region us.
Image: node:24-bookworm@sha256:be23f54a88d34e8824c741b19b91064094f92c1c97b194144bfc8b50d67258e2.
Stock tools, skills, daemon, and Python bootstrap enabled; fresh homes and a fixed Git fixture.
Onboarding is dismissed; the editor starts without a selected model or submitted prompt.
Medians shown. Arrows require a 20% timing/memory change plus absolute floors and IQR.
These practical noise floors are not a statistical significance test.
Cold means stopped Prime processes; OS filesystem caches are not flushed.
No model requests or credentials. Installation excludes build/setup time.
Installer tarballs use loopback; npm/Python downloads use the network with fresh caches.
Artifact size counts release tarballs; footprint after first use includes registry packages.
MB is decimal. Summed RSS can double-count shared pages; PSS is recorded when available.
Provisioning, setup, and build durations are recorded separately in the raw results.
Kernel probes use the installed JSONL runtime, outside the TUI/TypeScript host.
Per trial: 50 Python cells, 5 calls per shell case, and one 35-cell mix (9 git status calls).
Cell/shell values are batch means; other runtime timings are single operations.
State fixture: a 10,000-row × 8-column integer DataFrame and a 10,000-integer list.
Restore runs in a fresh kernel, including pandas imports; kernel startup is excluded.
Kernel RSS covers the isolated Python process; loaded RSS follows the pandas workload.
Costs estimate full sandbox lifetimes at configured rates, including setup and build.
Budget target: $1; not a billing cap. Checks are informational.

Metric Main successful/attempted PR successful/attempted Main spread PR spread
Cold startup 10/10 10/10 IQR 85.7 ms IQR 66.0 ms
Warm startup 10/10 10/10 IQR 59.1 ms IQR 56.8 ms
Installation 3/3 3/3 range 2.54 s range 0.37 s
Compressed release artifacts 1/1 1/1
Installed footprint 1/1 1/1
Idle memory, summed RSS 10/10 10/10 IQR 99.37 MB IQR 23.80 MB
Python kernel startup 10/10 10/10 IQR 5.3 ms IQR 5.1 ms
Python cell round trip 10/10 10/10 IQR 0.045 ms IQR 0.019 ms
Empty bash command 10/10 10/10 IQR 0.8 ms IQR 0.7 ms
Bash git status 10/10 10/10 IQR 1.2 ms IQR 1.6 ms
Bash 32 KiB output 10/10 10/10 IQR 0.7 ms IQR 0.7 ms
35 cells / 9 shell calls 10/10 10/10 IQR 9.0 ms IQR 13.1 ms
Python interrupt to done 10/10 10/10 IQR 0.110 ms IQR 0.189 ms
Python state snapshot 10/10 10/10 IQR 2.2 ms IQR 1.3 ms
Python state restore 10/10 10/10 IQR 21.1 ms IQR 8.0 ms
Python idle RSS 10/10 10/10 IQR 4.60 MB IQR 4.73 MB
Python RSS after pandas workload 10/10 10/10 IQR 5.12 MB IQR 4.97 MB

kevinjosethomas added a commit that referenced this pull request Sep 9, 2026
@kevinjosethomas
kevinjosethomas changed the base branch from main to feat/eng-6046-native-migration September 9, 2026 23:55
@kevinjosethomas
kevinjosethomas changed the base branch from feat/eng-6046-native-migration to main September 10, 2026 01:32
Comment thread install.sh Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fccd033. Configure here.

Comment thread packages/coding-agent/src/utils/version-check.ts Outdated
@kevinjosethomas
kevinjosethomas force-pushed the feat/eng-6047-native-updates branch from 38cfd42 to e441b97 Compare September 10, 2026 23:42
@snimu

snimu commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

releases/ directory growth: Every update and every --force reinstall adds a releases/-- directory (~100MB class), and nothing ever prunes it — only the bin/prime-agent and bin/previous symlinks are re-pointed. A SIGKILL additionally leaks fully-staged .install.XXXXXX staging dirs, and there is no cap, sweep, or cleanup tooling anywhere. The install path (#2140) has the same never-pruned pattern, so the update machinery is the natural single owner for pruning both: keep current + previous, and sweep the rest plus orphaned staging dirs on successful activation.

[written by prime-agent, checked by snimu]

@snimu

snimu commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

prime_agent_native_activate (install.sh:1817-1826): A SIGKILL between the two atomic renames during an update leaves bin/previous stale — pointing at the release from two updates back, or missing entirely after a first update — so a later rollback silently restores the wrong version. Docs and tests cover only the kill-during-ROLLBACK variant, not kill-during-update.

[written by prime-agent, checked by snimu]

@snimu

snimu commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

--rollback verification gap (install.sh:1752-1772): A direct install.sh --rollback can activate a tampered or corrupt previous release, and afterwards all updates fail with the misleading 'not owned by the installer' lockout. The planner-side rollback re-verifies, but the direct invocation does not: it never re-checks .archive-sha256/package.json against the release-dir name, nor compares the binary's --version output to the directory version. Please run the same verification the planner does before activating a rollback target.

[written by prime-agent, checked by snimu]

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants