superpowers-manager 0.1.6 → 0.3.0

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.
Files changed (59) hide show
  1. package/README.md +184 -64
  2. package/bin/superpowers-manager.js +9 -237
  3. package/dist/adapter-result.js +204 -0
  4. package/dist/adapter.js +649 -0
  5. package/dist/atomic.js +142 -0
  6. package/dist/cli-arguments.js +32 -0
  7. package/dist/cli.js +293 -0
  8. package/dist/codex-json.js +89 -0
  9. package/dist/codex-state.js +78 -0
  10. package/dist/commands/context.js +1 -0
  11. package/dist/commands/install.js +376 -0
  12. package/dist/commands/pin.js +79 -0
  13. package/dist/commands/prepare.js +527 -0
  14. package/dist/commands/probe.js +392 -0
  15. package/dist/commands/track-latest.js +44 -0
  16. package/dist/commands/uninstall.js +308 -0
  17. package/dist/commands/unpin.js +95 -0
  18. package/dist/commands/update.js +138 -0
  19. package/dist/domain/fingerprint.js +4 -0
  20. package/dist/domain/refs.js +37 -0
  21. package/dist/effective-selection.js +123 -0
  22. package/dist/generated-plugin.js +748 -0
  23. package/dist/git.js +38 -0
  24. package/dist/hooks.js +290 -0
  25. package/dist/lifecycle.js +220 -0
  26. package/dist/manifest-overlay.js +125 -0
  27. package/dist/provenance.js +111 -0
  28. package/dist/python-json-format.js +83 -0
  29. package/dist/python-json.js +29 -0
  30. package/dist/python-text.js +74 -0
  31. package/dist/safe-path.js +137 -0
  32. package/dist/safety-error.js +10 -0
  33. package/dist/selection-state-cli.js +85 -0
  34. package/dist/selection-store.js +172 -0
  35. package/dist/selection.js +200 -0
  36. package/dist/status.js +24 -0
  37. package/dist/strict-json.js +248 -0
  38. package/dist/upstream-cli.js +110 -0
  39. package/dist/upstream-version.js +40 -0
  40. package/dist/upstream.js +253 -0
  41. package/dist/validate-generated-plugin-cli.js +118 -0
  42. package/dist/validator.js +317 -0
  43. package/dist/workspace.js +139 -0
  44. package/package.json +25 -2
  45. package/scripts/adapters/codex/adapter +0 -598
  46. package/scripts/adapters/codex/lib.sh +0 -391
  47. package/scripts/adapters/codex/validate-generated-plugin.py +0 -314
  48. package/scripts/core/adapter.sh +0 -92
  49. package/scripts/core/common.sh +0 -35
  50. package/scripts/core/lifecycle.sh +0 -127
  51. package/scripts/core/provenance.sh +0 -135
  52. package/scripts/core/status.sh +0 -27
  53. package/scripts/core/upstream.sh +0 -146
  54. package/scripts/core/validate-adapter-response.py +0 -245
  55. package/scripts/install +0 -60
  56. package/scripts/prepare +0 -126
  57. package/scripts/probe +0 -61
  58. package/scripts/uninstall +0 -44
  59. package/scripts/update +0 -31
