7.8 KiB
GStack 2 upgrade and rollback
Skill placement and the optional runtime have different lifecycles. Do not reintroduce host-specific setup by coupling them. Standard skill installation remains Markdown-only; runtime dependencies are never smuggled into that path.
Skill updates
Install and update the canonical Agent Skills source with the same standard installer that placed it:
npx skills add time-attack/gstack
Use that installer's update/remove commands and scope. It owns project/global placement, host destination paths, and selected-skill choices. GStack must not re-detect hosts during an update or enroll a host/skill the user did not previously select.
Before accepting an update, list the source and confirm that the defaults are
still exactly plan, design, qa, debug, review, and ship. Pure
judgment must remain usable even if the optional runtime update fails.
1.x command migration
The complete old-to-new map is SKILL-MIGRATION.md. Opt-in compatibility aliases are retained for two minor releases or 90 days from the 2.0 release, whichever policy the release notes identify. Each alias:
- prints the canonical replacement;
- routes to the exact preserved specialist module;
- contains no copied judgment; and
- stays outside default skill discovery.
Examples:
/office-hours -> /plan --mode product
/plan-eng-review -> /plan --mode eng
/design-review -> /design --mode live-review
/qa-only -> /qa --mode report
/investigate -> /debug --mode investigate
/cso -> /review --mode security
/land-and-deploy -> /ship --mode land
Existing safe preferences may migrate. Context.dev choice and data-egress consent must never be inferred from legacy browser, telemetry, service, or update-check settings. Leave Context network mode off until the user explicitly selects it.
Initial managed runtime install
From a reviewed repository checkout, install only the optional runtime and local capability bundle with:
./setup
Skill placement remains a separate standard-installer operation. ./setup
resolves a symlinked source checkout, installs frozen production-only
dependencies, and invokes runtime/install.js. The installer copies an explicit allowlist
into an immutable version, rejects internal symlinks and path escapes, records
size/mode/SHA-256 for every file, validates capability targets, smoke-tests the
CLI, then atomically activates it. Stable POSIX and Windows launchers are
written under $GSTACK_HOME/bin (default ~/.gstack/bin), alongside
runtime-install.json, which distinguishes managed paths from preserved
config, secrets, projects, and plans.
Twenty-one focused installer tests pass with 307 assertions. They cover paths with spaces, a symlinked source root, internal-link rejection, runtime-only builder selection, production dependency closure, failed build/validation/ smoke rollback, interrupted recovery, launchers, manifests, wrapper neutrality, and state-preserving uninstall.
The current managed-bundle audit records 107 components, 1,830 files, 459,056,031 bytes, and 50 launchers. The Sharp/ngrok closure is included. The development-only Claude Agent SDK and Hugging Face sidecar are excluded; the Hugging Face package is development-only. Setup therefore installs neither its inference runtime nor model weights and reports the L4 capability unavailable.
A separate clean Linux arm64 container smoke copied the source through a path with spaces, installed only frozen production dependencies with the development SDK absent, rebuilt runtime capabilities without Git history or skill regeneration, passed setup/doctor/version/design/PDF checks, completed a local browser journey and Sharp full-page screenshot, and uninstalled while preserving state. Non-Darwin bundles omit the physical-iOS capability. Native Windows execution remains a separate gate; source-level Windows launchers are not native evidence.
Runtime upgrade transaction
The candidate runtime intentionally does not combine “download arbitrary code” with activation. Give it a reviewed staged directory and an explicit version:
gstack upgrade --source /path/to/verified-runtime --version 2.0.1
The transaction is:
validate version and source
-> lock upgrade state
-> recover any interrupted pending transaction
-> copy to a unique stage directory
-> write stage metadata
-> run verification when supplied
-> atomically rename stage to immutable version directory
-> write pending pointer with last-known-good
-> run health check
-> atomically mark pointer active
If copy/verification fails, the stage directory is removed and the active
pointer is unchanged. If health fails, the previous pointer is restored and
the command returns UPGRADE_ROLLED_BACK. If the process dies after writing a
pending pointer, the next upgrade/cleanup/doctor path recovers the last known
good version before selection.
The runtime uses one per-user version store, not one copy per AI host. Skill install failure and runtime install failure are independent; neither may erase the other.
Manual rollback
Inspect health first:
gstack doctor
gstack doctor --json
Roll back to the retained last-known-good version:
gstack upgrade --rollback
Rollback validates that the retained directory exists, optionally health-checks it in the library call, atomically switches the pointer, and retains the version rolled back from as the next fallback. If no fallback exists it fails with an actionable error rather than choosing an arbitrary directory.
Runtime state schemas migrate forward only. If a state or migration marker is
newer than the running runtime, stop with STATE_NEWER_THAN_RUNTIME or
MIGRATION_NEWER_THAN_RUNTIME; never downgrade or rewrite the newer data.
Recovery after interruption
- Do not delete
~/.gstack/versions/current.jsonwhile diagnosing. - Run
gstack doctor --jsonand preserve the output with secrets removed. - Run
gstack cleanup --dry-runto preview only stale managed temporaries. - Retry the upgrade command. It recovers a pending pointer before staging.
- If the candidate remains unhealthy, use
gstack upgrade --rollback. - Inspect the current worktree's run state with
gstack state inspect. - Resume only the named/current-worktree run. An external effect left
uncertainmust be reconciled; do not clear the marker and repeat it blindly.
Cleanup skips symlinks and user-named data, and removes only recognized stale
runtime temporaries/locks. --dry-run is non-mutating.
Uninstall
Use the standard installer to remove skills. Separately, remove managed runtime versions while preserving configuration, secrets, and project history:
gstack uninstall
Purge all runtime state only after reviewing the path and accepting data loss:
gstack uninstall --purge --yes
The runtime refuses unsafe roots such as the filesystem root or home directory. It does not remove host skills, browser profiles, unrelated apps, repositories, or iPhone data.
Evidence state
Focused candidate tests cover the managed installer plus atomic activation,
failed-health rollback, interrupted-pointer recovery, manual rollback,
newer-schema refusal, and non-mutating cleanup preview. The standard installer
matrix separately passed 470/470 checks across six hosts, 16 installs, scopes,
selections, and two removals; its artifact is
evals/installation/install-matrix.json.
The runtime installer is green at 21 pass / 0 fail and 307 assertions, and the
current 107-component bundle audit is recorded. The clean Linux Dev Container
install/uninstall smoke passed. Interrupted network acquisition/stage at OS
level, a passing live v3 host run, actual host UI execution, native-host Linux,
and native Windows runs remain gates. See
TEST-EVIDENCE.md.