superpowers-manager 0.2.0 → 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.
- package/README.md +112 -47
- package/bin/superpowers-manager.js +9 -283
- package/dist/adapter-result.js +204 -0
- package/dist/adapter.js +649 -0
- package/dist/atomic.js +142 -0
- package/dist/cli-arguments.js +32 -0
- package/dist/cli.js +293 -0
- package/dist/codex-json.js +89 -0
- package/dist/codex-state.js +78 -0
- package/dist/commands/context.js +1 -0
- package/dist/commands/install.js +376 -0
- package/dist/commands/pin.js +79 -0
- package/dist/commands/prepare.js +527 -0
- package/dist/commands/probe.js +392 -0
- package/dist/commands/track-latest.js +44 -0
- package/dist/commands/uninstall.js +308 -0
- package/dist/commands/unpin.js +95 -0
- package/dist/commands/update.js +138 -0
- package/dist/domain/fingerprint.js +4 -0
- package/dist/domain/refs.js +37 -0
- package/dist/effective-selection.js +123 -0
- package/dist/generated-plugin.js +748 -0
- package/dist/git.js +38 -0
- package/dist/hooks.js +290 -0
- package/dist/lifecycle.js +220 -0
- package/dist/manifest-overlay.js +125 -0
- package/dist/provenance.js +111 -0
- package/dist/python-json-format.js +83 -0
- package/dist/python-json.js +29 -0
- package/dist/python-text.js +74 -0
- package/dist/safe-path.js +137 -0
- package/dist/safety-error.js +10 -0
- package/dist/selection-state-cli.js +85 -0
- package/dist/selection-store.js +172 -0
- package/dist/selection.js +200 -0
- package/dist/status.js +24 -0
- package/dist/strict-json.js +248 -0
- package/dist/upstream-cli.js +110 -0
- package/dist/upstream-version.js +40 -0
- package/dist/upstream.js +253 -0
- package/dist/validate-generated-plugin-cli.js +118 -0
- package/dist/validator.js +317 -0
- package/dist/workspace.js +139 -0
- package/package.json +25 -2
- package/scripts/adapters/codex/adapter +0 -603
- package/scripts/adapters/codex/lib.sh +0 -449
- package/scripts/adapters/codex/validate-generated-plugin.py +0 -314
- package/scripts/core/adapter.sh +0 -103
- package/scripts/core/common.sh +0 -59
- package/scripts/core/lifecycle.sh +0 -141
- package/scripts/core/provenance.sh +0 -135
- package/scripts/core/selection-state.py +0 -414
- package/scripts/core/selection.sh +0 -168
- package/scripts/core/status.sh +0 -27
- package/scripts/core/upstream.sh +0 -280
- package/scripts/core/validate-adapter-response.py +0 -284
- package/scripts/install +0 -59
- package/scripts/pin +0 -51
- package/scripts/prepare +0 -117
- package/scripts/probe +0 -82
- package/scripts/track-latest +0 -30
- package/scripts/uninstall +0 -35
- package/scripts/unpin +0 -41
- package/scripts/update +0 -34
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// `selectionError` already exists at
|
|
2
|
+
// `src/selection.ts:41::export function selectionError` and tags errors with
|
|
3
|
+
// module "selection". Import it rather than defining a second one.
|
|
4
|
+
import { normalizeSaved, selectionError, validateSource, } from "./selection.js";
|
|
5
|
+
import { readSelectionState } from "./selection-store.js";
|
|
6
|
+
import { readConfigRef, resolveRef } from "./upstream.js";
|
|
7
|
+
import { COMMIT_RE } from "./domain/refs.js";
|
|
8
|
+
function requireAbsolute(value, variable) {
|
|
9
|
+
if (!value.startsWith("/")) {
|
|
10
|
+
throw selectionError(`${variable} must be absolute`);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
// Precedence mirrors
|
|
15
|
+
// `git show ad56569a4c161e7b122967442e2b026eeb6395f6:scripts/core/selection.sh:4-29::spw_selection_config_dir(`.
|
|
16
|
+
// SUPERPOWERS_CONFIG_DIR is selected on *presence*, matching the shell's
|
|
17
|
+
// ${SUPERPOWERS_CONFIG_DIR+x}: an empty value takes this branch and then fails
|
|
18
|
+
// the absolute check, rather than falling through to XDG.
|
|
19
|
+
export function selectionConfigDir(env) {
|
|
20
|
+
const explicit = env.SUPERPOWERS_CONFIG_DIR;
|
|
21
|
+
if (explicit !== undefined) {
|
|
22
|
+
return requireAbsolute(explicit, "SUPERPOWERS_CONFIG_DIR");
|
|
23
|
+
}
|
|
24
|
+
const xdg = env.XDG_CONFIG_HOME;
|
|
25
|
+
if (xdg !== undefined && xdg.length > 0) {
|
|
26
|
+
return `${requireAbsolute(xdg, "XDG_CONFIG_HOME")}/superpowers-manager`;
|
|
27
|
+
}
|
|
28
|
+
const home = env.HOME;
|
|
29
|
+
if (home === undefined || home.length === 0) {
|
|
30
|
+
throw selectionError("HOME is required to locate selection state");
|
|
31
|
+
}
|
|
32
|
+
return `${requireAbsolute(home, "HOME")}/.config/superpowers-manager`;
|
|
33
|
+
}
|
|
34
|
+
export function selectionStatePath(env) {
|
|
35
|
+
return `${selectionConfigDir(env)}/selection.json`;
|
|
36
|
+
}
|
|
37
|
+
// Composes exactly what `src/selection-state-cli.ts:39::const normalized`
|
|
38
|
+
// composes. The shell wrote a normalized document to a mktemp file and read
|
|
39
|
+
// five fields back with five python3 invocations; in-process this is one call.
|
|
40
|
+
export async function loadSavedSelection(env) {
|
|
41
|
+
return normalizeSaved(await readSelectionState(selectionStatePath(env)));
|
|
42
|
+
}
|
|
43
|
+
export const UPSTREAM_URL_DEFAULT = "https://github.com/obra/superpowers";
|
|
44
|
+
// Ports the env > saved > package-default precedence ladder from
|
|
45
|
+
// `git show ad56569a4c161e7b122967442e2b026eeb6395f6:scripts/core/selection.sh:88-162::spw_compute_effective_selection`.
|
|
46
|
+
// validateSource runs before any ref resolution -- pinned by
|
|
47
|
+
// tests/unit/effective-selection.test.js's "source validation precedes ref
|
|
48
|
+
// resolution": a credential-bearing source must fail before Git is ever
|
|
49
|
+
// invoked.
|
|
50
|
+
export async function computeEffectiveSelection(root, env) {
|
|
51
|
+
const saved = await loadSavedSelection(env);
|
|
52
|
+
let upstreamSourceOrigin;
|
|
53
|
+
let effectiveSource;
|
|
54
|
+
if (env.SUPERPOWERS_UPSTREAM_URL) {
|
|
55
|
+
upstreamSourceOrigin = "environment";
|
|
56
|
+
effectiveSource = env.SUPERPOWERS_UPSTREAM_URL;
|
|
57
|
+
}
|
|
58
|
+
else if (saved.saved_mode !== "none") {
|
|
59
|
+
upstreamSourceOrigin = "user-config";
|
|
60
|
+
effectiveSource = saved.saved_source;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
upstreamSourceOrigin = "package-default";
|
|
64
|
+
effectiveSource = UPSTREAM_URL_DEFAULT;
|
|
65
|
+
}
|
|
66
|
+
// Before any Git access. Pinned by tests/unit/effective-selection.test.js's
|
|
67
|
+
// "source validation precedes ref resolution".
|
|
68
|
+
validateSource(effectiveSource);
|
|
69
|
+
let selectionOrigin;
|
|
70
|
+
let selectionMode;
|
|
71
|
+
let requestedRef;
|
|
72
|
+
let usesSavedPin = false;
|
|
73
|
+
if (env.SUPERPOWERS_REF) {
|
|
74
|
+
selectionOrigin = "environment";
|
|
75
|
+
selectionMode = "override";
|
|
76
|
+
requestedRef = env.SUPERPOWERS_REF;
|
|
77
|
+
}
|
|
78
|
+
else if (saved.saved_mode === "pinned") {
|
|
79
|
+
selectionOrigin = "user-config";
|
|
80
|
+
selectionMode = "pinned";
|
|
81
|
+
requestedRef = saved.saved_requested_ref;
|
|
82
|
+
usesSavedPin = true;
|
|
83
|
+
}
|
|
84
|
+
else if (saved.saved_mode === "track-latest") {
|
|
85
|
+
selectionOrigin = "user-config";
|
|
86
|
+
selectionMode = "track-latest";
|
|
87
|
+
requestedRef = "latest-release";
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
selectionOrigin = "package-default";
|
|
91
|
+
selectionMode = "default";
|
|
92
|
+
requestedRef = await readConfigRef(root, env);
|
|
93
|
+
}
|
|
94
|
+
if (usesSavedPin) {
|
|
95
|
+
return {
|
|
96
|
+
selectionOrigin,
|
|
97
|
+
selectionMode,
|
|
98
|
+
upstreamSourceOrigin,
|
|
99
|
+
effectiveSource,
|
|
100
|
+
requestedRef,
|
|
101
|
+
resolvedRef: saved.saved_resolved_ref,
|
|
102
|
+
desiredCommit: saved.saved_commit,
|
|
103
|
+
resolutionKind: COMMIT_RE.test(saved.saved_requested_ref)
|
|
104
|
+
? "raw-commit"
|
|
105
|
+
: "tag",
|
|
106
|
+
saved,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const resolution = await resolveRef(effectiveSource, requestedRef);
|
|
110
|
+
// `Resolution` (src/upstream.ts) is { kind, ref, commit } — the
|
|
111
|
+
// resolved ref field is named `ref`, not `resolvedRef`.
|
|
112
|
+
return {
|
|
113
|
+
selectionOrigin,
|
|
114
|
+
selectionMode,
|
|
115
|
+
upstreamSourceOrigin,
|
|
116
|
+
effectiveSource,
|
|
117
|
+
requestedRef,
|
|
118
|
+
resolvedRef: resolution.ref,
|
|
119
|
+
desiredCommit: resolution.commit,
|
|
120
|
+
resolutionKind: resolution.kind,
|
|
121
|
+
saved,
|
|
122
|
+
};
|
|
123
|
+
}
|