@guiho/runx 0.2.7 → 0.4.1
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/CHANGELOG.md +39 -0
- package/DOCS.md +127 -128
- package/README.md +56 -75
- package/devops/build-binaries.ts +44 -62
- package/devops/devops.xdocs.md +8 -5
- package/devops/install.ps1 +182 -152
- package/devops/install.sh +197 -262
- package/devops/installers.spec.ts +31 -0
- package/devops/verify-release-assets.ts +17 -0
- package/docs/docs.xdocs.md +3 -1
- package/docs/plans/plans.xdocs.md +7 -0
- package/docs/plans/rfc-0034-cli-compliance-migration.md +586 -0
- package/docs/plans/upgrade-reliability-implementation.md +95 -0
- package/docs/reviews/implementation/implementation.xdocs.md +2 -0
- package/docs/reviews/implementation/rfc-0034-cli-compliance-migration-review.md +69 -0
- package/docs/reviews/plans/plans.xdocs.md +6 -0
- package/docs/reviews/plans/rfc-0034-cli-compliance-migration-review.md +80 -0
- package/docs/reviews/plans/upgrade-reliability-implementation-review.md +65 -0
- package/docs/superpowers/specs/2026-07-15-upgrade-reliability-design.md +662 -0
- package/docs/superpowers/specs/specs.xdocs.md +24 -0
- package/docs/superpowers/superpowers.xdocs.md +21 -0
- package/docs/todo/rfc-0034-cli-compliance-migration-implementation.md +77 -0
- package/docs/todo/rfc-0034-cli-compliance-migration.md +152 -0
- package/docs/todo/todo.xdocs.md +6 -2
- package/docs/validation/rfc-0034-cli-compliance-migration.md +83 -0
- package/docs/validation/upgrade-reliability.md +124 -0
- package/docs/validation/validation.xdocs.md +5 -0
- package/library/agents.d.ts +29 -4
- package/library/agents.d.ts.map +1 -1
- package/library/agents.js +143 -41
- package/library/cli.d.ts.map +1 -1
- package/library/cli.js +311 -331
- package/library/configuration.d.ts +57 -0
- package/library/configuration.d.ts.map +1 -0
- package/library/configuration.js +111 -0
- package/library/embedded-resources.d.ts +6 -1
- package/library/embedded-resources.d.ts.map +1 -1
- package/library/embedded-resources.js +10 -4
- package/library/executor.d.ts +5 -1
- package/library/executor.d.ts.map +1 -1
- package/library/executor.js +10 -10
- package/library/help.d.ts +8 -4
- package/library/help.d.ts.map +1 -1
- package/library/help.js +70 -46
- package/library/init.d.ts +8 -27
- package/library/init.d.ts.map +1 -1
- package/library/init.js +37 -159
- package/library/manifest.d.ts +4 -43
- package/library/manifest.d.ts.map +1 -1
- package/library/manifest.js +4 -125
- package/library/path-utils.d.ts +13 -0
- package/library/path-utils.d.ts.map +1 -0
- package/library/path-utils.js +82 -0
- package/library/recovery.d.ts +7 -0
- package/library/recovery.d.ts.map +1 -0
- package/library/recovery.js +23 -0
- package/library/release-catalog.d.ts +32 -0
- package/library/release-catalog.d.ts.map +1 -0
- package/library/release-catalog.js +124 -0
- package/library/self-management.d.ts +24 -4
- package/library/self-management.d.ts.map +1 -1
- package/library/self-management.js +279 -99
- package/library/storage.d.ts +13 -0
- package/library/storage.d.ts.map +1 -0
- package/library/storage.js +38 -0
- package/library/types.d.ts +11 -16
- package/library/types.d.ts.map +1 -1
- package/library/types.js +3 -0
- package/library/update-cache.d.ts +21 -0
- package/library/update-cache.d.ts.map +1 -0
- package/library/update-cache.js +68 -0
- package/library/upgrade-reporting.d.ts +11 -0
- package/library/upgrade-reporting.d.ts.map +1 -0
- package/library/upgrade-reporting.js +67 -0
- package/library/upgrade-types.d.ts +72 -0
- package/library/upgrade-types.d.ts.map +1 -0
- package/library/upgrade-types.js +3 -0
- package/package.json +6 -3
- package/scripts/runx-bin.mjs +49 -0
- package/scripts/runx-bin.spec.ts +62 -0
- package/scripts/scripts.xdocs.md +3 -3
- package/skills/guiho-s-runx/SKILL.md +64 -59
- package/skills/guiho-s-runx/guiho-s-runx.xdocs.md +7 -4
- package/skills/skills.xdocs.md +1 -1
- package/docs/todo/implement-runx-alpha.md +0 -36
- package/scripts/runx-bin.ts +0 -24
package/devops/install.sh
CHANGED
|
@@ -1,324 +1,259 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
|
|
3
|
-
# Install GUIHO RunX as a native CLI binary from GitHub Releases.
|
|
4
|
-
#
|
|
5
|
-
set -Eeuo pipefail
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -eu
|
|
6
3
|
|
|
7
4
|
REPO="${RUNX_REPO:-CGuiho/runx}"
|
|
8
5
|
VERSION="${RUNX_VERSION:-latest}"
|
|
9
6
|
INSTALL_DIR="${RUNX_INSTALL_DIR:-$HOME/.local/bin}"
|
|
7
|
+
DOWNLOAD_BASE_URL="${RUNX_DOWNLOAD_BASE_URL:-}"
|
|
10
8
|
ARCH_OVERRIDE=""
|
|
11
9
|
VARIANT_OVERRIDE=""
|
|
12
10
|
OS=""
|
|
13
11
|
ARCH=""
|
|
14
|
-
|
|
12
|
+
TARGET_VERSION=""
|
|
15
13
|
TMP=""
|
|
16
14
|
|
|
17
|
-
cleanup() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
trap cleanup EXIT
|
|
15
|
+
cleanup() { [ -z "$TMP" ] || rm -rf -- "$TMP"; }
|
|
16
|
+
trap cleanup EXIT HUP INT TERM
|
|
17
|
+
fail() { printf 'error: %s\n' "$*" >&2; exit 1; }
|
|
18
|
+
require_command() { command -v "$1" >/dev/null 2>&1 || fail "required command not found: $1"; }
|
|
19
|
+
require_value() { [ -n "${2:-}" ] || fail "$1 requires a value"; }
|
|
24
20
|
|
|
25
21
|
usage() {
|
|
26
22
|
cat <<EOF
|
|
27
|
-
Install GUIHO RunX as a native CLI binary from GitHub Releases.
|
|
23
|
+
Install GUIHO RunX as a verified native CLI binary from GitHub Releases.
|
|
28
24
|
|
|
29
|
-
Usage: install.sh [
|
|
25
|
+
Usage: install.sh [--version VERSION] [--arch x64|arm64] [--variant baseline|default|modern] [--install-dir DIR]
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
-v, --version VERSION Version to install (default: latest).
|
|
33
|
-
Examples: latest, 0.1.1, @guiho/runx@0.1.1
|
|
34
|
-
--arch ARCH Force architecture: x64 | arm64 (default: auto-detect)
|
|
35
|
-
--variant VARIANT Force x64 variant: baseline | default | modern (default: baseline)
|
|
36
|
-
--install-dir DIR Install directory (default: \$HOME/.local/bin)
|
|
37
|
-
-h, --help Show this help
|
|
38
|
-
|
|
39
|
-
Environment variables:
|
|
40
|
-
RUNX_VERSION Same as --version
|
|
41
|
-
RUNX_REPO GitHub repo (default: CGuiho/runx)
|
|
42
|
-
RUNX_INSTALL_DIR Same as --install-dir
|
|
27
|
+
VERSION may be an exact stable or prerelease version. The default is latest stable.
|
|
43
28
|
EOF
|
|
44
29
|
}
|
|
45
30
|
|
|
46
|
-
fail() {
|
|
47
|
-
printf 'error: %s\n' "$*" >&2
|
|
48
|
-
exit 1
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
require_command() {
|
|
52
|
-
command -v "$1" >/dev/null 2>&1 || fail "required command not found: $1"
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
require_value() {
|
|
56
|
-
local option="$1"
|
|
57
|
-
local value="${2:-}"
|
|
58
|
-
|
|
59
|
-
[[ -n "$value" ]] || fail "$option requires a value"
|
|
60
|
-
}
|
|
61
|
-
|
|
62
31
|
parse_args() {
|
|
63
|
-
while [
|
|
32
|
+
while [ "$#" -gt 0 ]; do
|
|
64
33
|
case "$1" in
|
|
65
|
-
-v
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
--
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
require_value "$1" "${2:-}"
|
|
76
|
-
ARCH_OVERRIDE="$2"
|
|
77
|
-
shift 2
|
|
78
|
-
;;
|
|
79
|
-
--arch=*)
|
|
80
|
-
ARCH_OVERRIDE="${1#*=}"
|
|
81
|
-
shift
|
|
82
|
-
;;
|
|
83
|
-
--variant)
|
|
84
|
-
require_value "$1" "${2:-}"
|
|
85
|
-
VARIANT_OVERRIDE="$2"
|
|
86
|
-
shift 2
|
|
87
|
-
;;
|
|
88
|
-
--variant=*)
|
|
89
|
-
VARIANT_OVERRIDE="${1#*=}"
|
|
90
|
-
shift
|
|
91
|
-
;;
|
|
92
|
-
--install-dir)
|
|
93
|
-
require_value "$1" "${2:-}"
|
|
94
|
-
INSTALL_DIR="$2"
|
|
95
|
-
shift 2
|
|
96
|
-
;;
|
|
97
|
-
--install-dir=*)
|
|
98
|
-
INSTALL_DIR="${1#*=}"
|
|
99
|
-
shift
|
|
100
|
-
;;
|
|
101
|
-
-h | --help)
|
|
102
|
-
usage
|
|
103
|
-
exit 0
|
|
104
|
-
;;
|
|
105
|
-
*)
|
|
106
|
-
fail "unknown flag: $1. Run with --help for usage."
|
|
107
|
-
;;
|
|
34
|
+
-v|--version) require_value "$1" "${2:-}"; VERSION="$2"; shift 2 ;;
|
|
35
|
+
--version=*) VERSION=${1#*=}; shift ;;
|
|
36
|
+
--arch) require_value "$1" "${2:-}"; ARCH_OVERRIDE="$2"; shift 2 ;;
|
|
37
|
+
--arch=*) ARCH_OVERRIDE=${1#*=}; shift ;;
|
|
38
|
+
--variant) require_value "$1" "${2:-}"; VARIANT_OVERRIDE="$2"; shift 2 ;;
|
|
39
|
+
--variant=*) VARIANT_OVERRIDE=${1#*=}; shift ;;
|
|
40
|
+
--install-dir) require_value "$1" "${2:-}"; INSTALL_DIR="$2"; shift 2 ;;
|
|
41
|
+
--install-dir=*) INSTALL_DIR=${1#*=}; shift ;;
|
|
42
|
+
-h|--help) usage; exit 0 ;;
|
|
43
|
+
*) fail "unknown flag: $1" ;;
|
|
108
44
|
esac
|
|
109
45
|
done
|
|
110
46
|
}
|
|
111
47
|
|
|
112
|
-
detect_os() {
|
|
113
|
-
case "$(uname -s)" in
|
|
114
|
-
Linux) printf 'linux\n' ;;
|
|
115
|
-
Darwin) printf 'macos\n' ;;
|
|
116
|
-
*) fail "unsupported OS: $(uname -s)" ;;
|
|
117
|
-
esac
|
|
118
|
-
}
|
|
119
|
-
|
|
48
|
+
detect_os() { case "$(uname -s)" in Linux) printf 'linux\n' ;; Darwin) printf 'darwin\n' ;; *) fail "unsupported OS: $(uname -s)" ;; esac; }
|
|
120
49
|
detect_arch() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
x64 | arm64) printf '%s\n' "$ARCH_OVERRIDE" ;;
|
|
124
|
-
*) fail "invalid --arch '$ARCH_OVERRIDE'. Must be x64 or arm64." ;;
|
|
125
|
-
esac
|
|
126
|
-
return
|
|
127
|
-
fi
|
|
128
|
-
|
|
129
|
-
case "$(uname -m)" in
|
|
130
|
-
x86_64 | amd64) printf 'x64\n' ;;
|
|
131
|
-
arm64 | aarch64) printf 'arm64\n' ;;
|
|
132
|
-
*) fail "unsupported architecture: $(uname -m)" ;;
|
|
133
|
-
esac
|
|
50
|
+
detected=${ARCH_OVERRIDE:-$(uname -m)}
|
|
51
|
+
case "$detected" in x64|x86_64|amd64) printf 'x64\n' ;; arm64|aarch64) printf 'arm64\n' ;; *) fail "unsupported architecture: $detected" ;; esac
|
|
134
52
|
}
|
|
135
53
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
;;
|
|
155
|
-
*)
|
|
156
|
-
fail "invalid --variant '$variant'. Must be baseline, default, or modern."
|
|
54
|
+
normalize_version() {
|
|
55
|
+
value=$1
|
|
56
|
+
value=${value#@guiho/runx@}
|
|
57
|
+
value=${value#v}
|
|
58
|
+
printf '%s\n' "$value" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$' || fail "invalid RunX version: $1"
|
|
59
|
+
case "$value" in
|
|
60
|
+
*-*)
|
|
61
|
+
prerelease=${value#*-}
|
|
62
|
+
prerelease=${prerelease%%+*}
|
|
63
|
+
old_ifs=$IFS
|
|
64
|
+
IFS=.
|
|
65
|
+
set -- $prerelease
|
|
66
|
+
IFS=$old_ifs
|
|
67
|
+
for identifier do
|
|
68
|
+
if printf '%s\n' "$identifier" | grep -Eq '^[0-9]+$'; then
|
|
69
|
+
case "$identifier" in 0|[1-9]*) ;; 0*) fail "invalid RunX version: $value" ;; esac
|
|
70
|
+
fi
|
|
71
|
+
done
|
|
157
72
|
;;
|
|
158
73
|
esac
|
|
74
|
+
printf '%s\n' "$value"
|
|
159
75
|
}
|
|
160
76
|
|
|
161
|
-
|
|
162
|
-
|
|
77
|
+
resolve_target_version() {
|
|
78
|
+
if [ "$VERSION" != latest ]; then normalize_version "$VERSION"; return; fi
|
|
79
|
+
printf 'Resolving latest stable RunX release...\n' >&2
|
|
80
|
+
effective=$(curl --fail --location --silent --show-error --proto '=https' --tlsv1.2 --output /dev/null --write-out '%{url_effective}' "https://github.com/${REPO}/releases/latest")
|
|
81
|
+
tag=${effective##*/}
|
|
82
|
+
tag=$(printf '%s' "$tag" | sed 's/%40/@/g; s/%2[Ff]/\//g')
|
|
83
|
+
normalize_version "$tag"
|
|
84
|
+
}
|
|
163
85
|
|
|
164
|
-
|
|
165
|
-
|
|
86
|
+
build_candidates() {
|
|
87
|
+
variant=${VARIANT_OVERRIDE:-baseline}
|
|
88
|
+
if [ "$ARCH" = arm64 ]; then
|
|
89
|
+
[ -z "$VARIANT_OVERRIDE" ] || fail '--variant is only valid for x64 installs'
|
|
90
|
+
printf 'runx-%s-arm64\n' "$OS"
|
|
166
91
|
return
|
|
167
92
|
fi
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
*) tag="@guiho/runx@${VERSION}" ;;
|
|
93
|
+
case "$variant" in
|
|
94
|
+
baseline) printf 'runx-%s-x64-baseline\nrunx-%s-x64\nrunx-%s-x64-modern\n' "$OS" "$OS" "$OS" ;;
|
|
95
|
+
default) printf 'runx-%s-x64\nrunx-%s-x64-baseline\nrunx-%s-x64-modern\n' "$OS" "$OS" "$OS" ;;
|
|
96
|
+
modern) printf 'runx-%s-x64-modern\nrunx-%s-x64\nrunx-%s-x64-baseline\n' "$OS" "$OS" "$OS" ;;
|
|
97
|
+
*) fail "invalid variant: $variant" ;;
|
|
174
98
|
esac
|
|
175
|
-
|
|
176
|
-
local encoded_tag="${tag//@/%40}"
|
|
177
|
-
encoded_tag="${encoded_tag//\//%2F}"
|
|
178
|
-
printf 'https://github.com/%s/releases/download/%s/%s\n' "$REPO" "$encoded_tag" "$asset"
|
|
179
99
|
}
|
|
180
100
|
|
|
181
101
|
verify_native_binary() {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
magic2="$(LC_ALL=C head -c 2 "$path" 2>/dev/null || true)"
|
|
187
|
-
magic4="$(LC_ALL=C head -c 4 "$path" 2>/dev/null || true)"
|
|
188
|
-
|
|
189
|
-
case "$magic4" in
|
|
190
|
-
$'\177ELF' | $'\xcf\xfa\xed\xfe' | $'\xce\xfa\xed\xfe' | $'\xca\xfe\xba\xbe') return 0 ;;
|
|
191
|
-
'<!DO' | '<htm') return 1 ;;
|
|
192
|
-
esac
|
|
193
|
-
|
|
194
|
-
case "$magic2" in
|
|
195
|
-
MZ) return 0 ;;
|
|
196
|
-
'#!') return 1 ;;
|
|
197
|
-
esac
|
|
198
|
-
|
|
199
|
-
return 2
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
shell_profile_path() {
|
|
203
|
-
local shell_name="${SHELL##*/}"
|
|
204
|
-
|
|
205
|
-
case "$shell_name" in
|
|
206
|
-
fish) printf '%s/.config/fish/config.fish\n' "$HOME" ;;
|
|
207
|
-
zsh) printf '%s/.zshrc\n' "$HOME" ;;
|
|
208
|
-
bash)
|
|
209
|
-
if [[ "$OS" == "macos" && -f "$HOME/.bash_profile" ]]; then
|
|
210
|
-
printf '%s/.bash_profile\n' "$HOME"
|
|
211
|
-
else
|
|
212
|
-
printf '%s/.bashrc\n' "$HOME"
|
|
213
|
-
fi
|
|
214
|
-
;;
|
|
215
|
-
*) printf '%s/.profile\n' "$HOME" ;;
|
|
216
|
-
esac
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
path_contains_install_dir() {
|
|
220
|
-
case ":$PATH:" in
|
|
221
|
-
*:"$INSTALL_DIR":*) return 0 ;;
|
|
102
|
+
magic=$(od -An -tx1 -N4 "$1" 2>/dev/null | tr -d ' \n')
|
|
103
|
+
case "$OS:$magic" in
|
|
104
|
+
linux:7f454c46|darwin:cffaedfe|darwin:cefaedfe|darwin:cafebabe|darwin:feedfacf|darwin:feedface) return 0 ;;
|
|
222
105
|
*) return 1 ;;
|
|
223
106
|
esac
|
|
224
107
|
}
|
|
225
108
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if [
|
|
233
|
-
|
|
109
|
+
verify_installed_version() {
|
|
110
|
+
verify_output=$(mktemp "${TMPDIR:-/tmp}/runx-version.XXXXXX") || return 1
|
|
111
|
+
"$1" --version >"$verify_output" 2>&1 &
|
|
112
|
+
verify_pid=$!
|
|
113
|
+
verify_waited=0
|
|
114
|
+
while kill -0 "$verify_pid" 2>/dev/null; do
|
|
115
|
+
if [ "$verify_waited" -ge 10 ]; then
|
|
116
|
+
kill "$verify_pid" 2>/dev/null || true
|
|
117
|
+
wait "$verify_pid" 2>/dev/null || true
|
|
118
|
+
rm -f -- "$verify_output"
|
|
119
|
+
printf 'error: installed RunX version check timed out after 10 seconds\n' >&2
|
|
120
|
+
return 1
|
|
234
121
|
fi
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
122
|
+
sleep 1
|
|
123
|
+
verify_waited=$((verify_waited + 1))
|
|
124
|
+
done
|
|
125
|
+
if ! wait "$verify_pid"; then
|
|
126
|
+
cat "$verify_output" >&2
|
|
127
|
+
rm -f -- "$verify_output"
|
|
128
|
+
return 1
|
|
241
129
|
fi
|
|
242
|
-
|
|
243
|
-
|
|
130
|
+
actual=$(cat "$verify_output")
|
|
131
|
+
rm -f -- "$verify_output"
|
|
132
|
+
[ "$actual" = "$TARGET_VERSION" ] || { printf 'error: installed RunX reported %s; expected %s\n' "${actual:-<empty>}" "$TARGET_VERSION" >&2; return 1; }
|
|
244
133
|
}
|
|
245
134
|
|
|
246
135
|
ensure_path() {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
136
|
+
PATH="$INSTALL_DIR:$PATH"; export PATH
|
|
137
|
+
profile="$HOME/.profile"
|
|
138
|
+
case "${SHELL##*/}" in zsh) profile="$HOME/.zshrc" ;; bash) profile="$HOME/.bashrc" ;; fish) profile="$HOME/.config/fish/config.fish" ;; esac
|
|
139
|
+
mkdir -p -- "$(dirname "$profile")"
|
|
140
|
+
if ! grep -Fq "$INSTALL_DIR" "$profile" 2>/dev/null; then
|
|
141
|
+
if [ "${SHELL##*/}" = fish ]; then printf '\n# Added by runx installer\nfish_add_path %s\n' "$INSTALL_DIR" >>"$profile"
|
|
142
|
+
else printf '\n# Added by runx installer\nexport PATH=%s:$PATH\n' "$INSTALL_DIR" >>"$profile"; fi
|
|
251
143
|
fi
|
|
252
|
-
|
|
253
|
-
local profile
|
|
254
|
-
profile="$(shell_profile_path)"
|
|
255
|
-
append_path_to_profile "$profile"
|
|
256
|
-
|
|
257
|
-
printf 'runx: ensured %s is added to PATH in %s\n' "$INSTALL_DIR" "$profile"
|
|
258
|
-
printf 'runx: restart your terminal, or run this for the current shell:\n'
|
|
259
|
-
printf ' export PATH=%q:\$PATH\n' "$INSTALL_DIR"
|
|
260
144
|
}
|
|
261
145
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
146
|
+
download_asset() {
|
|
147
|
+
url=$1
|
|
148
|
+
output=$2
|
|
149
|
+
set +e
|
|
150
|
+
if [ -n "$DOWNLOAD_BASE_URL" ]; then
|
|
151
|
+
http_code=$(curl --location --progress-bar --show-error --output "$output" --write-out '%{http_code}' "$url")
|
|
152
|
+
else
|
|
153
|
+
http_code=$(curl --location --progress-bar --show-error --proto '=https' --tlsv1.2 --output "$output" --write-out '%{http_code}' "$url")
|
|
154
|
+
fi
|
|
155
|
+
curl_exit=$?
|
|
156
|
+
set -e
|
|
157
|
+
[ "$curl_exit" -eq 0 ] || fail "download failed for $url (curl exit $curl_exit)"
|
|
158
|
+
case "$http_code" in
|
|
159
|
+
404) return 44 ;;
|
|
160
|
+
2??) return 0 ;;
|
|
161
|
+
*) fail "download failed for $url (HTTP $http_code)" ;;
|
|
162
|
+
esac
|
|
274
163
|
}
|
|
275
164
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
165
|
+
install_transactional() {
|
|
166
|
+
source_path=$1
|
|
167
|
+
destination=$2
|
|
168
|
+
backup="${destination}.old.$$.$(date +%s)"
|
|
169
|
+
original_moved=false
|
|
170
|
+
if [ -e "$destination" ]; then mv -- "$destination" "$backup" || fail "could not back up existing RunX at $destination"; original_moved=true; fi
|
|
171
|
+
if ! install -m 0755 "$source_path" "$destination"; then
|
|
172
|
+
[ "$original_moved" = false ] || mv -- "$backup" "$destination" || fail "installation and automatic rollback both failed; backup remains at $backup"
|
|
173
|
+
fail 'installation failed; the previous executable was restored'
|
|
174
|
+
fi
|
|
175
|
+
printf 'Verifying...\n'
|
|
176
|
+
if ! verify_installed_version "$destination"; then
|
|
177
|
+
rm -f -- "$destination"
|
|
178
|
+
[ "$original_moved" = false ] || mv -- "$backup" "$destination" || fail "verification and automatic rollback both failed; backup remains at $backup"
|
|
179
|
+
fail 'installation verification failed; the previous executable was restored'
|
|
180
|
+
fi
|
|
181
|
+
[ "$original_moved" = false ] || rm -f -- "$backup"
|
|
182
|
+
}
|
|
289
183
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
184
|
+
install_agent_assets() {
|
|
185
|
+
tag_base=${DOWNLOAD_BASE_URL:-"https://github.com/${REPO}/releases/download"}
|
|
186
|
+
skill_url="${tag_base%/}/${encoded_tag}/guiho-s-runx"
|
|
187
|
+
prompt_url="${tag_base%/}/${encoded_tag}/guiho-i-runx"
|
|
188
|
+
printf 'Downloading skill asset: %s\n' "$skill_url"
|
|
189
|
+
download_asset "$skill_url" "$TMP/guiho-s-runx" || fail 'could not download guiho-s-runx'
|
|
190
|
+
printf 'Downloading instruction asset: %s\n' "$prompt_url"
|
|
191
|
+
download_asset "$prompt_url" "$TMP/guiho-i-runx" || fail 'could not download guiho-i-runx'
|
|
192
|
+
for skill_root in "$HOME/.agents/skills/guiho-s-runx" "$HOME/.claude/skills/guiho-s-runx"; do
|
|
193
|
+
mkdir -p -- "$skill_root"
|
|
194
|
+
install -m 0644 "$TMP/guiho-s-runx" "$skill_root/SKILL.md"
|
|
195
|
+
printf 'Installed skill: %s\n' "$skill_root/SKILL.md"
|
|
196
|
+
done
|
|
197
|
+
targets=""
|
|
198
|
+
[ ! -f AGENTS.md ] || targets="AGENTS.md"
|
|
199
|
+
[ ! -f CLAUDE.md ] || targets="${targets}${targets:+ }CLAUDE.md"
|
|
200
|
+
[ -n "$targets" ] || targets="AGENTS.md"
|
|
201
|
+
for instruction_file in $targets; do
|
|
202
|
+
printf 'Reconciling instruction file: %s\n' "$instruction_file"
|
|
203
|
+
clean_file="$TMP/instruction-clean"
|
|
204
|
+
if [ -f "$instruction_file" ]; then
|
|
205
|
+
awk '
|
|
206
|
+
$0 == "<!-- BEGIN RUNX — DO NOT EDIT THIS SECTION -->" { managed=1; next }
|
|
207
|
+
$0 == "<!-- END RUNX -->" { managed=0; next }
|
|
208
|
+
!managed { print }
|
|
209
|
+
' "$instruction_file" >"$clean_file"
|
|
210
|
+
else
|
|
211
|
+
: >"$clean_file"
|
|
297
212
|
fi
|
|
298
|
-
|
|
299
|
-
|
|
213
|
+
{
|
|
214
|
+
cat "$clean_file"
|
|
215
|
+
[ ! -s "$clean_file" ] || printf '\n'
|
|
216
|
+
printf '<!-- BEGIN RUNX — DO NOT EDIT THIS SECTION -->\n'
|
|
217
|
+
cat "$TMP/guiho-i-runx"
|
|
218
|
+
printf '\n<!-- END RUNX -->\n'
|
|
219
|
+
} >"$instruction_file"
|
|
300
220
|
done
|
|
301
|
-
|
|
302
|
-
fail "no compatible runx binary found. Check available assets at: https://github.com/${REPO}/releases"
|
|
303
221
|
}
|
|
304
222
|
|
|
305
223
|
main() {
|
|
306
224
|
parse_args "$@"
|
|
307
|
-
require_command
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
225
|
+
for command in awk cat curl date dirname grep head install mktemp mv od rm sed tr uname; do require_command "$command"; done
|
|
226
|
+
OS=$(detect_os); ARCH=$(detect_arch); TARGET_VERSION=$(resolve_target_version)
|
|
227
|
+
TMP=$(mktemp -d "${TMPDIR:-/tmp}/runx-install.XXXXXX")
|
|
228
|
+
mkdir -p -- "$INSTALL_DIR"
|
|
229
|
+
destination="$INSTALL_DIR/runx"
|
|
230
|
+
encoded_tag="%40guiho%2Frunx%40${TARGET_VERSION}"
|
|
231
|
+
downloaded=""
|
|
232
|
+
first_asset=$(build_candidates | head -n 1)
|
|
233
|
+
source_url="${DOWNLOAD_BASE_URL:-https://github.com/${REPO}/releases/download}/${encoded_tag}/${first_asset}"
|
|
234
|
+
printf 'Initiating GUIHO CLI Upgrade / Installation Sequence...\n'
|
|
235
|
+
printf 'Target Version: v%s\nArchitecture: %s\nVariant: %s\nSource URL: %s\n' "$TARGET_VERSION" "$ARCH" "${VARIANT_OVERRIDE:-baseline}" "$source_url"
|
|
236
|
+
build_candidates | while IFS= read -r asset; do printf '%s\n' "$asset"; done >"$TMP/candidates"
|
|
237
|
+
while IFS= read -r asset; do
|
|
238
|
+
if [ -n "$DOWNLOAD_BASE_URL" ]; then url="${DOWNLOAD_BASE_URL%/}/${encoded_tag}/${asset}"; else url="https://github.com/${REPO}/releases/download/${encoded_tag}/${asset}"; fi
|
|
239
|
+
candidate="$TMP/$asset"
|
|
240
|
+
printf 'Downloading %s\n' "$url"
|
|
241
|
+
if download_asset "$url" "$candidate"; then :; else
|
|
242
|
+
status=$?
|
|
243
|
+
if [ "$status" -eq 44 ]; then printf ' %s is not available; trying the next compatible candidate.\n' "$asset"; continue; fi
|
|
244
|
+
exit "$status"
|
|
245
|
+
fi
|
|
246
|
+
verify_native_binary "$candidate" || fail "downloaded asset $asset is not a native $OS executable"
|
|
247
|
+
downloaded=$candidate
|
|
248
|
+
break
|
|
249
|
+
done <"$TMP/candidates"
|
|
250
|
+
[ -n "$downloaded" ] || fail "no compatible RunX $TARGET_VERSION binary found at https://github.com/${REPO}/releases"
|
|
251
|
+
printf 'Replacing...\n'
|
|
252
|
+
install_transactional "$downloaded" "$destination"
|
|
253
|
+
install_agent_assets
|
|
254
|
+
[ "${RUNX_SKIP_PATH_UPDATE:-0}" = 1 ] || ensure_path
|
|
255
|
+
printf 'Final verification: %s --version\n' "$destination"
|
|
256
|
+
printf 'Installed and verified RunX %s at %s\n' "$TARGET_VERSION" "$destination"
|
|
322
257
|
}
|
|
323
258
|
|
|
324
259
|
main "$@"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'bun:test'
|
|
6
|
+
|
|
7
|
+
describe('RunX direct installers', () => {
|
|
8
|
+
test('PowerShell installer exposes the complete RFC sequence', async () => {
|
|
9
|
+
const script = await Bun.file(new URL('./install.ps1', import.meta.url)).text()
|
|
10
|
+
expect(script).toContain('Initiating GUIHO CLI Upgrade / Installation Sequence...')
|
|
11
|
+
expect(script).toContain('guiho-s-runx')
|
|
12
|
+
expect(script).toContain('guiho-i-runx')
|
|
13
|
+
expect(script).toContain('.agents\\skills\\guiho-s-runx')
|
|
14
|
+
expect(script).toContain('.claude\\skills\\guiho-s-runx')
|
|
15
|
+
expect(script).toContain('BEGIN RUNX — DO NOT EDIT THIS SECTION')
|
|
16
|
+
expect(script).toContain('Test-NativeBinary')
|
|
17
|
+
expect(script).toContain('Install-Transactional')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('POSIX installer selects Darwin assets and has no Bun dependency', async () => {
|
|
21
|
+
const script = await Bun.file(new URL('./install.sh', import.meta.url)).text()
|
|
22
|
+
expect(script).toContain("Darwin) printf 'darwin")
|
|
23
|
+
expect(script).toContain('--progress-bar')
|
|
24
|
+
expect(script).toContain('guiho-s-runx')
|
|
25
|
+
expect(script).toContain('guiho-i-runx')
|
|
26
|
+
expect(script).toContain('.agents/skills/guiho-s-runx')
|
|
27
|
+
expect(script).toContain('.claude/skills/guiho-s-runx')
|
|
28
|
+
expect(script).toContain('BEGIN RUNX — DO NOT EDIT THIS SECTION')
|
|
29
|
+
expect(script).not.toContain(' bun ')
|
|
30
|
+
})
|
|
31
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { expectedReleaseAssetNames } from './build-binaries.js'
|
|
6
|
+
import { joinPath } from '../source/path-utils.js'
|
|
7
|
+
|
|
8
|
+
const root = Bun.fileURLToPath(new URL('..', import.meta.url))
|
|
9
|
+
const bin = joinPath(root, 'bin')
|
|
10
|
+
const observed = [...new Bun.Glob('*').scanSync({ cwd: bin, onlyFiles: true })].sort()
|
|
11
|
+
const expected = [...expectedReleaseAssetNames].sort()
|
|
12
|
+
|
|
13
|
+
if (JSON.stringify(observed) !== JSON.stringify(expected)) {
|
|
14
|
+
throw new Error(`Expected exactly ${expected.length} release assets.\nExpected: ${expected.join(', ')}\nObserved: ${observed.join(', ')}`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
process.stdout.write(`${JSON.stringify({ count: observed.length, assets: observed }, null, 2)}\n`)
|
package/docs/docs.xdocs.md
CHANGED
|
@@ -8,6 +8,7 @@ children:
|
|
|
8
8
|
- runx-decisions
|
|
9
9
|
- runx-plans
|
|
10
10
|
- runx-reviews
|
|
11
|
+
- runx-superpowers
|
|
11
12
|
- runx-todo
|
|
12
13
|
- runx-validation
|
|
13
14
|
files: {}
|
|
@@ -22,4 +23,5 @@ flags: []
|
|
|
22
23
|
status: stable
|
|
23
24
|
---
|
|
24
25
|
|
|
25
|
-
The documentation tree records the approved
|
|
26
|
+
The documentation tree records the approved product direction, executable
|
|
27
|
+
design specifications, and verification evidence.
|
|
@@ -9,14 +9,18 @@ files:
|
|
|
9
9
|
interactive-init-manifest.md: Sequences the SemVer manifest, public group, scripts directory, and interactive initializer delivery.
|
|
10
10
|
mirror-automatic-push.md: Enables automatic Mirror release pushes with a synchronized protected-main safety gate.
|
|
11
11
|
npm-trusted-publishing-release.md: Sequences workflow implementation, protected delivery, Mirror patching, and public trusted-publishing verification.
|
|
12
|
+
rfc-0034-cli-compliance-migration.md: Executes the breaking full RFC 0034 migration across runtime, configuration, help, agents, upgrades, distribution, release assets, documentation, and validation.
|
|
12
13
|
windows-self-upgrade.md: Sequences synchronous Windows replacement, rollback coverage, validation, issue closure, and patch delivery.
|
|
14
|
+
upgrade-reliability-implementation.md: Sequences release discovery, streamed progress, transactional replacement, recovery, installers, and validation.
|
|
13
15
|
documents:
|
|
14
16
|
alpha-implementation.md: Plan used for the initial RunX implementation.
|
|
15
17
|
citty-cli-migration.md: Active plan for replacing handwritten CLI parsing and routing with Citty and delivering its patch release.
|
|
16
18
|
interactive-init-manifest.md: Approved implementation plan for the RunX interactive init manifest feature.
|
|
17
19
|
mirror-automatic-push.md: Approved plan for configuring, validating, and merging Mirror push=true without applying another release.
|
|
18
20
|
npm-trusted-publishing-release.md: Approved executable plan for the RunX 0.2.1 trusted-publishing release trial.
|
|
21
|
+
rfc-0034-cli-compliance-migration.md: Approved step-by-step plan for making RunX fully compliant with the GUIHO CLI engineer contract.
|
|
19
22
|
windows-self-upgrade.md: Approved executable plan for fixing Windows native self-upgrade and delivering its patch.
|
|
23
|
+
upgrade-reliability-implementation.md: Approved executable plan for GitHub issues 12 and 13.
|
|
20
24
|
tags:
|
|
21
25
|
- plans
|
|
22
26
|
keywords:
|
|
@@ -26,6 +30,9 @@ keywords:
|
|
|
26
30
|
- runx init
|
|
27
31
|
- scripts directory
|
|
28
32
|
- mirror push
|
|
33
|
+
- RFC 0034
|
|
34
|
+
- agent namespace
|
|
35
|
+
- fourteen release assets
|
|
29
36
|
- windows self-upgrade
|
|
30
37
|
flags: []
|
|
31
38
|
status: stable
|