Update scripts to keep SOUL.md idempotent. Add release upgrade framework.

This commit is contained in:
2026-02-20 07:36:54 -06:00
parent eac247c5cb
commit 1e4eefeca3
9 changed files with 551 additions and 17 deletions

View File

@@ -14,6 +14,9 @@ set -euo pipefail
# mosaic doctor [args...] Health audit
# mosaic sync [args...] Sync skills
# mosaic bootstrap <path> Bootstrap a repo
# mosaic upgrade release Upgrade installed Mosaic release
# mosaic upgrade check Check release upgrade status (no changes)
# mosaic upgrade project [args] Upgrade project-local stale files
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
VERSION="0.1.0"
@@ -34,7 +37,10 @@ Management:
doctor [args...] Audit runtime state and detect drift
sync [args...] Sync skills from canonical source
bootstrap <path> Bootstrap a repo with Mosaic standards
upgrade [path] Clean up stale SOUL.md/CLAUDE.md in a project
upgrade [mode] [args] Upgrade release (default) or project files
upgrade check Check release upgrade status (no changes)
release-upgrade [...] Upgrade installed Mosaic release
project-upgrade [...] Clean up stale SOUL.md/CLAUDE.md in a project
Options:
-h, --help Show this help
@@ -147,11 +153,54 @@ run_bootstrap() {
exec "$MOSAIC_HOME/bin/mosaic-bootstrap-repo" "$@"
}
run_upgrade() {
run_release_upgrade() {
check_mosaic_home
exec "$MOSAIC_HOME/bin/mosaic-release-upgrade" "$@"
}
run_project_upgrade() {
check_mosaic_home
exec "$MOSAIC_HOME/bin/mosaic-upgrade" "$@"
}
run_upgrade() {
check_mosaic_home
# Default: upgrade installed release
if [[ $# -eq 0 ]]; then
run_release_upgrade
fi
case "$1" in
release)
shift
run_release_upgrade "$@"
;;
check)
shift
run_release_upgrade --dry-run "$@"
;;
project)
shift
run_project_upgrade "$@"
;;
# Backward compatibility for historical project-upgrade usage.
--all|--root)
run_project_upgrade "$@"
;;
--dry-run|--ref|--keep|--overwrite|-y|--yes)
run_release_upgrade "$@"
;;
-*)
run_release_upgrade "$@"
;;
*)
run_project_upgrade "$@"
;;
esac
}
# Main router
if [[ $# -eq 0 ]]; then
usage
@@ -170,6 +219,8 @@ case "$command" in
sync) run_sync "$@" ;;
bootstrap) run_bootstrap "$@" ;;
upgrade) run_upgrade "$@" ;;
release-upgrade) run_release_upgrade "$@" ;;
project-upgrade) run_project_upgrade "$@" ;;
help|-h|--help) usage ;;
version|-v|--version) echo "mosaic $VERSION" ;;
*)

124
bin/mosaic-release-upgrade Executable file
View File

@@ -0,0 +1,124 @@
#!/usr/bin/env bash
set -euo pipefail
# mosaic-release-upgrade — Upgrade installed Mosaic framework release.
#
# This re-runs the remote installer with explicit install mode controls.
# Default behavior is safe/idempotent (keep SOUL.md + memory).
#
# Usage:
# mosaic-release-upgrade
# mosaic-release-upgrade --ref main --keep
# mosaic-release-upgrade --ref v0.2.0 --overwrite --yes
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
REMOTE_SCRIPT_URL="${MOSAIC_REMOTE_INSTALL_URL:-https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.sh}"
BOOTSTRAP_REF="${MOSAIC_BOOTSTRAP_REF:-main}"
INSTALL_MODE="${MOSAIC_INSTALL_MODE:-keep}" # keep|overwrite
YES=false
DRY_RUN=false
usage() {
cat <<USAGE
Usage: $(basename "$0") [options]
Upgrade the installed Mosaic framework release.
Options:
--ref <name> Bootstrap archive ref (branch/tag/commit). Default: main
--keep Keep local files (SOUL.md, memory/) during upgrade (default)
--overwrite Overwrite target install directory contents
-y, --yes Skip confirmation prompt
--dry-run Show actions without executing
-h, --help Show this help
USAGE
}
while [[ $# -gt 0 ]]; do
case "$1" in
--ref)
[[ $# -lt 2 ]] && { echo "Missing value for --ref" >&2; exit 1; }
BOOTSTRAP_REF="$2"
shift 2
;;
--keep)
INSTALL_MODE="keep"
shift
;;
--overwrite)
INSTALL_MODE="overwrite"
shift
;;
-y|--yes)
YES=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage >&2
exit 1
;;
esac
done
case "$INSTALL_MODE" in
keep|overwrite) ;;
*)
echo "[mosaic-release-upgrade] Invalid install mode: $INSTALL_MODE" >&2
exit 1
;;
esac
current_version="unknown"
if [[ -x "$MOSAIC_HOME/bin/mosaic" ]]; then
current_version="$("$MOSAIC_HOME/bin/mosaic" --version 2>/dev/null | awk '{print $2}' || true)"
[[ -n "$current_version" ]] || current_version="unknown"
fi
echo "[mosaic-release-upgrade] Current version: $current_version"
echo "[mosaic-release-upgrade] Target ref: $BOOTSTRAP_REF"
echo "[mosaic-release-upgrade] Install mode: $INSTALL_MODE"
echo "[mosaic-release-upgrade] Installer URL: $REMOTE_SCRIPT_URL"
if [[ "$DRY_RUN" == "true" ]]; then
echo "[mosaic-release-upgrade] Dry run: no changes applied."
exit 0
fi
if [[ "$YES" != "true" && -t 0 ]]; then
printf "Proceed with Mosaic release upgrade? [y/N]: "
read -r confirm
case "${confirm:-n}" in
y|Y|yes|YES) ;;
*)
echo "[mosaic-release-upgrade] Aborted."
exit 1
;;
esac
fi
if command -v curl >/dev/null 2>&1; then
curl -sL "$REMOTE_SCRIPT_URL" | \
MOSAIC_BOOTSTRAP_REF="$BOOTSTRAP_REF" \
MOSAIC_INSTALL_MODE="$INSTALL_MODE" \
MOSAIC_HOME="$MOSAIC_HOME" \
sh
elif command -v wget >/dev/null 2>&1; then
wget -qO- "$REMOTE_SCRIPT_URL" | \
MOSAIC_BOOTSTRAP_REF="$BOOTSTRAP_REF" \
MOSAIC_INSTALL_MODE="$INSTALL_MODE" \
MOSAIC_HOME="$MOSAIC_HOME" \
sh
else
echo "[mosaic-release-upgrade] ERROR: curl or wget required." >&2
exit 1
fi

