@1aboveio/skills 1.0.6 → 1.0.8
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/package.json +2 -2
- package/skills/app-dev/airflow/SKILL.md +1 -1
- package/skills/app-dev/android-foundation/SKILL.md +92 -34
- package/skills/app-dev/android-foundation/assets/android-ci-job.yml +13 -7
- package/skills/app-dev/android-foundation/references/ci.md +23 -13
- package/skills/app-dev/android-foundation/references/delivery-focus.md +29 -0
- package/skills/app-dev/android-foundation/references/diagnosis.md +136 -0
- package/skills/app-dev/android-foundation/references/gotchas.md +20 -11
- package/skills/app-dev/android-foundation/references/setup.md +15 -6
- package/skills/app-dev/android-foundation/scripts/device-run.sh +148 -42
- package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +322 -58
- package/skills/app-dev/app-debug/SKILL.md +1 -1
- package/skills/app-dev/better-auth/SKILL.md +1 -1
- package/skills/app-dev/data-catalog/SKILL.md +1 -1
- package/skills/app-dev/data-quality/SKILL.md +1 -1
- package/skills/app-dev/ios-foundation/SKILL.md +1 -1
- package/skills/app-dev/monorepo/SKILL.md +1 -1
- package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
- package/skills/app-dev/prisma-setup/SKILL.md +1 -1
- package/skills/app-dev/pyspark/SKILL.md +1 -1
- package/skills/app-dev/python-backend/SKILL.md +1 -1
- package/skills/app-dev/shadcn/SKILL.md +1 -1
- package/skills/app-dev/zod-v4/SKILL.md +1 -1
- package/skills/cicd/cloud-build/SKILL.md +1 -1
- package/skills/cicd/cloud-debug/SKILL.md +1 -1
- package/skills/cicd/cloud-deploy/SKILL.md +1 -1
- package/skills/cicd/docker/SKILL.md +1 -1
- package/skills/cicd/github-actions/SKILL.md +1 -1
- package/skills/cicd/github-flow/SKILL.md +1 -1
- package/skills/cicd/google-cloud/SKILL.md +1 -1
- package/skills/cicd/mergify/SKILL.md +1 -1
- package/skills/cicd/podman/SKILL.md +1 -1
- package/skills/content/article-review/SKILL.md +1 -1
- package/skills/content/article-to-image/SKILL.md +1 -1
- package/skills/content/flowchart-svg/SKILL.md +1 -1
- package/skills/content/image-gen/SKILL.md +1 -1
- package/skills/content/mermaid/SKILL.md +1 -1
- package/skills/content/wechat-article-writer/SKILL.md +1 -1
- package/skills/content/wechat-publisher/SKILL.md +1 -1
- package/skills/content/wechat-search/SKILL.md +1 -1
- package/skills/content/xai-search/SKILL.md +1 -1
- package/skills/core/distill-writing/SKILL.md +22 -4
- package/skills/core/distill-writing/references/extraction.md +19 -3
- package/skills/core/doc-to-md/SKILL.md +1 -1
- package/skills/core/editorial-review/SKILL.md +1 -1
- package/skills/core/house-style/SKILL.md +2 -1
- package/skills/core/house-style/references/persistence.md +93 -0
- package/skills/core/house-style/references/rules.md +15 -6
- package/skills/core/plain-language/SKILL.md +40 -4
- package/skills/core/polish-cn/SKILL.md +1 -1
- package/skills/core/reg-parser/SKILL.md +1 -1
- package/skills/core/terminology/SKILL.md +1 -1
- package/skills/core/write-doc/SKILL.md +14 -6
- package/skills/engineering/better-review/SKILL.md +1 -1
- package/skills/engineering/contributing/SKILL.md +1 -1
- package/skills/engineering/e2e-test/SKILL.md +1 -1
- package/skills/engineering/engineering-runtime/SKILL.md +1 -1
- package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
- package/skills/engineering/ensure-coverage/SKILL.md +1 -1
- package/skills/engineering/golden-path/SKILL.md +1 -1
- package/skills/engineering/harness-runtime/SKILL.md +1 -1
- package/skills/engineering/resolve-issues/SKILL.md +11 -20
- package/skills/engineering/resolve-issues/references/delivery-progress.md +63 -0
- package/skills/engineering/resolve-issues/references/expire.md +24 -11
- package/skills/engineering/resolve-issues/references/implementation.md +9 -1
- package/skills/engineering/resolve-issues/references/task-plan.md +7 -4
- package/skills/engineering/resolve-release/SKILL.md +1 -1
- package/skills/engineering/rush-issues/SKILL.md +5 -2
- package/skills/engineering/rush-release/SKILL.md +1 -1
- package/skills/engineering/test-quality/SKILL.md +1 -1
- package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
- package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
- package/skills/risk-compliance/contract-review/SKILL.md +1 -1
- package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
- package/skills/risk-compliance/fraud-analysis/SKILL.md +1 -1
- package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
- package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
- package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
# Optional environment:
|
|
17
17
|
# POSTGRES_IMAGE (postgres:17) DB_URL_VAR (SHARD_ADMIN_URL) DB_NAME_VAR (SHARD_DB_NAME)
|
|
18
18
|
# LOG_DIR (.cache/logs) BOUNDED_SECONDS (30) BOOT_ATTEMPTS (60) KILL_GRACE_SECONDS (10)
|
|
19
|
+
# JOURNEY_SECONDS (0 = no deadline; caller chooses a positive whole-journey limit)
|
|
20
|
+
#
|
|
21
|
+
# ADB_SERVER_SOCKET / ANDROID_ADB_SERVER_PORT are inherited unchanged. The caller
|
|
22
|
+
# selects a private ADB endpoint before entry; this script never stops that server.
|
|
23
|
+
# Journey children must stay in their process group (no daemonizing / setsid).
|
|
24
|
+
# Send TERM to this launcher and allow cleanup to finish, rather than killing it.
|
|
25
|
+
# A forced kill or host crash cannot clean up; keep the printed resource directory.
|
|
19
26
|
#
|
|
20
27
|
# Exports ANDROID_EMULATOR_SERIAL, $DB_URL_VAR and $DB_NAME_VAR to both commands.
|
|
21
28
|
# Prints `original_stage_exit=<n> cleanup_exit=<n>` last and exits with the
|
|
@@ -47,6 +54,26 @@ LOG_DIR="${LOG_DIR:-.cache/logs}"
|
|
|
47
54
|
BOUNDED_SECONDS="${BOUNDED_SECONDS:-30}"
|
|
48
55
|
BOOT_ATTEMPTS="${BOOT_ATTEMPTS:-60}"
|
|
49
56
|
KILL_GRACE_SECONDS="${KILL_GRACE_SECONDS:-10}"
|
|
57
|
+
JOURNEY_SECONDS="${JOURNEY_SECONDS:-0}"
|
|
58
|
+
|
|
59
|
+
# Reject invalid limits before creating any owned resources.
|
|
60
|
+
python3 -c 'import math, sys
|
|
61
|
+
for value in sys.argv[1:4]:
|
|
62
|
+
number = float(value)
|
|
63
|
+
if not math.isfinite(number) or number < 0: sys.exit("limits must be finite and non-negative")
|
|
64
|
+
if float(sys.argv[1]) == 0: sys.exit("BOUNDED_SECONDS must be positive")
|
|
65
|
+
if not sys.argv[4].isdigit() or int(sys.argv[4]) < 1: sys.exit("BOOT_ATTEMPTS must be a positive integer")' \
|
|
66
|
+
"$BOUNDED_SECONDS" "$KILL_GRACE_SECONDS" "$JOURNEY_SECONDS" "$BOOT_ATTEMPTS" || exit 2
|
|
67
|
+
for variable in "$DB_URL_VAR" "$DB_NAME_VAR"; do
|
|
68
|
+
if ! [[ "$variable" =~ ^[a-zA-Z_][a-zA-Z_0-9]*$ ]]; then
|
|
69
|
+
echo "invalid database environment variable: $variable" >&2
|
|
70
|
+
exit 2
|
|
71
|
+
fi
|
|
72
|
+
done
|
|
73
|
+
if test "$DB_URL_VAR" = "$DB_NAME_VAR"; then
|
|
74
|
+
echo "DB_URL_VAR and DB_NAME_VAR must differ" >&2
|
|
75
|
+
exit 2
|
|
76
|
+
fi
|
|
50
77
|
|
|
51
78
|
if ! [[ "$EMULATOR_PORT" =~ ^[0-9]+$ ]] || (( EMULATOR_PORT < 5554 || EMULATOR_PORT > 5584 || EMULATOR_PORT % 2 )); then
|
|
52
79
|
echo "EMULATOR_PORT must be an even port in 5554-5584: $EMULATOR_PORT" >&2
|
|
@@ -56,67 +83,139 @@ fi
|
|
|
56
83
|
mkdir -p "$LOG_DIR"
|
|
57
84
|
run_dir="$(mktemp -d "${TMPDIR:-/tmp}/android-device-run.XXXXXX")"
|
|
58
85
|
emulator_pid=""
|
|
86
|
+
active_pid=""
|
|
59
87
|
db_ready=""
|
|
88
|
+
container_started=""
|
|
89
|
+
launch_in_progress=0
|
|
90
|
+
pending_signal=0
|
|
91
|
+
handle_signal() {
|
|
92
|
+
pending_signal="$1"
|
|
93
|
+
# Do not abandon a spawned supervisor before its PID has been recorded.
|
|
94
|
+
if test "$launch_in_progress" -eq 0; then exit "$pending_signal"; fi
|
|
95
|
+
}
|
|
96
|
+
honor_pending_signal() {
|
|
97
|
+
if test "$pending_signal" -ne 0; then exit "$pending_signal"; fi
|
|
98
|
+
}
|
|
99
|
+
echo "Owned resource records: $run_dir" >&2
|
|
60
100
|
export ANDROID_EMULATOR_SERIAL="emulator-$EMULATOR_PORT"
|
|
61
101
|
|
|
62
|
-
|
|
63
|
-
#
|
|
64
|
-
# the
|
|
65
|
-
python3 -c 'import os, signal, subprocess, sys
|
|
66
|
-
limit = float
|
|
67
|
-
|
|
102
|
+
supervise() {
|
|
103
|
+
# Only called in a background subshell: exec makes $! the signal-aware owner.
|
|
104
|
+
# Keep the process group owned even if its original leader exits first.
|
|
105
|
+
exec python3 -c 'import os, signal, subprocess, sys, time
|
|
106
|
+
limit, grace = map(float, sys.argv[1:3])
|
|
107
|
+
mode = sys.argv[3]
|
|
108
|
+
cancelled = 0
|
|
109
|
+
def cancel(signum, frame):
|
|
110
|
+
global cancelled
|
|
111
|
+
cancelled = 128 + signum
|
|
112
|
+
signal.signal(signal.SIGTERM, cancel)
|
|
113
|
+
signal.signal(signal.SIGINT, cancel)
|
|
68
114
|
try:
|
|
69
|
-
|
|
70
|
-
except
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
sys.
|
|
115
|
+
child = subprocess.Popen(sys.argv[4:], start_new_session=True)
|
|
116
|
+
except FileNotFoundError as error:
|
|
117
|
+
print(error, file=sys.stderr)
|
|
118
|
+
sys.exit(127)
|
|
119
|
+
except OSError as error:
|
|
120
|
+
print(error, file=sys.stderr)
|
|
121
|
+
sys.exit(126)
|
|
122
|
+
def group_alive():
|
|
123
|
+
# Ignore unreapable orphan zombies. macOS can return EPERM, not ESRCH, for
|
|
124
|
+
# an empty group under a sandbox, so inspect membership before signalling.
|
|
125
|
+
listing = subprocess.check_output(["ps", "-A", "-o", "pgid=,stat="], text=True)
|
|
126
|
+
return any(int(parts[0]) == child.pid and not parts[1].startswith("Z")
|
|
127
|
+
for line in listing.splitlines() if len(parts := line.split()) == 2)
|
|
128
|
+
def send(sig):
|
|
129
|
+
try: os.killpg(child.pid, sig)
|
|
130
|
+
except ProcessLookupError: pass
|
|
131
|
+
except PermissionError:
|
|
132
|
+
if group_alive(): raise
|
|
133
|
+
end = time.monotonic() + limit if limit else float("inf")
|
|
134
|
+
timed_out = False
|
|
135
|
+
while child.poll() is None and not cancelled:
|
|
136
|
+
if time.monotonic() >= end:
|
|
137
|
+
timed_out = True
|
|
138
|
+
break
|
|
139
|
+
time.sleep(0.02)
|
|
140
|
+
forced = False
|
|
141
|
+
if timed_out:
|
|
142
|
+
send(signal.SIGKILL)
|
|
143
|
+
else:
|
|
144
|
+
send(signal.SIGTERM)
|
|
145
|
+
stop = time.monotonic() + grace
|
|
146
|
+
while group_alive() and time.monotonic() < stop:
|
|
147
|
+
child.poll()
|
|
148
|
+
time.sleep(0.02)
|
|
149
|
+
if group_alive():
|
|
150
|
+
forced = True
|
|
151
|
+
send(signal.SIGKILL)
|
|
152
|
+
status = child.wait()
|
|
153
|
+
status = 128 - status if status < 0 else status
|
|
154
|
+
if timed_out:
|
|
155
|
+
print("Command exceeded %s seconds: %s" % (sys.argv[1], " ".join(sys.argv[4:])), file=sys.stderr)
|
|
156
|
+
sys.exit(124)
|
|
157
|
+
if mode == "emulator" and forced: sys.exit(1)
|
|
158
|
+
sys.exit(cancelled or status or (1 if forced else 0))' "$1" "$KILL_GRACE_SECONDS" "${@:2}"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
managed() {
|
|
162
|
+
local limit="$1" status=0
|
|
163
|
+
shift
|
|
164
|
+
launch_in_progress=1
|
|
165
|
+
supervise "$limit" command "$@" <&0 &
|
|
166
|
+
active_pid=$!
|
|
167
|
+
launch_in_progress=0
|
|
168
|
+
honor_pending_signal
|
|
169
|
+
# Bash defers signal traps for foreground commands, but not for this wait.
|
|
170
|
+
wait "$active_pid" || status=$?
|
|
171
|
+
active_pid=""
|
|
172
|
+
return "$status"
|
|
75
173
|
}
|
|
76
174
|
|
|
175
|
+
bounded() { managed "$BOUNDED_SECONDS" "$@"; }
|
|
176
|
+
|
|
77
177
|
cleanup() {
|
|
78
178
|
original_status=$?
|
|
79
|
-
trap - EXIT
|
|
179
|
+
trap - EXIT
|
|
180
|
+
trap '' INT TERM
|
|
181
|
+
pending_signal=0
|
|
182
|
+
launch_in_progress=0
|
|
80
183
|
set +e
|
|
81
184
|
cleanup_status=0
|
|
185
|
+
if test -n "$active_pid"; then
|
|
186
|
+
kill -TERM "$active_pid" 2>/dev/null
|
|
187
|
+
wait "$active_pid" || :
|
|
188
|
+
active_pid=""
|
|
189
|
+
fi
|
|
82
190
|
if test -n "$db_ready"; then
|
|
83
191
|
bounded "${drop_cmd[@]}" || cleanup_status=1
|
|
84
192
|
fi
|
|
85
193
|
if test -n "$emulator_pid"; then
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
kill -0 "$emulator_pid" 2>/dev/null || break
|
|
91
|
-
sleep 1
|
|
92
|
-
done
|
|
93
|
-
if kill -0 "$emulator_pid" 2>/dev/null; then
|
|
94
|
-
cleanup_status=1
|
|
95
|
-
kill -KILL "$emulator_pid"
|
|
96
|
-
sleep 1
|
|
97
|
-
fi
|
|
98
|
-
if kill -0 "$emulator_pid" 2>/dev/null; then
|
|
99
|
-
cleanup_status=1
|
|
100
|
-
else
|
|
101
|
-
wait "$emulator_pid"
|
|
102
|
-
emulator_status=$?
|
|
103
|
-
# 0 = clean exit; 143 = ended by our TERM. A KILL was already counted above.
|
|
104
|
-
case "$emulator_status" in 0|143) ;; *) cleanup_status=1 ;; esac
|
|
105
|
-
fi
|
|
194
|
+
kill -TERM "$emulator_pid" 2>/dev/null
|
|
195
|
+
emulator_status=0
|
|
196
|
+
wait "$emulator_pid" || emulator_status=$?
|
|
197
|
+
case "$emulator_status" in 0|143) ;; *) cleanup_status=1 ;; esac
|
|
106
198
|
fi
|
|
107
199
|
if test -s "$run_dir/postgres.cid"; then
|
|
108
200
|
container_id="$(< "$run_dir/postgres.cid")"
|
|
109
201
|
bounded docker rm --force "$container_id" >/dev/null || cleanup_status=1
|
|
110
|
-
|
|
111
|
-
|
|
202
|
+
bounded docker ps -a --no-trunc --filter "id=$container_id" --format '{{.ID}}' \
|
|
203
|
+
> "$run_dir/remaining" || cleanup_status=1
|
|
204
|
+
test ! -s "$run_dir/remaining" || cleanup_status=1
|
|
205
|
+
elif test -n "$container_started"; then
|
|
206
|
+
echo "Container startup not acknowledged; ownership unknown, inspect $run_dir before recovery" >&2
|
|
207
|
+
cleanup_status=1
|
|
112
208
|
fi
|
|
113
|
-
printf 'original_stage_exit=%s cleanup_exit=%s\n' "$original_status" "$cleanup_status"
|
|
209
|
+
printf 'original_stage_exit=%s cleanup_exit=%s\n' "$original_status" "$cleanup_status" >&3
|
|
114
210
|
if test "$original_status" -ne 0; then exit "$original_status"; fi
|
|
115
211
|
exit "$cleanup_status"
|
|
116
212
|
}
|
|
213
|
+
# EXIT can run inside a redirected function (notably docker run >/dev/null).
|
|
214
|
+
# Keep the caller's output for the final status line, even on startup failure.
|
|
215
|
+
exec 3>&1
|
|
117
216
|
trap cleanup EXIT
|
|
118
|
-
trap '
|
|
119
|
-
trap '
|
|
217
|
+
trap 'handle_signal 130' INT
|
|
218
|
+
trap 'handle_signal 143' TERM
|
|
120
219
|
|
|
121
220
|
# Every port this run listens on or dials must be free before anything starts.
|
|
122
221
|
python3 -c 'import socket, sys
|
|
@@ -130,21 +229,28 @@ bounded adb start-server
|
|
|
130
229
|
|
|
131
230
|
# -memory 4096 overrides the AVD's hw.ramSize, so a reused 2 GB AVD cannot starve the
|
|
132
231
|
# guest kernel's vsock allocations and drop adb mid-journey (references/gotchas.md).
|
|
133
|
-
|
|
232
|
+
launch_in_progress=1
|
|
233
|
+
supervise 0 emulator "$ANDROID_HOME/emulator/emulator" -avd "$SETUP_AVD" -port "$EMULATOR_PORT" -memory 4096 \
|
|
134
234
|
-no-window -no-audio -no-snapshot -gpu swiftshader_indirect -accel on \
|
|
135
235
|
> "$LOG_DIR/emulator.log" 2>&1 &
|
|
136
236
|
emulator_pid=$!
|
|
237
|
+
launch_in_progress=0
|
|
238
|
+
honor_pending_signal
|
|
137
239
|
|
|
138
240
|
container_name="android-device-run-$(date +%s)-$$"
|
|
241
|
+
container_started=1
|
|
242
|
+
printf '%s\n' "$container_name" > "$run_dir/container-name"
|
|
139
243
|
bounded docker run --detach --name "$container_name" --cidfile "$run_dir/postgres.cid" \
|
|
140
244
|
--publish 127.0.0.1::5432 --env POSTGRES_USER=postgres \
|
|
141
245
|
--env POSTGRES_PASSWORD=postgres --env POSTGRES_DB=postgres "$POSTGRES_IMAGE" >/dev/null
|
|
142
|
-
|
|
246
|
+
bounded docker port "$container_name" 5432/tcp > "$run_dir/postgres.port"
|
|
247
|
+
db_port="$(head -1 "$run_dir/postgres.port" | awk -F: '{print $NF}')"
|
|
143
248
|
test -n "$db_port"
|
|
144
249
|
|
|
145
250
|
boot_state=""
|
|
146
251
|
for _ in $(seq 1 "$BOOT_ATTEMPTS"); do
|
|
147
|
-
if
|
|
252
|
+
if bounded adb -s "$ANDROID_EMULATOR_SERIAL" shell getprop sys.boot_completed > "$run_dir/boot" 2>/dev/null; then
|
|
253
|
+
boot_state="$(tr -d '\r' < "$run_dir/boot")"
|
|
148
254
|
if test "$boot_state" = 1; then break; fi
|
|
149
255
|
else
|
|
150
256
|
probe_status=$?
|
|
@@ -173,4 +279,4 @@ export "$DB_URL_VAR=postgresql://postgres:postgres@127.0.0.1:$db_port/postgres"
|
|
|
173
279
|
export "$DB_NAME_VAR=${DB_NAME_PREFIX}$(date +%s)_$$"
|
|
174
280
|
db_ready=1
|
|
175
281
|
|
|
176
|
-
"${journey_cmd[@]}"
|
|
282
|
+
managed "$JOURNEY_SECONDS" "${journey_cmd[@]}"
|