superpowers-manager 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/scripts/prepare CHANGED
@@ -2,22 +2,39 @@
2
2
  set -eu
3
3
 
4
4
  root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
5
- . "$root/scripts/lib.sh"
5
+ . "$root/scripts/core/common.sh"
6
+ . "$root/scripts/core/upstream.sh"
7
+ . "$root/scripts/core/provenance.sh"
8
+ . "$root/scripts/core/lifecycle.sh"
9
+ . "$root/scripts/core/adapter.sh"
6
10
 
7
11
  upstream_url="${SUPERPOWERS_UPSTREAM_URL:-$SPW_UPSTREAM_URL_DEFAULT}"
8
12
  cache_parent="${SUPERPOWERS_CACHE_DIR:-$root/.cache/upstream}"
9
- cache="$cache_parent/superpowers"
10
13
  plugin_root="${SUPERPOWERS_PLUGIN_ROOT:-$root/plugins/superpowers}"
11
14
  manifest_template="${SUPERPOWERS_MANIFEST_TEMPLATE:-$root/plugins/superpowers/.codex-plugin/plugin.template.json}"
12
- builtin_validator="$root/scripts/validate-generated-plugin.py"
13
15
  additional_validator="${SUPERPOWERS_VALIDATOR:-}"
16
+ invocation_root=$(pwd -P)
17
+ case "$cache_parent" in
18
+ /*) ;;
19
+ *) cache_parent="$invocation_root/$cache_parent" ;;
20
+ esac
21
+ case "$plugin_root" in
22
+ /*) ;;
23
+ *) plugin_root="$invocation_root/$plugin_root" ;;
24
+ esac
25
+ cache="$cache_parent/superpowers"
14
26
  tmp_parent=$(dirname "$plugin_root")
15
- tmp_plugin="$tmp_parent/.superpowers.tmp.$$"
27
+ mkdir -p "$tmp_parent"
28
+ if ! prepare_workspace=$(mktemp -d "$tmp_parent/.superpowers.prepare.XXXXXX"); then
29
+ spw_die "cannot create prepare workspace under $tmp_parent"
30
+ fi
31
+ tmp_plugin="$prepare_workspace/superpowers"
32
+ adapter_result="$prepare_workspace/adapter-build.json"
16
33
 
17
34
  cleanup_tmp_plugin() {
18
35
  status=$?
19
36
  trap - 0 HUP INT TERM
20
- rm -rf "$tmp_plugin" || :
37
+ rm -rf "$prepare_workspace" || :
21
38
  exit "$status"
22
39
  }
23
40
 
@@ -26,12 +43,15 @@ trap 'exit 129' HUP
26
43
  trap 'exit 130' INT
27
44
  trap 'exit 143' TERM
28
45
 
46
+ TMPDIR="$prepare_workspace"
47
+ export TMPDIR
48
+
29
49
  requested_ref=$(spw_config_ref "$root")
30
50
 
31
51
  spw_require_command git
32
52
  spw_require_command python3
53
+ spw_require_command "$SPW_ADAPTER"
33
54
  [ -f "$manifest_template" ] || spw_die "missing fallback manifest template: $manifest_template"
34
- [ -f "$builtin_validator" ] || spw_die "missing built-in plugin validator: $builtin_validator"
35
55
 
36
56
  resolved_record=$(spw_resolve_ref "$upstream_url" "$requested_ref")
37
57
  resolution_kind=$(printf '%s\n' "$resolved_record" | awk '{ print $1 }')
@@ -60,11 +80,6 @@ spw_require_upstream_path "$cache/CODE_OF_CONDUCT.md" "CODE_OF_CONDUCT.md"
60
80
  rm -rf "$tmp_plugin"
61
81
  mkdir -p "$tmp_plugin/.codex-plugin"
62
82
  upstream_manifest="$cache/.codex-plugin/plugin.json"
63
- if [ -f "$upstream_manifest" ]; then
64
- cp "$upstream_manifest" "$tmp_plugin/.codex-plugin/plugin.json"
65
- else
66
- cp "$manifest_template" "$tmp_plugin/.codex-plugin/plugin.json"
67
- fi
68
83
 
69
84
  spw_copy_path_if_present "$cache/skills" "$tmp_plugin/skills"
70
85
  spw_copy_path_if_present "$cache/assets" "$tmp_plugin/assets"
@@ -88,23 +103,15 @@ spw_write_metadata_json \
88
103
  manager_version=$(
89
104
  spw_manifest_version_for_ref "$requested_ref" "$resolution_kind" "$resolved_ref" "$commit"
90
105
  )
91
- spw_apply_manifest_overlay \
92
- "$tmp_plugin/.codex-plugin/plugin.json" \
93
- "$manager_version"
94
-
95
- # The validator must inspect the exact complete tree that will be swapped.
96
- cp "$manifest_template" "$tmp_plugin/.codex-plugin/plugin.template.json"
97
-
98
- if ! python3 -S "$builtin_validator" \
99
- --plugin-root "$tmp_plugin" \
100
- --source "$upstream_url" \
106
+ spw_invoke_adapter build "$adapter_result" "" -- \
107
+ --upstream-root "$cache" \
108
+ --candidate-root "$tmp_plugin" \
101
109
  --requested-ref "$requested_ref" \
102
110
  --resolved-ref "$resolved_ref" \
103
111
  --commit "$commit" \
104
- --manifest-version "$manager_version" \
105
- --upstream-manifest-version "$upstream_manifest_version"; then
106
- spw_die "built-in generated plugin validation failed"
107
- fi
112
+ --manager-version "$manager_version" \
113
+ --upstream-manifest-version "$upstream_manifest_version" \
114
+ --fallback-manifest "$manifest_template"
108
115
 
109
116
  if [ -n "$additional_validator" ]; then
110
117
  [ -f "$additional_validator" ] || \
@@ -114,23 +121,6 @@ if [ -n "$additional_validator" ]; then
114
121
  fi
115
122
  fi
116
123
 
117
- # Replace the live tree with a single atomic rename, keeping a backup so a
118
- # failed swap restores the previous working generated tree (the spec requires
119
- # that a failed prepare never destroy it). tmp_plugin is a same-filesystem
120
- # sibling of plugin_root, so the renames cannot fail mid-copy.
121
- backup="$tmp_parent/.superpowers.bak.$$"
122
- rm -rf "$backup"
123
- if [ -e "$plugin_root" ]; then
124
- mv "$plugin_root" "$backup"
125
- fi
126
- if mv "$tmp_plugin" "$plugin_root"; then
127
- rm -rf "$backup"
128
- else
129
- if [ -e "$backup" ]; then
130
- mv "$backup" "$plugin_root"
131
- fi
132
- rm -rf "$tmp_plugin"
133
- spw_die "failed to install generated tree into $plugin_root; previous tree restored"
134
- fi
124
+ spw_replace_generated_tree "$tmp_plugin" "$plugin_root"
135
125
 
136
126
  echo "prepared $resolved_ref at $commit"
package/scripts/probe CHANGED
@@ -2,13 +2,12 @@
2
2
  set -eu
3
3
 
4
4
  root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
5
- . "$root/scripts/lib.sh"
6
-
7
- codex_bin="${SUPERPOWERS_CODEX:-codex}"
8
- spw_require_command "$codex_bin"
9
- spw_require_command python3
10
- identity_snapshot=$(spw_codex_identity_snapshot "$codex_bin")
11
- identity_state=$(spw_snapshot_get "$identity_snapshot" identity_state)
5
+ . "$root/scripts/core/common.sh"
6
+ . "$root/scripts/core/upstream.sh"
7
+ . "$root/scripts/core/provenance.sh"
8
+ . "$root/scripts/core/status.sh"
9
+ . "$root/scripts/core/lifecycle.sh"
10
+ . "$root/scripts/core/adapter.sh"
12
11
 
13
12
  upstream_url="${SUPERPOWERS_UPSTREAM_URL:-$SPW_UPSTREAM_URL_DEFAULT}"
14
13
  requested_ref=$(spw_config_ref "$root")
@@ -16,18 +15,30 @@ resolved_record=$(spw_resolve_ref "$upstream_url" "$requested_ref")
16
15
  resolved_ref=$(printf '%s\n' "$resolved_record" | awk '{ print $2 }')
17
16
  desired_commit=$(printf '%s\n' "$resolved_record" | awk '{ print $3 }')
18
17
 
19
- generated_metadata="$root/plugins/superpowers/.superpowers-upstream.json"
20
- generated_commit=$(spw_metadata_commit_or_empty "$generated_metadata" || true)
21
-
22
- installed_metadata=$(spw_find_installed_metadata || true)
23
- installed_manifest=$(spw_find_installed_manifest || true)
24
- installed_commit=""
25
- if [ -n "$installed_metadata" ]; then
26
- installed_commit=$(spw_metadata_commit_or_empty "$installed_metadata" || true)
27
- fi
28
- if [ -z "$installed_commit" ] && [ -n "$installed_manifest" ]; then
29
- installed_commit=$(spw_manifest_short_sha_or_empty "$installed_manifest" || true)
18
+ generated_commit=$(spw_generated_commit_or_empty "$root")
19
+ tmp_parent="${TMPDIR:-/tmp}"
20
+ if ! probe_workspace=$(mktemp -d "$tmp_parent/superpowers-manager.probe.XXXXXX"); then
21
+ spw_die "cannot create probe workspace under $tmp_parent"
30
22
  fi
23
+ fingerprint_result="$probe_workspace/fingerprint.json"
24
+ ownership_result="$probe_workspace/ownership.json"
25
+ cleanup() {
26
+ status=$?
27
+ trap - 0 HUP INT TERM
28
+ rm -rf "$probe_workspace" || :
29
+ exit "$status"
30
+ }
31
+ trap cleanup 0
32
+ trap 'exit 129' HUP
33
+ trap 'exit 130' INT
34
+ trap 'exit 143' TERM
35
+
36
+ TMPDIR="$probe_workspace"
37
+ export TMPDIR
38
+ spw_inspect_fingerprint "$fingerprint_result"
39
+ installed_commit=$(spw_adapter_result_get "$fingerprint_result" "fingerprint")
40
+ spw_inspect_ownership "$ownership_result"
41
+ identity_state=$(spw_adapter_result_get "$ownership_result" "identity_state")
31
42
 
32
43
  status=$(spw_status_for_commits "$desired_commit" "$generated_commit" "$installed_commit")
33
44
 
package/scripts/uninstall CHANGED
@@ -2,60 +2,43 @@
2
2
  set -eu
3
3
 
4
4
  root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
5
- . "$root/scripts/lib.sh"
5
+ . "$root/scripts/core/common.sh"
6
+ . "$root/scripts/core/provenance.sh"
7
+ . "$root/scripts/core/lifecycle.sh"
8
+ . "$root/scripts/core/adapter.sh"
6
9
 
7
- codex_bin="${SUPERPOWERS_CODEX:-codex}"
8
-
9
- spw_require_command "$codex_bin"
10
10
  spw_require_command python3
11
11
 
12
- # Preflight: read and parse BOTH Codex listings before removing anything, so a
13
- # read/parse failure aborts before any removal (fail closed).
14
- ownership=$(spw_codex_identity_snapshot "$codex_bin")
15
- plugin_present=$(spw_snapshot_get "$ownership" manager_plugin)
16
- marketplace_present=$(spw_snapshot_get "$ownership" manager_marketplace)
17
-
18
- # Remove the plugin first, then the marketplace, so an installed plugin is
19
- # never orphaned from a just-removed marketplace source.
20
- if [ "$plugin_present" = true ]; then
21
- if ! "$codex_bin" plugin remove "$SPW_PLUGIN_ID"; then
22
- spw_die "codex plugin remove failed for $SPW_PLUGIN_ID"
23
- fi
24
- echo "removed plugin $SPW_PLUGIN_ID"
25
- else
26
- echo "plugin not installed; skipping"
27
- fi
28
-
29
- if [ "$marketplace_present" = true ]; then
30
- if ! "$codex_bin" plugin marketplace remove "$SPW_MARKETPLACE_NAME"; then
31
- spw_die "codex plugin marketplace remove failed for $SPW_MARKETPLACE_NAME"
32
- fi
33
- echo "removed marketplace $SPW_MARKETPLACE_NAME"
34
- else
35
- echo "marketplace not registered; skipping"
12
+ tmp_parent="${TMPDIR:-/tmp}"
13
+ if ! uninstall_workspace=$(mktemp -d "$tmp_parent/superpowers-manager.uninstall.XXXXXX"); then
14
+ spw_die "cannot create uninstall workspace under $tmp_parent"
36
15
  fi
37
-
38
- # Verify-after: re-query and refuse to claim success while either manager
39
- # target survives. The strict snapshot also records whether legacy state is
40
- # still present without ever mutating that state.
41
- ownership=$(spw_codex_identity_snapshot "$codex_bin")
42
- plugin_present=$(spw_snapshot_get "$ownership" manager_plugin)
43
- marketplace_present=$(spw_snapshot_get "$ownership" manager_marketplace)
44
- identity_state=$(spw_snapshot_get "$ownership" identity_state)
45
- if [ "$plugin_present" = true ]; then
46
- spw_die "plugin $SPW_PLUGIN_ID is still installed after removal"
47
- fi
48
- if [ "$marketplace_present" = true ]; then
49
- spw_die "marketplace $SPW_MARKETPLACE_NAME is still registered after removal"
50
- fi
51
-
52
- case "$identity_state" in
53
- legacy|both)
54
- printf '%s\n' \
55
- 'Legacy superpowers-wrapper Codex state remains installed.' \
56
- 'Run: npx superpowers-wrapper@0.1.1 uninstall'
57
- ;;
58
- esac
16
+ inspect_result="$uninstall_workspace/inspect.json"
17
+ uninstall_result="$uninstall_workspace/uninstall.json"
18
+ cleanup() {
19
+ status=$?
20
+ trap - 0 HUP INT TERM
21
+ rm -rf "$uninstall_workspace" || :
22
+ exit "$status"
23
+ }
24
+ trap cleanup 0
25
+ trap 'exit 129' HUP
26
+ trap 'exit 130' INT
27
+ trap 'exit 143' TERM
28
+
29
+ TMPDIR="$uninstall_workspace"
30
+ export TMPDIR
31
+
32
+ spw_inspect_ownership "$inspect_result"
33
+ plugin_present=$(spw_adapter_result_boolean "$inspect_result" "resources.plugin")
34
+ marketplace_present=$(spw_adapter_result_boolean "$inspect_result" "resources.marketplace")
35
+
36
+ spw_adapter_uninstall "$uninstall_result" "$plugin_present" "$marketplace_present"
37
+
38
+ spw_inspect_ownership "$inspect_result"
39
+ spw_verify_uninstalled_resources "$inspect_result"
40
+ identity_state=$(spw_adapter_result_get "$inspect_result" "identity_state")
41
+ spw_report_legacy_state "$identity_state"
59
42
 
60
43
  echo "uninstall complete"
61
44
  echo "note: local generated artifacts under plugins/superpowers/ and .cache/upstream/ were left in place; remove them manually or regenerate with scripts/prepare."
package/scripts/update CHANGED
@@ -2,11 +2,12 @@
2
2
  set -eu
3
3
 
4
4
  root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
5
- . "$root/scripts/lib.sh"
5
+ . "$root/scripts/core/common.sh"
6
+ . "$root/scripts/core/lifecycle.sh"
6
7
 
7
8
  probe_output=$(sh "$root/scripts/probe" --porcelain)
8
9
  identity_state=$(printf '%s\n' "$probe_output" | awk -F= '$1 == "identity_state" { print $2 }')
9
- [ -n "$identity_state" ] || spw_die "probe did not report Codex identity state"
10
+ [ -n "$identity_state" ] || spw_die "probe did not report adapter identity state"
10
11
  spw_require_no_legacy_state "$identity_state"
11
12
  status=$(printf '%s\n' "$probe_output" | awk -F= '$1 == "status" { print $2 }')
12
13
 
@@ -18,15 +19,9 @@ case "$status" in
18
19
  needs\ prepare)
19
20
  sh "$root/scripts/prepare"
20
21
  sh "$root/scripts/install"
21
- desired_commit=$(spw_metadata_commit_or_empty "$root/plugins/superpowers/.superpowers-upstream.json" || true)
22
- [ -n "$desired_commit" ] || spw_die "generated metadata missing desired commit after install"
23
- spw_verify_refresh "$desired_commit"
24
22
  ;;
25
23
  needs\ install)
26
24
  sh "$root/scripts/install"
27
- desired_commit=$(spw_metadata_commit_or_empty "$root/plugins/superpowers/.superpowers-upstream.json" || true)
28
- [ -n "$desired_commit" ] || spw_die "generated metadata missing desired commit after install"
29
- spw_verify_refresh "$desired_commit"
30
25
  ;;
31
26
  *)
32
27
  echo "$probe_output"