View File

@@ -0,0 +1,65 @@
# mosaic-release-upgrade.ps1 — Upgrade installed Mosaic framework release (Windows)
#
# Usage:
# mosaic-release-upgrade.ps1
# mosaic-release-upgrade.ps1 -Ref main -Keep
# mosaic-release-upgrade.ps1 -Ref v0.2.0 -Overwrite -Yes
#
param(
[string]$Ref = $(if ($env:MOSAIC_BOOTSTRAP_REF) { $env:MOSAIC_BOOTSTRAP_REF } else { "main" }),
[switch]$Keep,
[switch]$Overwrite,
[switch]$Yes,
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
$RemoteInstallerUrl = if ($env:MOSAIC_REMOTE_INSTALL_URL) {
$env:MOSAIC_REMOTE_INSTALL_URL
} else {
"https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.ps1"
}
$installMode = if ($Overwrite) { "overwrite" } elseif ($Keep) { "keep" } elseif ($env:MOSAIC_INSTALL_MODE) { $env:MOSAIC_INSTALL_MODE } else { "keep" }
if ($installMode -notin @("keep", "overwrite")) {
Write-Host "[mosaic-release-upgrade] Invalid install mode: $installMode" -ForegroundColor Red
exit 1
}
$currentVersion = "unknown"
$mosaicCmd = Join-Path $MosaicHome "bin\mosaic.ps1"
if (Test-Path $mosaicCmd) {
try {
$currentVersion = (& $mosaicCmd --version) -replace '^mosaic\s+', ''
}
catch {
$currentVersion = "unknown"
}
}
Write-Host "[mosaic-release-upgrade] Current version: $currentVersion"
Write-Host "[mosaic-release-upgrade] Target ref: $Ref"
Write-Host "[mosaic-release-upgrade] Install mode: $installMode"
Write-Host "[mosaic-release-upgrade] Installer URL: $RemoteInstallerUrl"
if ($DryRun) {
Write-Host "[mosaic-release-upgrade] Dry run: no changes applied."
exit 0
}
if (-not $Yes) {
$confirmation = Read-Host "Proceed with Mosaic release upgrade? [y/N]"
if ($confirmation -notin @("y", "Y", "yes", "YES")) {
Write-Host "[mosaic-release-upgrade] Aborted."
exit 1
}
}
$env:MOSAIC_BOOTSTRAP_REF = $Ref
$env:MOSAIC_INSTALL_MODE = $installMode
$env:MOSAIC_HOME = $MosaicHome
Invoke-RestMethod -Uri $RemoteInstallerUrl | Invoke-Expression

View File

@@ -31,7 +31,10 @@ Management:
doctor [args...] Audit runtime state and detect drift
sync [args...] Sync skills from canonical source
bootstrap <path> Bootstrap a repo with Mosaic standards
upgrade [path] Clean up stale SOUL.md/CLAUDE.md in a project
upgrade [mode] [args] Upgrade release (default) or project files
upgrade check Check release upgrade status (no changes)
release-upgrade [...] Upgrade installed Mosaic release
project-upgrade [...] Clean up stale SOUL.md/CLAUDE.md in a project
Options:
-h, --help Show this help
@@ -142,6 +145,48 @@ switch ($command) {
& (Join-Path $MosaicHome "bin\mosaic-bootstrap-repo") @remaining
}
"upgrade" {
Assert-MosaicHome
if ($remaining.Count -eq 0) {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1")
break
}
$mode = $remaining[0]
$tail = if ($remaining.Count -gt 1) { $remaining[1..($remaining.Count - 1)] } else { @() }
switch -Regex ($mode) {
"^release$" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @tail
}
"^check$" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") -DryRun @tail
}
"^project$" {
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @tail
}
"^(--all|--root)$" {
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
}
"^(--dry-run|--ref|--keep|--overwrite|-y|--yes)$" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
}
"^-.*" {
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
}
default {
Write-Host "[mosaic] NOTE: treating positional argument as project path." -ForegroundColor Yellow
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
}
}
}
"release-upgrade" {
Assert-MosaicHome
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
}
"project-upgrade" {
Assert-MosaicHome
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining