Receber por email
← Voltar para o catálogo

update-gaia

Pull the latest GAIA release into this project without clobbering customizations. Three-way merge per file using .gaia/manifest.json classes. Trigger when the user clicks the statusline `Run /update-gaia` indicator or asks "update GAIA", "pull the latest GAIA", "apply the new GAIA release".

15estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add gaia-react/gaia

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/update-gaia/svg)](https://www.skillteca.com.br/skills/update-gaia)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Pull the latest GAIA release into this project without clobbering customizations. Does a three-way comparison per file (adopter / baseline / latest) and respects explicit classes in .gaia/manifest.json:

  • owned — GAIA controls fully. Overwrites silently if unchanged from baseline; prompts if drifted.
  • shared — GAIA seeds, you customize. Emits a .gaia-merge/ patch for manual resolution on drift.
  • wiki-owned — GAIA-seeded concept/decision/module wiki pages. Same drift handling as shared.
  • adopter-owned (implicit) — anything not in the manifest, plus sentinels like wiki/hot.md, wiki/log.md, CHANGELOG.md, .gaia/VERSION, .gaia/manifest.json. Never touched.

Backups land in .gaia-backup/<timestamp>/. Conflict patches land in .gaia-merge/.

Pre-flight: Worktree check

This wrapper changes .gaia/VERSION and opens a PR — both belong on the main checkout, not a per-SPEC worktree branch. If invoked from a linked worktree, reject hard with a message that surfaces the cached version state from main so the user knows whether a GAIA update is even pending.

Detection (run this first, before anything else):

common_dir="$(git rev-parse --git-common-dir 2>/dev/null)"
if [ -n "$common_dir" ]; then
  case "$common_dir" in
    /*) absolute_common_dir="$common_dir" ;;
    *)  absolute_common_dir="$(pwd)/$common_dir" ;;
  esac
  main_root="$(cd "$(dirname "$absolute_common_dir")" 2>/dev/null && pwd)"
  current_root="$(git rev-parse --show-toplevel 2>/dev/null)"
  if [ -n "$main_root" ] && [ -n "$current_root" ] && [ "$main_root" != "$current_root" ]; then
    cached_line="Cached state unavailable on main; symlinks may be broken — run \`gaia setup link-worktree\` to repair."
    cache_file="$main_root/.gaia/cache/update-check.json"
    if [ -f "$cache_file" ] && command -v jq >/dev/null 2>&1; then
      gaia_current="$(jq -r '.gaiaCurrent // ""' "$cache_file" 2>/dev/null)"
      gaia_latest="$(jq -r '.gaiaLatest // ""' "$cache_file" 2>/dev/null)"
      gaia_has_update="$(jq -r '.gaiaHasUpdate // false' "$cache_file" 2>/dev/null)"
      if [ -n "$gaia_current" ] && [ -n "$gaia_latest" ]; then
        update_phrase="not-available"
        if [ "$gaia_has_update" = "true" ]; then update_phrase="available"; fi
        cached_line="Cached on main: GAIA $gaia_current installed; latest $gaia_latest (update $update_phrase)."
      fi
    fi
    cat <<EOF
/update-gaia must run from the main checkout, not a worktree.

Worktree:       $current_root
Main checkout:  $main_root

$cached_line

Run \`cd $main_root\` then re-invoke /update-gaia.
EOF
    exit 1
  fi
fi

If the detection does not fire, fall through to the existing ## Pre-flight: Branch check section.

Pre-flight: Branch check

git branch --show-current

If the current branch is main or master, create and switch to a new branch:

git checkout -b chore/update-gaia-$(date +%Y-%m-%d-%H-%M)

Otherwise proceed on the current branch.

Step 1: Read baseline version

cat .gaia/VERSION 2>/dev/null || echo MISSING

If the file is missing, stop and tell the user:

"No .gaia/VERSION found — this project was not scaffolded from GAIA, or the marker was deleted. Run /gaia-init on a fresh create-gaia scaffold first."

Persist the trimmed version as BASELINE (e.g., 1.0.0).

Step 2: Resolve latest release

gh release list --repo gaia-react/gaia --limit 1 --json tagName --jq '.[0].tagName'

Persist as LATEST_TAG (e.g., v1.0.1) and LATEST (strip leading v).

If gh is unavailable, fall back to:

curl -fsSL https://api.github.com/repos/gaia-react/gaia/releases/latest | jq -r .tag_name

If both fail, stop and ask the user to supply the target version explicitly.

Step 3: Compare versions

  • If LATEST == BASELINE → print "You are up to date on GAIA v$BASELINE." and exit.
  • If semver(LATEST) < semver(BASELINE) → print a warning that the installed version is ahead of the latest release and exit. Never downgrade.

Step 4: Show the release notes and confirm

Fetch the release body for LATEST_TAG:

gh release view "$LATEST_TAG" --repo gaia-react/gaia --json body --jq .body

Print the notes to the user. Then use AskUserQuestion:

  • Question: "Update GAIA from v$BASELINE to $LATEST_TAG?"
  • Options: Proceed / Abort.

On Abort, exit cleanly with no filesystem changes.

Model selection

After the user confirms, determine the model for the execution agent:

  • Compare LATEST major vs BASELINE major (leading integer).
  • Major bump → spawn an Opus agent (model: "opus").
  • Minor or patch bump → spawn a Sonnet agent (model: "sonnet").

Spawn the agent for Steps 5–10, passing BASELINE, LATEST, and LATEST_TAG as context.

Steps 5–10 (execution agent)

Step 5: Fetch baseline and latest tarballs

Cache under .gaia/cache/ (gitignored) so repeated runs don't redownload:

mkdir -p .gaia/cache
for tag in "v$BASELINE" "$LATEST_TAG"; do
  dir=".gaia/cache/$tag"
  if [ ! -d "$dir" ]; then
    mkdir -p "$dir"
    gh release download "$tag" \
      --repo gaia-react/gaia \
      --pattern "gaia-${tag}.tar.gz" \
      --dir "$dir"
    tar -xzf "$dir/gaia-${tag}.tar.gz" -C "$dir" --strip-components=1
  fi
done

BASELINE_DIR=".gaia/cache/v$BASELINE", LATEST_DIR=".gaia/cache/$LATEST_TAG".

If the baseline tarball is unavailable (older release, pre-manifest), stop and explain — the adopter can manually cherry-pick changes by comparing their project to the $LATEST_DIR.

Step 6: Load the latest manifest

LATEST_MANIFEST="$LATEST_DIR/.gaia/manifest.json"

Iterate keys of .files. For each <path>, <class> entry, apply the decision table below. Track counts per outcome for the summary.

Step 7: Three-way merge

Apply the decision table directly — there is no CLI for this step.

Setup:

BACKUP_DIR=".gaia-backup/$(date +%Y%m%d-%H%M%S)"
mkdir -p .gaia-merge "$BACKUP_DIR"

Track six lists internally (UpdateMergeReport):

{
  overwrite: string[];   // owned files overwritten with latest
  skip: string[];        // no change needed; left alone
  merge: string[];       // clean shared/wiki-owned merges written into the working tree
  add: string[];         // new files copied from latest
  delete: string[];      // files removed upstream; surfaced but NOT auto-deleted
  conflicts: Array<{
    path: string;
    class: 'owned' | 'shared' | 'wiki-owned';
    patch_path: string;  // .gaia-merge/<path>.patch
  }>;
}

Iterate every <path>: <class> entry in $LATEST_MANIFEST's .files object:

Let A = working-tree <path>, B = $BASELINE_DIR/<path>, L = $LATEST_DIR/<path>. Use cmp -s for equality; mkdir -p before writing.

Match in declared order — first matching row wins. The first row applies to every class and runs before any class-specific check; it closes the silent-skip gap where the manifest declares a file but the adopter's tree never had it (in particular, the shared / wiki-owned B ≅ L row below would otherwise short-circuit and leave the file missing on disk).

| Class | Condition | Action | List | |---|---|---|---| | any | A missing and L exists | Copy L → <path> | add[] | | owned | B missing (new file) | Copy L → <path> | add[] | | owned | A ≅ B (no adopter drift) | Back up A to $BACKUP_DIR/<path>; copy L → <path> | overwrite[] | | owned | A ≅ L (adopter already current) | No-op | skip[] | | owned | A ≠ B and A ≠ L | diff -u "$A" "$L" > .gaia-merge/<path>.patch | conflicts[] | | shared / wiki-owned | B ≅ L (no upstream change) | No-op | skip[] | | shared / wiki-owned | A ≅ B (no adopter drift) | Back up A to $BACKUP_DIR/<path>; copy L → <path> | merge[] | | shared / wiki-owned | A ≅ L (adopter already at latest) | No-op | skip[] | | shared / `wiki-

Compartilhar X LinkedIn