Files
gstack/bin/gstack-launch-probe.sh
T
Garry Tanandcapy-ai[bot] 4b8c03bea9 v1.91.294.0 fix(doctor): cut Git Bash process starts so the doctor tests fit Windows CI (GSTA-138) (#3540)
* perf(doctor): cut Git Bash process starts in doctor, hook-check and launch probe (GSTA-138)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

The doctor's in-process config read reselected the state root after the
doctor set GSTACK_STATE_ROOT, so --check and --json printed 'selected by
GSTACK_STATE_ROOT' whatever selected the root. cfg now keeps _gstack_sr_var.
Adds the regression test, a CRLF/blank/200-byte launch-probe detail test,
and corrects the clamp comment.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: check the doctor cores row's test_backend by behavior, not the reader's spelling

test/owner-brief-contributor-banned.test.ts pinned the literal
'gstack-config" get test_backend' in bin/gstack-doctor-check.sh, which the
in-process cfg read removed (CI: quick-bun-default, free-suite 14). It now
runs gstack-doctor --check --require cores against a state root holding
test_backend: ubicloud and expects test_backend=ubicloud, with an empty
state root as the negative control (test_backend=local). The under-8-cores
wording pin stays.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: CHANGELOG [Unreleased] entry for the doctor's Windows process cuts

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: stamp v1.91.294.0 for #3540

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-28 13:05:02 +00:00

76 lines
3.1 KiB
Bash

# shellcheck shell=bash
# gstack-launch-probe.sh — sourced by setup and bin/gstack-doctor.
#
# Windows Smart App Control (and other application-control policies) blocks
# unsigned executables at launch, and Git Bash reports that as a plain
# "Permission denied" (#2595, #2124). `[ -x ]` cannot see it, so this runs
# each compiled binary's side-effect-free `--version` and classifies it:
#
# native launched and exited 0
# blocked could not launch: spawn error, permission denied (exit 126/127),
# or an application-control message in its output
# broken launched but exited non-zero or timed out: a build problem
# missing not built
#
# The exact Windows error text is unverified on a real SAC machine, so callers
# show the raw first output line ($_glp_detail) beside the classification.
# Bash 3.2 plus POSIX tools.
GSTACK_COMPILED_BINARIES="browse/dist/browse browse/dist/find-browse design/dist/design make-pdf/dist/pdf bin/gstack-global-discover"
# gstack_launch_probe PATH — sets _glp_state and _glp_detail.
gstack_launch_probe() {
local out rc
_glp_state=missing
_glp_detail=""
[ -e "$1" ] || return 0
if command -v timeout >/dev/null 2>&1; then
out=$(timeout 20 "$1" --version </dev/null 2>&1)
else
out=$("$1" --version </dev/null 2>&1)
fi
rc=$?
# The first non-blank line, CRs dropped, at most 200 bytes: one subshell, not
# a five-process pipeline (each process start is ~20 ms on Windows).
_glp_detail=$(set -f; IFS='
'; LC_ALL=C; for line in $out; do line=${line//$'\r'/}; case "$line" in *[![:space:]]*) printf '%s' "${line:0:200}"; break ;; esac; done)
case "$out" in
*[Aa]pplication\ [Cc]ontrol*|*"Smart App Control"*|*"blocked by group policy"*|*"has blocked this file"*)
_glp_state=blocked; return 0 ;;
esac
case "$rc" in
0) _glp_state=native ;;
126|127) _glp_state=blocked ;;
124) _glp_state=broken; _glp_detail="timed out after 20s${_glp_detail:+: $_glp_detail}" ;;
*) _glp_state=broken; _glp_detail="exit $rc${_glp_detail:+: $_glp_detail}" ;;
esac
}
# gstack_launch_probe_skills REL — the skills that stop working without it.
gstack_launch_probe_skills() {
case "$1" in
browse/dist/browse|browse/dist/find-browse) printf '%s' "/browse, /qa, /qa-only, /design-review, /canary, /benchmark, /pair-agent, /scrape, /make-pdf" ;;
design/dist/design) printf '%s' "/design-consultation, /design-shotgun, /design-html, /plan-design-review" ;;
make-pdf/dist/pdf) printf '%s' "/make-pdf" ;;
bin/gstack-global-discover) printf '%s' "/retro global" ;;
esac
}
# gstack_launch_probe_all ROOT EXE — probes every compiled binary under ROOT
# (EXE is ".exe" on Windows). Sets _glp_blocked and _glp_broken to
# newline-separated "rel<TAB>detail" rows, and _glp_missing to a list.
gstack_launch_probe_all() {
local rel
_glp_blocked="" _glp_broken="" _glp_missing=""
for rel in $GSTACK_COMPILED_BINARIES; do
gstack_launch_probe "$1/$rel$2"
case "$_glp_state" in
blocked) _glp_blocked="$_glp_blocked$rel $_glp_detail
" ;;
broken) _glp_broken="$_glp_broken$rel $_glp_detail
" ;;
missing) _glp_missing="${_glp_missing:+$_glp_missing, }$rel" ;;
esac
done
}