feat: add ctx self-update and release/update mechanism#11
Merged
Conversation
…ement - ctx self-update [--version X.Y.Z]: queries the GitHub Releases API, picks the artifact for the compile-time target (mirroring the release build matrix), verifies its sha256 against the release's aggregated SHA256SUMS file (mismatch aborts with exit 2, binary untouched), and atomically renames the extracted binary over the running executable (Windows: rename-aside to ctx.exe.old, cleaned up on the next run). Unwritable install locations are refused with guidance before any network work. --json emits a self_update envelope. - Passive update notice: interactive runs check at most once per 24h (timestamp cache under the user cache dir), 1s timeout, silent failure, one stderr line. Suppressed entirely (no network call) by CTX_NO_UPDATE_CHECK, non-TTY stderr, --json, Claude Code hook env vars (CLAUDECODE, CLAUDE_PROJECT_DIR, CLAUDE_PLUGIN_ROOT), and for self-update/--version invocations. Never updates automatically. - ctx --version --check: explicit comparison on stdout, exempt from suppression and the 24h cache; clap's auto version flag is replaced by an equivalent custom flag (plain --version/-V output unchanged). - Tests: unit coverage for the artifact mapping, SHA256SUMS parsing, cache clock, suppression matrix, extraction, and atomic replace; end-to-end CLI tests against a hand-rolled mock HTTP server in testutil (CTX_UPDATE_BASE_URL/CTX_CACHE_DIR/CTX_UPDATE_FORCE_TTY test hooks), replacing a copied binary, never the real one.
- Releases now attach one aggregated SHA256SUMS file over all artifacts (consumed by ctx self-update; per-artifact .sha256 files are kept). - New plugin job runs scripts/release-plugin-check.sh: builds the binary, scaffolds the plugin with 'ctx harness init --mode plugin' into a scratch dir, fails the release when the generated plugin.json version differs from the tag (lockstep is by construction; this asserts it), and attaches the scaffold as ctx-claude-plugin-<version>.zip. The script is locally runnable.
- docs/commands/self-update.md (+ website mirror and sidebar entry): update flow, checksum verification, passive-notice suppression rules, /plugin update as the plugin update path, sha-pinning the marketplace entry for frozen installs, exit codes. - docs/json-output.md (+ website copy): self_update and version.check envelopes. - README: 'Updating' subsection under Installation (self-update, CTX_NO_UPDATE_CHECK, /plugin update, sha-pinning, and the no-silent-updates determinism rule). - CHANGELOG: Unreleased entries for the release & update mechanism.
# Conflicts: # src/commands/mod.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Feature H — the final feature of the Quality Intelligence Suite. Stacked on #9 (
feat/harness) — review the top 3 commits until #9 merges.Determinism rule throughout: no automatic updates, ever — ctx is a quality gate, so gate semantics never change without explicit user action.
ctx self-update [--version X.Y.Z]: queries GitHub Releases, downloads the platform artifact, verifies sha256 against the release'sSHA256SUMS(mismatch → exit 2, binary untouched), and atomically replaces the executable with a writability preflight.--jsonsupported.CTX_NO_UPDATE_CHECK, non-TTY stderr,--json, or Claude Code hook env vars — notices can never leak into model context.ctx --version --check: explicit, cache-exempt comparison; plainctx --versionoutput is byte-identical to before (snapshot-tested).SHA256SUMSrelease asset + a new gate job runningscripts/release-plugin-check.sh(locally runnable) — it generates the plugin scaffold from the release binary, fails the release ifplugin.json≠ tag version, and attachesctx-claude-plugin-<version>.zip. Plugin/binary lockstep is by construction.ctx self-update,/plugin update,CTX_NO_UPDATE_CHECK, marketplace sha-pinning for frozen installs),self-updatecommand page + JSON payloads documented.tar(runtime extraction) and windows-onlyzip— both already in Cargo.lock transitively; reqwest gains theblockingfeature. The mock release server for tests is hand-rolled std-only.Test plan
--check).clippy -D warnings,fmt --check,--no-default-features+--features mcpbuilds, docsnpm run build— all clean.scripts/release-plugin-check.sh: OK (0.2.1 == 0.2.1).🤖 Generated with Claude Code