diff --git a/bin/gs b/bin/gs index 630f0e1..9b085f4 100755 --- a/bin/gs +++ b/bin/gs @@ -35,8 +35,10 @@ gs - gentle-shell on main, plus one disposable worktree per PR gs sync Bring gentle-shell, gentle-ai and engram to main, run gentle-ai sync for managed configs, and check compatibility (workshop: local clones; elsewhere: GitHub) + Workshop: gentle-ai sync --agents claude-code, then + gentle-shell --isolated setup (re-provisions the isolated home) GS_SYNC_AGENTS=a,b scopes gentle-ai sync to those runtimes; - GS_SKIP_AI_SYNC=1 skips it (binaries only) + GS_SKIP_AI_SYNC=1 skips both steps (binaries only) Then pulls the dotfiles clone (clean, on main only); the shell profile reads it in place. GS_SKIP_DOTFILES=1 skips this step @@ -458,12 +460,17 @@ cmd_sync() { # New binaries are not enough: gentle-ai sync materializes the managed configs # (agents, skills, plugins, engram instructions) every runtime reads. - # GS_SYNC_AGENTS scopes runtimes per host (local env); empty = gentle-ai default. + # GS_SYNC_AGENTS scopes runtimes per host (local env). Workshop defaults to + # claude-code (Shell runs on the isolated home, provisioned below by + # gentle-shell setup); consumer empty = gentle-ai default. + local sync_agents="${GS_SYNC_AGENTS:-}" + is_workshop && sync_agents="${GS_SYNC_AGENTS:-claude-code}" if [ "${GS_SKIP_AI_SYNC:-}" = 1 ]; then printf ' %-34s skipped (GS_SKIP_AI_SYNC=1)\n' 'gentle-ai sync' + is_workshop && printf ' %-34s skipped (GS_SKIP_AI_SYNC=1)\n' 'gentle-shell setup (isolated home)' else local ai_sync=(sync) - [ -n "${GS_SYNC_AGENTS:-}" ] && ai_sync+=(--agents "$GS_SYNC_AGENTS") + [ -n "$sync_agents" ] && ai_sync+=(--agents "$sync_agents") # Like run_quiet, but keeps the output: its file count feeds the restart hint. local ai_out; ai_out=$(mktemp) if "$ai_bin" "${ai_sync[@]}" >"$ai_out" 2>&1; then @@ -475,6 +482,9 @@ cmd_sync() { fi ai_files=$(sed -n 's/^Sync actions executed: \([0-9][0-9]*\) files* changed.*/\1/p' "$ai_out" | head -1) rm -f "$ai_out" + # Official re-provisioning of the isolated home (~/.gentle-shell/agent) from the clone. + is_workshop && run_quiet 'gentle-shell setup (isolated home)' \ + node "$CLONES/gentle-shell/bin/gentle-shell.mjs" --isolated setup fi sync_dotfiles # gs sync is the only upgrade path; older homemade scripts drift the hosts apart. diff --git a/docs/gentle-official-migration.md b/docs/gentle-official-migration.md index c4dd508..37eafb5 100644 --- a/docs/gentle-official-migration.md +++ b/docs/gentle-official-migration.md @@ -265,7 +265,7 @@ Corrección del usuario, textual: - Shell mantiene su mecanismo oficial `gentle-shell upgrade --channel main`. No asumir que ese comando actualiza el Gentle AI externo que usa Claude Code. - Después de actualizar, comprobar qué binario externo resuelve el PATH y qué versión/commit quedó instalado; evitar actualizar una copia y ejecutar otra. Definir y verificar el mecanismo oficial de sincronización de assets de Claude Code cuando se implemente. - Implementado en [`bin/gs-official`](../bin/gs-official) ([doc](gs-official.md)), desplegado solo en hosts migrados como `~/.local/bin/gs`. El `bin/gs` legacy de Mac y workshop no cambia. El PATH permanente se activa con el fragmento opt-in [`zsh/scripts/official-gentle-path.zsh`](../zsh/scripts/official-gentle-path.zsh), enlazado en `~/.config/cortex-dotfiles/shell/official-gentle-path.zsh`. -- Workshop (agent-gentle): el `bin/gs` de workshop conserva sus accesorios (`gs issue`, `gs pr`, `gs review`, `gs new`, `gs base`, `gs ls`, `gs done`, `gs sync`), pero todo arranque usa el home aislado (`--isolated`, nunca `--link`) y, desde un clon o worktree, `--package-root `. `gs sync` en workshop no agrega `~/.pi/agent/bin` al PATH ni ejecuta `pi update`; registra Gentle AI de main en `~/.pi/gentle-ai/dev-binary.json`: es estado de instalación y el lanzador oficial lo lee ahí también con el home aislado, así que no se mueve ni se retira. Ver [gs-sync.md](gs-sync.md). `gs-official` y Mac/agent-dev no cambian por esto. +- Workshop (agent-gentle): el `bin/gs` de workshop conserva sus accesorios (`gs issue`, `gs pr`, `gs review`, `gs new`, `gs base`, `gs ls`, `gs done`, `gs sync`), pero todo arranque usa el home aislado (`--isolated`, nunca `--link`) y, desde un clon o worktree, `--package-root `. `gs sync` en workshop no agrega `~/.pi/agent/bin` al PATH ni ejecuta `pi update`; registra Gentle AI de main en `~/.pi/gentle-ai/dev-binary.json`: es estado de instalación y el lanzador oficial lo lee ahí también con el home aislado, así que no se mueve ni se retira. Luego ejecuta `gentle-ai sync --agents claude-code` (solo Claude Code; `GS_SYNC_AGENTS` lo sobrescribe) y `node ~/dev/gentle/gentle-shell/bin/gentle-shell.mjs --isolated setup`, que reaprovisiona el home aislado `~/.gentle-shell/agent`; si un paso falla, el sync queda `INCOMPLETE`. `GS_SKIP_AI_SYNC=1` omite ambos pasos. El sync de consumidor no cambia. Ver [gs-sync.md](gs-sync.md). `gs-official` y Mac/agent-dev no cambian por esto. - El instalador oficial `install.sh --channel beta` falló en esta sesión: `get_main_commit_sha` emite un mensaje informativo en stdout y su captura mezcla ese mensaje con el SHA, causando una URL inválida al buscar `go.mod`. Se comprobó en el script remoto. No parchear el instalador ni desactivar verificaciones como workaround. - También hubo un error de pegado independiente (`\\ |` en una misma línea). Corregir el pegado no arregla el bug del instalador. diff --git a/docs/gs-sync.md b/docs/gs-sync.md index 397852b..124d1c3 100644 --- a/docs/gs-sync.md +++ b/docs/gs-sync.md @@ -30,10 +30,17 @@ Workshop `gs sync` also stays off the legacy Pi home: - It no longer warns about `gentle-pi`/`gentle-engram` in the isolated home's `settings.json`: the official Shell declares and requires them there, and the `--package-root` take-over loads the clone instead of the published gentle-pi. +- It runs `gentle-ai sync --agents claude-code` (Claude Code only; never the + legacy `pi` agent nor `opencode`). `GS_SYNC_AGENTS=a,b` overrides the agents. +- It then runs `node ~/dev/gentle/gentle-shell/bin/gentle-shell.mjs --isolated setup` + (`gentle-shell setup (isolated home)`), the official re-provisioning of + `~/.gentle-shell/agent`. A failure marks the sync `INCOMPLETE` and shows its output. +- `GS_SKIP_AI_SYNC=1` skips both steps and prints a `skipped` line for each. The `gs pr` / `gs issue` kickoff prompts name the `cortex-maintainer-delivery` skill without a home path. Consumer sync keeps its official update steps -(`pi update`, `gentle-shell upgrade --channel main`, `pi update --extensions`). +(`pi update`, `gentle-shell upgrade --channel main`, `pi update --extensions`) +and runs `gentle-ai sync` with `--agents` only when `GS_SYNC_AGENTS` is set. ## Why this changed diff --git a/local/env.zsh.example b/local/env.zsh.example index 620601b..4d13fb4 100644 --- a/local/env.zsh.example +++ b/local/env.zsh.example @@ -51,9 +51,11 @@ # export CORTEX_BRAINS_PG_HOST="" # export CORTEX_BRAINS_PG_PORT="5432" -# gs sync runs gentle-ai sync after updating binaries. Scope it to this host's runtimes: -# export GS_SYNC_AGENTS="claude-code,opencode,pi" -# Binaries only, no managed-config sync: +# gs sync runs gentle-ai sync after updating binaries. Workshop defaults to claude-code +# and then runs gentle-shell --isolated setup; consumer defaults to gentle-ai's own set. +# Override the runtimes for this host: +# export GS_SYNC_AGENTS="claude-code" +# Binaries only, no managed-config sync (workshop: also skips gentle-shell setup): # export GS_SKIP_AI_SYNC=1 # gs sync also pulls the dotfiles clone (clean, on main); the zsh profile reads it in place. # export GS_SKIP_DOTFILES=1 diff --git a/odd/tasks/agent-gentle-official-home.md b/odd/tasks/agent-gentle-official-home.md index 8dc2aac..966fefc 100644 --- a/odd/tasks/agent-gentle-official-home.md +++ b/odd/tasks/agent-gentle-official-home.md @@ -11,11 +11,13 @@ Shell keeps running from the gentle-shell clone; only the home, Pi runtime and G - S4. Gentle AI from main inside Shell: workshop `gs sync` keeps writing the dev-binary registration `{"schema":"gentle-pi.dev-binary/v1","path":"<~/.local/share/gentle-ai/main/gentle-ai>"}` to `~/.pi/gentle-ai/dev-binary.json` (0600, atomic). It is install-level state the official launcher reads there even for the isolated home (gentle-shell `lib/gentle-shell-launcher.ts:252-254`, `lib/gentle-ai-binary.ts:218` `launcherMarker: false`); it is never moved or retired. - S5. Prompts for `gs pr` / `gs issue` no longer point at `~/.pi/agent/skills/...`; they name the `cortex-maintainer-delivery` skill without a legacy home path. - S6. Help text and docs (`docs/gs-sync.md`, `docs/gentle-official-migration.md`) describe the new behavior; `gs-official` and Mac/agent-dev are unaffected. +- S8. Workshop `gs sync` syncs external Gentle AI for Claude Code only and provisions the isolated home: "solo claude code". It runs `gentle-ai sync --agents claude-code` by default (never the legacy `pi` agent nor `opencode`; an explicit `GS_SYNC_AGENTS` still overrides), then `gentle-shell setup` on the isolated home from the synced clone (`node ~/dev/gentle/gentle-shell/bin/gentle-shell.mjs --isolated setup`), the official re-provisioning of `~/.gentle-shell/agent`. `GS_SKIP_AI_SYNC=1` skips both. A failed step marks the sync INCOMPLETE. Consumer sync is unchanged. - S7. Host deploy on agent-gentle: confirm last NAS backup succeeded; then pull dotfiles, run `gs sync`, replace the `~/.local/bin/gentle-shell` wrapper so it no longer sets `GENTLE_SHELL_PI=~/.pi/agent/bin/pi`, and move retired legacy pieces to a `mktemp -d` backup (never delete). Never touch Engram data, credentials, conversations, worktrees with uncommitted changes, or Herdr. ## Tasks - T1 (S2-S6) worker + parent fixes: change `bin/gs` + tests + docs. Done. Commit: e89c3d1 +- T3 (S8) worker: workshop sync scope + isolated setup. Done. Commit: see branch feat/agent-gentle-sync-scope - T2 (S7) parent: deploy and verify on agent-gentle. Commit: n/a (host) ## Log @@ -25,3 +27,4 @@ Shell keeps running from the gentle-shell clone; only the home, Pi runtime and G - L3 Evidence: official launcher (clone 14f44d11c) accepts `--isolated` with `--package-root` (only `--link`+`--isolated` and `--isolated`+`--home` conflict, `lib/gentle-shell-launcher.ts:169-174`); clone has adjacent Pi 1.4.0; isolated home `~/.gentle-shell/agent` already holds pi-mcp-adapter and brains; Engram already at main tip `7cf4ed29b6f9`. - L4 Parent review: removed the isolated-settings gentle-pi/gentle-engram warning; on agent-gentle the official Shell declares both there (gentle-engram is its required companion), so it would fire on every sync. Skill cortex-maintainer-delivery exists only in ~/.pi/agent/skills on agent-gentle; T2 must expose it to the isolated home before retiring legacy. - L5 Verifier FAIL on S4: the launcher reads dev-binary.json from ~/.pi/gentle-ai, not the isolated config home (confirmed on agent-gentle clone 14f44d11c, lib/gentle-ai-binary.ts:218). S4 rewritten: keep writing ~/.pi/gentle-ai/dev-binary.json; T1 reopened and fixed. +- L6 User asked whether gs sync also runs gentle-ai sync and whether gentle-shell has its own: "en el gs sync metimos también un gentle-ai sync? porque eso es lo que esta documentado en el proceso de actualizacion. Hay que revisar si gentle-shell no tiene algo de esto también". Finding: workshop runs bare `gentle-ai sync`; installed_agents on agent-gentle = claude-code, opencode, pi, so it keeps syncing the legacy ~/.pi/agent (gentle-shell README: `gentle-ai sync` is Path B, gentle-pi inside an existing pi) and never the isolated home; `gentle-shell setup` re-provisions the isolated home; the agent-gentle wrapper sets GENTLE_SHELL_NO_AUTO_SETUP=1. User decision on agents: "solo claude code". diff --git a/tests/gs_test.sh b/tests/gs_test.sh index 687c1d7..18adb46 100755 --- a/tests/gs_test.sh +++ b/tests/gs_test.sh @@ -28,6 +28,8 @@ setup() { # mode: consumer | workshop pkg=$(dirname "$(dirname "$1")"); shift if [ "${1:-}" = --version ]; then printf 'gentle-shell %s\npi 1.4.0\n' "$(cat "$pkg/VERSION")"; exit 0; fi echo "launch $pkg $*" >> "$CALLS" +[ "${2:-}" = setup ] && exit "${SETUP_RC:-0}" +exit 0 EOF printf '#!/bin/sh\necho "go PATH=$PATH" >> "$CALLS"\n' > "$S/go" for b in pnpm npm; do printf '#!/bin/sh\nexit 0\n' > "$S/$b"; done @@ -173,6 +175,22 @@ mkdir -p "$HOME/.gentle-shell/agent"; printf '{"packages":["npm:gentle-pi","npm: OUT=$("$GS" sync 2>&1) check "workshop sync: isolated home packages the official Shell requires raise no warning" \ '[[ "$OUT" != *"WARN:"*"settings.json"* ]]' +# S8: workshop gentle-ai sync is Claude Code only, then the isolated home is provisioned. +AI="$HOME/.local/share/gentle-ai/main/gentle-ai" +printf '#!/bin/sh\n[ "$1" = --version ] && { echo "gentle-ai 1.0.0"; exit 0; }\necho "gentle-ai $*" >> "$CALLS"\n' > "$AI"; chmod +x "$AI" +SHELL_CLONE="$HOME/dev/gentle/gentle-shell" +: > "$CALLS"; OUT=$(env -u GS_SKIP_AI_SYNC "$GS" sync 2>&1); rc=$? +check "workshop sync: gentle-ai sync targets claude-code only, then gentle-shell setup on the isolated home" \ + '[ $rc -eq 0 ] && [ "$(grep -E "^gentle-ai sync|--isolated setup" "$CALLS")" = "$(printf "gentle-ai sync --agents claude-code\nlaunch %s --isolated setup" "$SHELL_CLONE")" ] && [[ "$OUT" == *"gentle-shell setup (isolated home)"*ok* ]]' +: > "$CALLS"; OUT=$(env -u GS_SKIP_AI_SYNC GS_SYNC_AGENTS=x "$GS" sync 2>&1) +check "workshop sync: GS_SYNC_AGENTS overrides the claude-code default" \ + 'grep -qx "gentle-ai sync --agents x" "$CALLS"' +: > "$CALLS"; OUT=$(GS_SKIP_AI_SYNC=1 "$GS" sync 2>&1) +check "workshop sync: GS_SKIP_AI_SYNC=1 skips gentle-ai sync and gentle-shell setup" \ + '! grep -qE "^gentle-ai sync|--isolated setup" "$CALLS" && [[ "$OUT" == *"gentle-ai sync"*"skipped (GS_SKIP_AI_SYNC=1)"* ]] && [[ "$OUT" == *"gentle-shell setup (isolated home)"*"skipped (GS_SKIP_AI_SYNC=1)"* ]]' +OUT=$(env -u GS_SKIP_AI_SYNC SETUP_RC=1 "$GS" sync 2>&1); rc=$? +check "workshop sync: failed gentle-shell setup is INCOMPLETE, exit 1" \ + '[ $rc -eq 1 ] && [[ "$OUT" == *"INCOMPLETE"*"gentle-shell setup (isolated home)"* ]]' rm "$HOME/.gentle-shell/agent/settings.json" echo tracked >> "$HOME/dev/gentle/gentle-shell/VERSION"; git -C "$HOME/dev/gentle/gentle-shell" add VERSION OUT=$("$GS" sync 2>&1); rc=$? @@ -190,6 +208,12 @@ check "consumer sync: still runs pi update and pi update --extensions" \ check "sync: warns about the unused legacy checkout without deleting it" \ '[[ "$OUT" == *"stale legacy checkout"* ]] && [ -d "$HOME/.pi/agent/git/github.com/Gentleman-Programming/gentle-pi" ]' +setup consumer; remote_main HEAD +printf '#!/bin/sh\n[ "$1" = --version ] && { echo "gentle-ai 1.0.0"; exit 0; }\necho "gentle-ai $*" >> "$CALLS"\n' > "$HOME/ai" +OUT=$(env -u GS_SKIP_AI_SYNC "$GS" sync 2>&1) +check "consumer sync: still runs bare gentle-ai sync (no --agents) and no gentle-shell setup" \ + 'grep -qx "gentle-ai sync" "$CALLS" && ! grep -q -- "--isolated setup" "$CALLS" && [[ "$OUT" != *"gentle-shell setup"* ]]' + setup consumer; remote_main HEAD; main=$(sha_of) echo "4.5.2-main.${main:0:12}" > "$NPM/VERSION" OUT=$("$GS" sync 2>&1); rc=$?