@@ -1,598 +0,0 @@
1
- #!/bin/sh
2
- set -eu
3
-
4
- root=$(CDPATH= cd -- "$(dirname "$0")/../../.." && pwd)
5
- . "$root/scripts/core/common.sh"
6
- . "$root/scripts/adapters/codex/lib.sh"
7
-
8
- spw_codex_argument_error() {
9
- operation="$1"
10
- message="$2"
11
- spw_codex_failure "$operation" "invalid-arguments" "$message" "" ""
12
- }
13
-
14
- spw_codex_require_command() {
15
- operation="$1"
16
- command_name="$2"
17
- if ! command -v "$command_name" >/dev/null 2>&1; then
18
- spw_codex_failure "$operation" "command-not-found" \
19
- "required Codex command not found: $command_name" "" ""
20
- fi
21
- }
22
-
23
- spw_codex_require_absolute_path() {
24
- operation="$1"
25
- value="$2"
26
- flag="$3"
27
- case "$value" in
28
- /*) ;;
29
- *) spw_codex_argument_error "$operation" "$flag must be an absolute path" ;;
30
- esac
31
- }
32
-
33
- spw_codex_read_source_from_provenance() {
34
- provenance_path="$1"
35
- python3 - "$provenance_path" <<'PY'
36
- import json
37
- import sys
38
-
39
- path = sys.argv[1]
40
- try:
41
- with open(path, encoding="utf-8") as handle:
42
- data = json.load(handle)
43
- except (OSError, UnicodeError, json.JSONDecodeError, RecursionError, ValueError):
44
- sys.exit(1)
45
- if not isinstance(data, dict):
46
- sys.exit(1)
47
- source = data.get("source")
48
- if not isinstance(source, str) or not source:
49
- sys.exit(1)
50
- print(source)
51
- PY
52
- }
53
-
54
- spw_codex_capture_command() {
55
- messages_file="$1"
56
- stdout_file="$2"
57
- stderr_file="$3"
58
- shift 3
59
- : > "$stdout_file"
60
- : > "$stderr_file"
61
- if "$@" >"$stdout_file" 2>"$stderr_file"; then
62
- spw_codex_append_messages "$messages_file" stderr "$stdout_file"
63
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
64
- return 0
65
- fi
66
- spw_codex_append_messages "$messages_file" stderr "$stdout_file"
67
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
68
- return 1
69
- }
70
-
71
- spw_codex_install_result_json() {
72
- mismatch_hint="$1"
73
- missing_hint="$2"
74
- python3 - "$mismatch_hint" "$missing_hint" <<'PY'
75
- import json
76
- import sys
77
-
78
- mismatch_hint, missing_hint = sys.argv[1:]
79
- hints = {}
80
- if mismatch_hint:
81
- hints["mismatch"] = mismatch_hint
82
- if missing_hint:
83
- hints["missing"] = missing_hint
84
- json.dump({"verification_hints": hints}, sys.stdout, allow_nan=False, separators=(",", ":"))
85
- sys.stdout.write("\n")
86
- PY
87
- }
88
-
89
- spw_codex_append_message_text() {
90
- messages_file="$1"
91
- channel="$2"
92
- text="$3"
93
- python3 - "$messages_file" "$channel" "$text" <<'PY'
94
- import sys
95
-
96
- path, channel, text = sys.argv[1:]
97
- escaped = text.encode("unicode_escape").decode("ascii")
98
- with open(path, "a", encoding="utf-8") as handle:
99
- handle.write(f"{channel}\t{escaped}\n")
100
- PY
101
- }
102
-
103
- spw_codex_build() {
104
- upstream_root=
105
- candidate_root=
106
- requested_ref=
107
- resolved_ref=
108
- commit=
109
- manager_version=
110
- upstream_manifest_version=
111
- fallback_manifest=
112
- seen_upstream_root=0
113
- seen_candidate_root=0
114
- seen_requested_ref=0
115
- seen_resolved_ref=0
116
- seen_commit=0
117
- seen_manager_version=0
118
- seen_upstream_manifest_version=0
119
- seen_fallback_manifest=0
120
-
121
- while [ "$#" -gt 0 ]; do
122
- flag="$1"
123
- shift
124
- case "$flag" in
125
- --upstream-root)
126
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --upstream-root"
127
- [ "$seen_upstream_root" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --upstream-root"
128
- upstream_root="$1"
129
- seen_upstream_root=1
130
- shift
131
- ;;
132
- --candidate-root)
133
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --candidate-root"
134
- [ "$seen_candidate_root" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --candidate-root"
135
- candidate_root="$1"
136
- seen_candidate_root=1
137
- shift
138
- ;;
139
- --requested-ref)
140
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --requested-ref"
141
- [ "$seen_requested_ref" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --requested-ref"
142
- requested_ref="$1"
143
- seen_requested_ref=1
144
- shift
145
- ;;
146
- --resolved-ref)
147
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --resolved-ref"
148
- [ "$seen_resolved_ref" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --resolved-ref"
149
- resolved_ref="$1"
150
- seen_resolved_ref=1
151
- shift
152
- ;;
153
- --commit)
154
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --commit"
155
- [ "$seen_commit" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --commit"
156
- commit="$1"
157
- seen_commit=1
158
- shift
159
- ;;
160
- --manager-version)
161
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --manager-version"
162
- [ "$seen_manager_version" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --manager-version"
163
- manager_version="$1"
164
- seen_manager_version=1
165
- shift
166
- ;;
167
- --upstream-manifest-version)
168
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --upstream-manifest-version"
169
- [ "$seen_upstream_manifest_version" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --upstream-manifest-version"
170
- upstream_manifest_version="$1"
171
- seen_upstream_manifest_version=1
172
- shift
173
- ;;
174
- --fallback-manifest)
175
- [ "$#" -gt 0 ] || spw_codex_argument_error build "missing value for --fallback-manifest"
176
- [ "$seen_fallback_manifest" -eq 0 ] || spw_codex_argument_error build "duplicate flag: --fallback-manifest"
177
- fallback_manifest="$1"
178
- seen_fallback_manifest=1
179
- shift
180
- ;;
181
- *)
182
- spw_codex_argument_error build "unknown flag: $flag"
183
- ;;
184
- esac
185
- done
186
-
187
- [ "$seen_upstream_root" -eq 1 ] || spw_codex_argument_error build "missing required flag: --upstream-root"
188
- [ "$seen_candidate_root" -eq 1 ] || spw_codex_argument_error build "missing required flag: --candidate-root"
189
- [ "$seen_requested_ref" -eq 1 ] || spw_codex_argument_error build "missing required flag: --requested-ref"
190
- [ "$seen_resolved_ref" -eq 1 ] || spw_codex_argument_error build "missing required flag: --resolved-ref"
191
- [ "$seen_commit" -eq 1 ] || spw_codex_argument_error build "missing required flag: --commit"
192
- [ "$seen_manager_version" -eq 1 ] || spw_codex_argument_error build "missing required flag: --manager-version"
193
- [ "$seen_upstream_manifest_version" -eq 1 ] || spw_codex_argument_error build "missing required flag: --upstream-manifest-version"
194
- [ "$seen_fallback_manifest" -eq 1 ] || spw_codex_argument_error build "missing required flag: --fallback-manifest"
195
-
196
- spw_codex_require_absolute_path build "$upstream_root" "--upstream-root"
197
- spw_codex_require_absolute_path build "$candidate_root" "--candidate-root"
198
- [ -d "$upstream_root" ] || spw_codex_argument_error build "upstream root not found: $upstream_root"
199
- [ -d "$candidate_root" ] || spw_codex_argument_error build "candidate root not found: $candidate_root"
200
- [ -f "$fallback_manifest" ] || spw_codex_argument_error build "fallback manifest not found: $fallback_manifest"
201
-
202
- validator="$root/scripts/adapters/codex/validate-generated-plugin.py"
203
- [ -f "$validator" ] || spw_codex_failure build "build-failed" "missing built-in plugin validator: $validator" "" ""
204
-
205
- tmp_parent="${TMPDIR:-/tmp}"
206
- if ! scratch=$(mktemp -d "$tmp_parent/superpowers-manager.adapter-build.XXXXXX"); then
207
- spw_codex_failure build "build-failed" "cannot create adapter build workspace under $tmp_parent" "" ""
208
- fi
209
- stdout_file="$scratch/stdout"
210
- stderr_file="$scratch/stderr"
211
- messages_file="$scratch/messages"
212
- candidate_manifest="$candidate_root/.codex-plugin/plugin.json"
213
- provenance_path="$candidate_root/.superpowers-upstream.json"
214
- cleanup() {
215
- status=$?
216
- trap - 0 HUP INT TERM
217
- rm -rf "$scratch" || :
218
- exit "$status"
219
- }
220
- trap cleanup 0
221
- trap 'exit 129' HUP
222
- trap 'exit 130' INT
223
- trap 'exit 143' TERM
224
-
225
- mkdir -p "$candidate_root/.codex-plugin"
226
- : > "$messages_file"
227
-
228
- upstream_manifest="$upstream_root/.codex-plugin/plugin.json"
229
- if [ -f "$upstream_manifest" ]; then
230
- if ! cp "$upstream_manifest" "$candidate_manifest"; then
231
- spw_codex_failure build "build-failed" "cannot copy upstream manifest into candidate" "" "$messages_file"
232
- fi
233
- else
234
- if ! cp "$fallback_manifest" "$candidate_manifest"; then
235
- spw_codex_failure build "build-failed" "cannot copy fallback manifest into candidate" "" "$messages_file"
236
- fi
237
- fi
238
-
239
- if ! spw_apply_manifest_overlay "$candidate_manifest" "$manager_version"; then
240
- spw_codex_failure build "build-failed" "failed to apply manager manifest overlay" "" "$messages_file"
241
- fi
242
-
243
- if ! cp "$fallback_manifest" "$candidate_root/.codex-plugin/plugin.template.json"; then
244
- spw_codex_failure build "build-failed" "cannot copy fallback manifest template into candidate" "" "$messages_file"
245
- fi
246
-
247
- if ! upstream_source=$(spw_codex_read_source_from_provenance "$provenance_path"); then
248
- spw_codex_failure build "invalid-provenance" "candidate provenance is missing or invalid" "" "$messages_file"
249
- fi
250
-
251
- if python3 -S "$validator" \
252
- --plugin-root "$candidate_root" \
253
- --source "$upstream_source" \
254
- --requested-ref "$requested_ref" \
255
- --resolved-ref "$resolved_ref" \
256
- --commit "$commit" \
257
- --manifest-version "$manager_version" \
258
- --upstream-manifest-version "$upstream_manifest_version" \
259
- >"$stdout_file" 2>"$stderr_file"; then
260
- spw_codex_append_messages "$messages_file" stdout "$stdout_file"
261
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
262
- spw_codex_success build '{}' "$messages_file"
263
- else
264
- spw_codex_append_messages "$messages_file" stdout "$stdout_file"
265
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
266
- spw_codex_failure build "generated-plugin-validation-failed" "built-in generated plugin validation failed" "" "$messages_file"
267
- fi
268
- }
269
-
270
- spw_codex_install() {
271
- package_root=
272
- seen_package_root=0
273
-
274
- while [ "$#" -gt 0 ]; do
275
- flag="$1"
276
- shift
277
- case "$flag" in
278
- --package-root)
279
- [ "$#" -gt 0 ] || spw_codex_argument_error install "missing value for --package-root"
280
- [ "$seen_package_root" -eq 0 ] || spw_codex_argument_error install "duplicate flag: --package-root"
281
- package_root="$1"
282
- seen_package_root=1
283
- shift
284
- ;;
285
- *)
286
- spw_codex_argument_error install "unknown flag: $flag"
287
- ;;
288
- esac
289
- done
290
-
291
- [ "$seen_package_root" -eq 1 ] || spw_codex_argument_error install "missing required flag: --package-root"
292
- spw_codex_require_absolute_path install "$package_root" "--package-root"
293
- [ -d "$package_root" ] || spw_codex_argument_error install "package root not found: $package_root"
294
-
295
- codex_bin="${SUPERPOWERS_CODEX:-codex}"
296
- refresh_mode="${SUPERPOWERS_INSTALL_REFRESH_MODE:-add-only}"
297
- spw_require_command python3
298
- spw_codex_require_command install "$codex_bin"
299
- case "$refresh_mode" in
300
- add-only|remove-add) ;;
301
- *) spw_codex_failure install "invalid-arguments" "unsupported SUPERPOWERS_INSTALL_REFRESH_MODE: $refresh_mode" "" "" ;;
302
- esac
303
-
304
- tmp_parent="${TMPDIR:-/tmp}"
305
- if ! scratch=$(mktemp -d "$tmp_parent/superpowers-manager.adapter-install.XXXXXX"); then
306
- spw_codex_failure install "install-failed" "cannot create adapter install workspace under $tmp_parent" "" ""
307
- fi
308
- stdout_file="$scratch/stdout"
309
- stderr_file="$scratch/stderr"
310
- messages_file="$scratch/messages"
311
- hints_file="$scratch/hints"
312
- cleanup() {
313
- status=$?
314
- trap - 0 HUP INT TERM
315
- rm -rf "$scratch" || :
316
- exit "$status"
317
- }
318
- trap cleanup 0
319
- trap 'exit 129' HUP
320
- trap 'exit 130' INT
321
- trap 'exit 143' TERM
322
-
323
- : > "$messages_file"
324
- : > "$hints_file"
325
-
326
- : > "$stderr_file"
327
- if ! listing=$("$codex_bin" plugin marketplace list --json 2>"$stderr_file"); then
328
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
329
- spw_codex_failure install "install-failed" "cannot list Codex marketplaces via '$codex_bin plugin marketplace list --json'" "$hints_file" "$messages_file"
330
- fi
331
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
332
- if ! registered_root=$(spw_marketplace_root_from_json "$listing" "$SPW_MARKETPLACE_NAME"); then
333
- spw_codex_failure install "install-failed" "cannot parse output of '$codex_bin plugin marketplace list --json'" "$hints_file" "$messages_file"
334
- fi
335
-
336
- if [ -z "$registered_root" ]; then
337
- if ! spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin marketplace add "$package_root"; then
338
- spw_codex_failure install "install-failed" "codex marketplace add failed for $package_root" "$hints_file" "$messages_file"
339
- fi
340
- else
341
- if ! path_relation=$(spw_paths_equal "$package_root" "$registered_root"); then
342
- spw_codex_failure install "install-failed" "cannot compare registered and requested marketplace roots" "$hints_file" "$messages_file"
343
- fi
344
- case "$path_relation" in
345
- same) ;;
346
- different)
347
- spw_codex_append_message_text "$messages_file" stdout \
348
- "marketplace $SPW_MARKETPLACE_NAME registered at $registered_root; re-registering at $package_root"
349
- if ! spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin marketplace remove "$SPW_MARKETPLACE_NAME"; then
350
- spw_codex_failure install "install-failed" "codex marketplace remove failed for $SPW_MARKETPLACE_NAME (registered at $registered_root)" "$hints_file" "$messages_file"
351
- fi
352
- if ! spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin marketplace add "$package_root"; then
353
- printf 'recover with: %s plugin marketplace add %s\n' "$codex_bin" "$package_root" >> "$hints_file"
354
- printf 'previous root (last known good): %s\n' "$registered_root" >> "$hints_file"
355
- spw_codex_failure install "install-failed" "marketplace $SPW_MARKETPLACE_NAME was removed but re-adding failed." "$hints_file" "$messages_file"
356
- fi
357
- ;;
358
- *)
359
- spw_codex_failure install "install-failed" "invalid marketplace path comparison result" "$hints_file" "$messages_file"
360
- ;;
361
- esac
362
- fi
363
-
364
- if [ "$refresh_mode" = remove-add ]; then
365
- spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin remove "$SPW_PLUGIN_ID" || true
366
- fi
367
-
368
- if ! spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin add "$SPW_PLUGIN_ID"; then
369
- spw_codex_failure install "install-failed" "codex plugin add failed for $SPW_PLUGIN_ID" "$hints_file" "$messages_file"
370
- fi
371
-
372
- mismatch_hint=
373
- case "$refresh_mode" in
374
- add-only)
375
- mismatch_hint="retry with SUPERPOWERS_INSTALL_REFRESH_MODE=remove-add"
376
- ;;
377
- esac
378
- missing_hint="verify with 'codex plugin list --json'."
379
- result_json=$(spw_codex_install_result_json "$mismatch_hint" "$missing_hint")
380
- spw_codex_success install "$result_json" "$messages_file"
381
- }
382
-
383
- spw_codex_uninstall() {
384
- plugin_present=
385
- marketplace_present=
386
- seen_plugin_present=0
387
- seen_marketplace_present=0
388
-
389
- while [ "$#" -gt 0 ]; do
390
- flag="$1"
391
- shift
392
- case "$flag" in
393
- --plugin-present)
394
- [ "$#" -gt 0 ] || spw_codex_argument_error uninstall "missing value for --plugin-present"
395
- [ "$seen_plugin_present" -eq 0 ] || spw_codex_argument_error uninstall "duplicate flag: --plugin-present"
396
- plugin_present="$1"
397
- seen_plugin_present=1
398
- shift
399
- ;;
400
- --marketplace-present)
401
- [ "$#" -gt 0 ] || spw_codex_argument_error uninstall "missing value for --marketplace-present"
402
- [ "$seen_marketplace_present" -eq 0 ] || spw_codex_argument_error uninstall "duplicate flag: --marketplace-present"
403
- marketplace_present="$1"
404
- seen_marketplace_present=1
405
- shift
406
- ;;
407
- *)
408
- spw_codex_argument_error uninstall "unknown flag: $flag"
409
- ;;
410
- esac
411
- done
412
-
413
- [ "$seen_plugin_present" -eq 1 ] || spw_codex_argument_error uninstall "missing required flag: --plugin-present"
414
- [ "$seen_marketplace_present" -eq 1 ] || spw_codex_argument_error uninstall "missing required flag: --marketplace-present"
415
- case "$plugin_present" in
416
- true|false) ;;
417
- *) spw_codex_argument_error uninstall "--plugin-present must be true or false" ;;
418
- esac
419
- case "$marketplace_present" in
420
- true|false) ;;
421
- *) spw_codex_argument_error uninstall "--marketplace-present must be true or false" ;;
422
- esac
423
-
424
- codex_bin="${SUPERPOWERS_CODEX:-codex}"
425
- spw_require_command python3
426
- spw_codex_require_command uninstall "$codex_bin"
427
-
428
- tmp_parent="${TMPDIR:-/tmp}"
429
- if ! scratch=$(mktemp -d "$tmp_parent/superpowers-manager.adapter-uninstall.XXXXXX"); then
430
- spw_codex_failure uninstall "uninstall-failed" "cannot create adapter uninstall workspace under $tmp_parent" "" ""
431
- fi
432
- stdout_file="$scratch/stdout"
433
- stderr_file="$scratch/stderr"
434
- messages_file="$scratch/messages"
435
- cleanup() {
436
- status=$?
437
- trap - 0 HUP INT TERM
438
- rm -rf "$scratch" || :
439
- exit "$status"
440
- }
441
- trap cleanup 0
442
- trap 'exit 129' HUP
443
- trap 'exit 130' INT
444
- trap 'exit 143' TERM
445
-
446
- : > "$messages_file"
447
-
448
- if [ "$plugin_present" = true ]; then
449
- if ! spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin remove "$SPW_PLUGIN_ID"; then
450
- spw_codex_failure uninstall "uninstall-failed" "codex plugin remove failed for $SPW_PLUGIN_ID" "" "$messages_file"
451
- fi
452
- spw_codex_append_message_text "$messages_file" stdout "removed plugin $SPW_PLUGIN_ID"
453
- else
454
- spw_codex_append_message_text "$messages_file" stdout "plugin not installed; skipping"
455
- fi
456
-
457
- if [ "$marketplace_present" = true ]; then
458
- if ! spw_codex_capture_command "$messages_file" "$stdout_file" "$stderr_file" "$codex_bin" plugin marketplace remove "$SPW_MARKETPLACE_NAME"; then
459
- spw_codex_failure uninstall "uninstall-failed" "codex plugin marketplace remove failed for $SPW_MARKETPLACE_NAME" "" "$messages_file"
460
- fi
461
- spw_codex_append_message_text "$messages_file" stdout "removed marketplace $SPW_MARKETPLACE_NAME"
462
- else
463
- spw_codex_append_message_text "$messages_file" stdout "marketplace not registered; skipping"
464
- fi
465
-
466
- spw_codex_success uninstall '{}' "$messages_file"
467
- }
468
-
469
- spw_codex_inspect() {
470
- view=
471
- seen_view=0
472
-
473
- while [ "$#" -gt 0 ]; do
474
- flag="$1"
475
- shift
476
- case "$flag" in
477
- --view)
478
- [ "$#" -gt 0 ] || spw_codex_argument_error inspect "missing value for --view"
479
- [ "$seen_view" -eq 0 ] || spw_codex_argument_error inspect "duplicate flag: --view"
480
- view="$1"
481
- seen_view=1
482
- shift
483
- ;;
484
- *)
485
- spw_codex_argument_error inspect "unknown flag: $flag"
486
- ;;
487
- esac
488
- done
489
-
490
- [ "$seen_view" -eq 1 ] || spw_codex_argument_error inspect "missing required flag: --view"
491
-
492
- case "$view" in
493
- fingerprint)
494
- fingerprint=$(spw_installed_commit_or_empty || true)
495
- if [ -n "$fingerprint" ]; then
496
- spw_codex_success inspect "{\"view\":\"fingerprint\",\"fingerprint\":\"$fingerprint\"}" ""
497
- else
498
- spw_codex_success inspect '{"view":"fingerprint","fingerprint":null}' ""
499
- fi
500
- ;;
501
- ownership)
502
- codex_bin="${SUPERPOWERS_CODEX:-codex}"
503
- spw_require_command python3
504
- spw_codex_require_command inspect "$codex_bin"
505
-
506
- tmp_parent="${TMPDIR:-/tmp}"
507
- if ! scratch=$(mktemp -d "$tmp_parent/superpowers-manager.adapter-inspect.XXXXXX"); then
508
- spw_codex_failure inspect "inspect-failed" "cannot create adapter inspect workspace under $tmp_parent" "" ""
509
- fi
510
- stderr_file="$scratch/stderr"
511
- messages_file="$scratch/messages"
512
- cleanup() {
513
- status=$?
514
- trap - 0 HUP INT TERM
515
- rm -rf "$scratch" || :
516
- exit "$status"
517
- }
518
- trap cleanup 0
519
- trap 'exit 129' HUP
520
- trap 'exit 130' INT
521
- trap 'exit 143' TERM
522
-
523
- : > "$messages_file"
524
-
525
- : > "$stderr_file"
526
- if ! plugin_listing=$("$codex_bin" plugin list --json 2>"$stderr_file"); then
527
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
528
- spw_codex_failure inspect "inspect-failed" "cannot list Codex plugins via '$codex_bin plugin list --json'" "" "$messages_file"
529
- fi
530
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
531
- if ! plugin_result=$(spw_json_array_has "$plugin_listing" "installed" "pluginId" "$SPW_PLUGIN_ID"); then
532
- spw_codex_failure inspect "inspect-failed" "cannot parse output of '$codex_bin plugin list --json'" "" "$messages_file"
533
- fi
534
- if ! legacy_plugin_result=$(spw_json_array_has "$plugin_listing" "installed" "pluginId" "$SPW_LEGACY_PLUGIN_ID"); then
535
- spw_codex_failure inspect "inspect-failed" "cannot parse output of '$codex_bin plugin list --json'" "" "$messages_file"
536
- fi
537
-
538
- : > "$stderr_file"
539
- if ! marketplace_listing=$("$codex_bin" plugin marketplace list --json 2>"$stderr_file"); then
540
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
541
- spw_codex_failure inspect "inspect-failed" "cannot list Codex marketplaces via '$codex_bin plugin marketplace list --json'" "" "$messages_file"
542
- fi
543
- spw_codex_append_messages "$messages_file" stderr "$stderr_file"
544
- if ! marketplace_result=$(spw_json_array_has "$marketplace_listing" "marketplaces" "name" "$SPW_MARKETPLACE_NAME"); then
545
- spw_codex_failure inspect "inspect-failed" "cannot parse output of '$codex_bin plugin marketplace list --json'" "" "$messages_file"
546
- fi
547
- if ! legacy_marketplace_result=$(spw_json_array_has "$marketplace_listing" "marketplaces" "name" "$SPW_LEGACY_MARKETPLACE_NAME"); then
548
- spw_codex_failure inspect "inspect-failed" "cannot parse output of '$codex_bin plugin marketplace list --json'" "" "$messages_file"
549
- fi
550
-
551
- manager_present=false
552
- legacy_present=false
553
- if [ "$plugin_result" = present ] || [ "$marketplace_result" = present ]; then
554
- manager_present=true
555
- fi
556
- if [ "$legacy_plugin_result" = present ] || [ "$legacy_marketplace_result" = present ]; then
557
- legacy_present=true
558
- fi
559
- case "$manager_present:$legacy_present" in
560
- false:false) identity_state=neither ;;
561
- true:false) identity_state=manager ;;
562
- false:true) identity_state=legacy ;;
563
- true:true) identity_state=both ;;
564
- *) spw_codex_failure inspect "inspect-failed" "cannot derive Codex identity state" "" "$messages_file" ;;
565
- esac
566
-
567
- spw_codex_success inspect \
568
- "{\"view\":\"ownership\",\"resources\":{\"plugin\":$([ "$plugin_result" = present ] && printf true || printf false),\"marketplace\":$([ "$marketplace_result" = present ] && printf true || printf false)},\"legacy_resources\":{\"plugin\":$([ "$legacy_plugin_result" = present ] && printf true || printf false),\"marketplace\":$([ "$legacy_marketplace_result" = present ] && printf true || printf false)},\"identity_state\":\"$identity_state\"}" \
569
- "$messages_file"
570
- ;;
571
- *)
572
- spw_codex_argument_error inspect "unsupported inspect view: $view"
573
- ;;
574
- esac
575
- }
576
-
577
- operation="${1:-}"
578
- [ -n "$operation" ] || spw_codex_failure adapter "invalid-arguments" "missing adapter operation" "" ""
579
- shift
580
-
581
- case "$operation" in
582
- build)
583
- spw_codex_build "$@"
584
- ;;
585
- install)
586
- spw_codex_install "$@"
587
- ;;
588
- inspect)
589
- spw_codex_inspect "$@"
590
- ;;
591
- uninstall)
592
- spw_codex_uninstall "$@"
593
- ;;
594
- *)
595
- spw_codex_emit "$operation" false '{}' "unsupported-operation" "unsupported adapter operation: $operation" "" ""
596
- exit 1
597
- ;;
598
- esac