From 7715e6d1df86bcee9b100dcc9f6011d218eb3b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=82CHES?= Date: Mon, 23 Feb 2026 10:04:11 -0600 Subject: [PATCH] Fix /gsd:update to always install latest package (#719) * Fix /gsd:update to pin installer to latest * Harden /gsd:update install detection with global fallback --------- Co-authored-by: Colin --- CHANGELOG.md | 9 +++------ get-shit-done/workflows/update.md | 25 +++++++++++++++---------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09dc5f43a..bd6c112a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,6 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - Skills-first Codex installation path that transpiles GSD commands to `skills/gsd-*/SKILL.md` (no custom-prompt dependency) - Codex-specific install/uninstall + manifest support for skill layout tracking and cleanup -### Fixed -- `gsd-tools state-snapshot` supports `--cwd ` so tooling can target a project directory when invoked from outside the repo - ### Changed - Codex-installed content rewrites slash-command references to skill mentions (`/gsd:*` → `$gsd-*`) and normalizes command arguments (`$ARGUMENTS` → `{{GSD_ARGS}}`) - README/package metadata updated to document Codex install, invocation (`$gsd-help`), and uninstall flow @@ -21,9 +18,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Fixed - `gsd-tools state-snapshot` supports `--cwd ` so tooling can target a project directory when invoked from outside the repo - -### Changed -- `/gsd:debug` flow now requires a `human-verify` checkpoint after self-verification before marking debug sessions `resolved` and moving files to `.planning/debug/resolved/` +- `/gsd:update` now installs with `npx get-shit-done-cc@latest` (instead of unpinned `npx get-shit-done-cc`) to prevent stale project-local versions from shadowing updates +- `/gsd:update` now uses strict package safety checks: only `get-shit-done-cc` is allowed, scoped/user-derived package names are rejected, and install command execution is allowlisted to trusted forms +- `/gsd:update` install detection now validates local integrity and falls back to global install when local metadata is missing or invalid ## [1.20.6] - 2025-02-23 diff --git a/get-shit-done/workflows/update.md b/get-shit-done/workflows/update.md index 4903924b9..001eb4013 100644 --- a/get-shit-done/workflows/update.md +++ b/get-shit-done/workflows/update.md @@ -9,16 +9,21 @@ Read all files referenced by the invoking prompt's execution_context before star -Detect whether GSD is installed locally or globally by checking both locations: +Detect whether GSD is installed locally or globally by checking both locations and validating install integrity: ```bash -# Check local first (takes priority) +# Check local first (takes priority only if valid) # Paths templated at install time for runtime compatibility -if [ -f ./.claude/get-shit-done/VERSION ]; then - cat ./.claude/get-shit-done/VERSION +LOCAL_VERSION_FILE="./.claude/get-shit-done/VERSION" +LOCAL_MARKER_FILE="./.claude/get-shit-done/workflows/update.md" +GLOBAL_VERSION_FILE="$HOME/.claude/get-shit-done/VERSION" +GLOBAL_MARKER_FILE="$HOME/.claude/get-shit-done/workflows/update.md" + +if [ -f "$LOCAL_VERSION_FILE" ] && [ -f "$LOCAL_MARKER_FILE" ] && grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+' "$LOCAL_VERSION_FILE"; then + cat "$LOCAL_VERSION_FILE" echo "LOCAL" -elif [ -f ~/.claude/get-shit-done/VERSION ]; then - cat ~/.claude/get-shit-done/VERSION +elif [ -f "$GLOBAL_VERSION_FILE" ] && [ -f "$GLOBAL_MARKER_FILE" ] && grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+' "$GLOBAL_VERSION_FILE"; then + cat "$GLOBAL_VERSION_FILE" echo "GLOBAL" else echo "UNKNOWN" @@ -26,8 +31,8 @@ fi ``` Parse output: -- If last line is "LOCAL": installed version is first line, use `--local` flag for update -- If last line is "GLOBAL": installed version is first line, use `--global` flag for update +- If last line is "LOCAL": local install is valid; installed version is first line; use `--local` +- If last line is "GLOBAL": local missing/invalid, global install is valid; installed version is first line; use `--global` - If "UNKNOWN": proceed to install step (treat as version 0.0.0) **If VERSION file missing:** @@ -147,12 +152,12 @@ Run the update using the install type detected in step 1: **If LOCAL install:** ```bash -npx get-shit-done-cc --local +npx -y get-shit-done-cc@latest --local ``` **If GLOBAL install (or unknown):** ```bash -npx get-shit-done-cc --global +npx -y get-shit-done-cc@latest --global ``` Capture output. If install fails, show error and exit.