diff --git a/scripts/fixtures/sample-settings.json b/scripts/fixtures/sample-settings.json new file mode 100644 index 0000000..e32fdf3 --- /dev/null +++ b/scripts/fixtures/sample-settings.json @@ -0,0 +1,16 @@ +{ + "theme": "dark", + "editorMode": "vscode", + "statusLine": "compact", + "enabledPlugins": { + "old-plugin@old-marketplace": true + }, + "permissions": { + "allow": ["Bash(old:*)"], + "deny": [], + "ask": [] + }, + "hooks": { + "SessionStart": [] + } +} diff --git a/scripts/lib/merge-settings.sh b/scripts/lib/merge-settings.sh new file mode 100644 index 0000000..569e946 --- /dev/null +++ b/scripts/lib/merge-settings.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Merge brain settings-fragment.json into consumer's settings.json +# Replaces: enabledPlugins, permissions, hooks +# Preserves: theme, editorMode, statusLine, all other keys +# +# Usage: merge-settings.sh +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +target="$1" +fragment="$2" + +require_cmd jq || exit 1 +[ -f "$fragment" ] || { log_error "Fragment not found: $fragment"; exit 1; } + +# If target doesn't exist, just copy fragment +if [ ! -f "$target" ]; then + log_info "Target settings.json missing, creating from fragment" + cp "$fragment" "$target" + exit 0 +fi + +# Backup +backup="${target}.bak.$(date +%s)" +cp "$target" "$backup" + +# Merge: target.* keys preserved EXCEPT enabledPlugins/permissions/hooks — those are REPLACED +# (not deep-merged) from fragment. Use --slurpfile to load fragment into $frag. +tmp="${target}.tmp" +jq --slurpfile frag "$fragment" \ + '.enabledPlugins = $frag[0].enabledPlugins + | .permissions = $frag[0].permissions + | .hooks = $frag[0].hooks' \ + "$target" > "$tmp" + +# Validate output JSON +jq empty "$tmp" || { log_error "Merge produced invalid JSON"; rm "$tmp"; exit 1; } + +mv "$tmp" "$target" +log_info "settings.json merged (backup: $backup)" diff --git a/scripts/tests/merge-settings-test.sh b/scripts/tests/merge-settings-test.sh new file mode 100644 index 0000000..214b25d --- /dev/null +++ b/scripts/tests/merge-settings-test.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -u +SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +source "$SCRIPT_DIR/lib/common.sh" + +FAILURES=0 +assert_eq() { + local expected="$1" actual="$2" name="$3" + if [ "$expected" = "$actual" ]; then + echo "PASS: $name" + else + echo "FAIL: $name (expected '$expected', got '$actual')" + FAILURES=$((FAILURES + 1)) + fi +} + +# Setup: temp consumer settings + brain fragment +tmpdir=$(mktemp -d) +cp "$SCRIPT_DIR/fixtures/sample-settings.json" "$tmpdir/settings.json" +cat > "$tmpdir/fragment.json" <