Skip to content

Commit 31b3ab2

Browse files
committed
Track which failure mode each assistant hits
A bare pass count does not say whether a failure was the token-cache write, a TTY demand, a rejected flag, or something unrelated. classify() now returns a category alongside the status, the summary prints counts per cause, and --save records it, so the numbers can be compared across runs and branches. Categories: connection (denied token-cache write), tty, flag, trust, profile, timeout, other.
1 parent 56914af commit 31b3ab2

1 file changed

Lines changed: 43 additions & 24 deletions

File tree

test-assistants.sh

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -203,32 +203,36 @@ want() {
203203
return 1
204204
}
205205

206-
# A hard failure anywhere outweighs a success line: assistants often retry and
207-
# print both, and we care whether the run hit a wall at all.
206+
# Returns STATUS|CATEGORY|detail. The category is the trackable part: it says which
207+
# known failure mode was hit, so counts can be compared across runs and branches.
208+
# A hard failure anywhere outweighs a success line, since assistants often retry
209+
# and print both, and we care whether the run hit a wall at all.
208210
classify() {
209211
local log="$1" rc="$2"
210-
grep -qiE "unknown flag|unknown command" "$log" 2>/dev/null && { echo "FAIL|bad flag or unsupported command"; return; }
211-
grep -qi "connection issue" "$log" 2>/dev/null && { echo "FAIL|connection issue (denied token-cache write?)"; return; }
212-
grep -qiE "no profiles found|no active profile" "$log" 2>/dev/null && { echo "FAIL|no usable Foundry profile"; return; }
213-
grep -qE "APP ID|App ID" "$log" 2>/dev/null && { echo "PASS|listed apps"; return; }
214-
{ [ "$rc" -eq 124 ] || [ "$rc" -eq 137 ]; } && { echo "TIMEOUT|exceeded ${TIMEOUT}s"; return; }
215-
[ "$rc" -ne 0 ] && { echo "FAIL|exited $rc without reaching the tenant"; return; }
216-
echo "UNKNOWN|finished but printed no app list"
212+
grep -qiE "unknown flag|unknown command" "$log" 2>/dev/null && { echo "FAIL|flag|rejected a CLI flag"; return; }
213+
grep -qi "connection issue" "$log" 2>/dev/null && { echo "FAIL|connection|connection issue (denied token-cache write?)"; return; }
214+
grep -qiE "no TTY available|could not open a new TTY|device not configured" "$log" 2>/dev/null && { echo "FAIL|tty|CLI demanded a TTY"; return; }
215+
grep -qiE "not inside a trusted directory|skip-git-repo-check" "$log" 2>/dev/null && { echo "FAIL|trust|refused to run in this directory"; return; }
216+
grep -qiE "no profiles found|no active profile" "$log" 2>/dev/null && { echo "FAIL|profile|no usable Foundry profile"; return; }
217+
grep -qE "APP ID|App ID" "$log" 2>/dev/null && { echo "PASS|ok|listed apps"; return; }
218+
{ [ "$rc" -eq 124 ] || [ "$rc" -eq 137 ]; } && { echo "TIMEOUT|timeout|exceeded ${TIMEOUT}s"; return; }
219+
[ "$rc" -ne 0 ] && { echo "FAIL|other|exited $rc without reaching the tenant"; return; }
220+
echo "UNKNOWN|other|finished but printed no app list"
217221
}
218222

219223
head2 "Running"
220224
info "tenant check: foundry apps list · timeout ${TIMEOUT}s · logs in ${LOG_DIR/#$HOME/\~}"
221225
printf '\n'
222226

223-
RESULTS=(); FAILURES=0; TESTED=0
227+
RESULTS=(); CATEGORIES=(); FAILURES=0; TESTED=0
224228

225229
for entry in "${ASSISTANTS[@]}"; do
226230
IFS='|' read -r name bin source argv <<< "$entry"
227231
want "$name" || continue
228232

229233
if ! command -v "$bin" >/dev/null 2>&1; then
230234
printf ' %s%-16s SKIP%s %s not installed\n' "$DIM" "$name" "$RESET" "$bin"
231-
RESULTS+=("$name|SKIP|not installed|0|none")
235+
RESULTS+=("$name|SKIP|skip|not installed|0|none")
232236
continue
233237
fi
234238

@@ -253,7 +257,7 @@ for entry in "${ASSISTANTS[@]}"; do
253257

254258
if [ "$source" = "~/.agents/skills" ]; then unlink_repo_skills; fi
255259

256-
IFS='|' read -r status detail <<< "$(classify "$log" "$rc")"
260+
IFS='|' read -r status category detail <<< "$(classify "$log" "$rc")"
257261
case "$status" in
258262
PASS) printf '\r %s%-16s%s %s%sPASS%s %-42s %s%ss%s\n' \
259263
"$BOLD" "$name" "$RESET" "$BOLD" "$GREEN" "$RESET" "$detail" "$DIM" "$elapsed" "$RESET" ;;
@@ -266,25 +270,40 @@ for entry in "${ASSISTANTS[@]}"; do
266270
esac
267271
info "source: $source · log: ${log/#$HOME/\~}"
268272

269-
RESULTS+=("$name|$status|$detail|$elapsed|$source")
273+
[ "$status" != "PASS" ] && CATEGORIES+=("$category")
274+
RESULTS+=("$name|$status|$category|$detail|$elapsed|$source")
270275
TESTED=$((TESTED+1))
271276
done
272277

273278
head2 "Summary"
274279
if [ "$TESTED" -eq 0 ]; then
275280
printf ' no assistants tested\n'
276281
elif [ "$FAILURES" -eq 0 ]; then
277-
printf ' %sall %s tested assistant(s) reached the tenant%s\n' "$GREEN" "$TESTED" "$RESET"
282+
printf ' %s%s of %s reached the tenant%s\n' "$GREEN" "$TESTED" "$TESTED" "$RESET"
278283
else
279-
printf ' %s%s of %s failed%s\n' "$RED" "$FAILURES" "$TESTED" "$RESET"
280-
# Only offer the token-cache explanation when a run actually hit that error.
281-
if printf '%s\n' "${RESULTS[@]}" | grep -q "connection issue"; then
282-
info 'A "connection issue" failure means the sandbox denied the CLI its'
283-
info 'token-cache write to ~/.config/foundry/ — see debugging-workflows.'
284+
printf ' %s%s of %s reached the tenant%s · %s%s failed%s\n' \
285+
"$GREEN" "$((TESTED-FAILURES))" "$TESTED" "$RESET" "$RED" "$FAILURES" "$RESET"
286+
printf '\n %sfailures by cause%s\n' "$BOLD" "$RESET"
287+
# Counts per known failure mode, worth tracking run to run.
288+
printf '%s\n' ${CATEGORIES[@]+"${CATEGORIES[@]}"} | sort | uniq -c | sort -rn | while read -r n cat; do
289+
case "$cat" in
290+
connection) label="connection issue — denied token-cache write" ; col=$RED ;;
291+
tty) label="TTY demanded by the CLI" ; col=$MAGENTA ;;
292+
flag) label="unsupported CLI flag" ; col=$YELLOW ;;
293+
trust) label="refused to run in the test directory" ; col=$YELLOW ;;
294+
profile) label="no usable Foundry profile" ; col=$YELLOW ;;
295+
timeout) label="timed out" ; col=$YELLOW ;;
296+
*) label="other" ; col=$DIM ;;
297+
esac
298+
printf ' %s%s×%s %s%s%s\n' "$BOLD" "$n" "$RESET" "$col" "$label" "$RESET"
299+
done
300+
printf '\n'
301+
if printf '%s\n' ${CATEGORIES[@]+"${CATEGORIES[@]}"} | grep -qx connection; then
302+
info 'A connection issue means the sandbox denied the CLI its token-cache'
303+
info 'write to ~/.config/foundry/ — see debugging-workflows.'
284304
[ "$EXPIRE_TOKEN" -eq 0 ] && info 'Re-run with --expire-token to force that path on every trial.'
285305
else
286-
info 'No connection-issue failures — read the logs above; the cause is'
287-
info 'something other than the token cache.'
306+
info 'No connection or TTY failures. Read the logs above.'
288307
fi
289308
fi
290309

@@ -294,10 +313,10 @@ if [ -n "$SAVE_FILE" ]; then
294313
"$TIMEOUT" "$ISOLATE" "$EXPIRE_TOKEN"
295314
first=1
296315
for r in "${RESULTS[@]}"; do
297-
IFS='|' read -r n s d e src <<< "$r"
316+
IFS='|' read -r n st cat d e src <<< "$r"
298317
[ $first -eq 0 ] && printf ',\n'; first=0
299-
printf ' {"assistant": "%s", "status": "%s", "detail": "%s", "seconds": %s, "source": "%s"}' \
300-
"$n" "$s" "$d" "$e" "$src"
318+
printf ' {"assistant": "%s", "status": "%s", "category": "%s", "detail": "%s", "seconds": %s, "source": "%s"}' \
319+
"$n" "$st" "$cat" "$d" "$e" "$src"
301320
done
302321
printf '\n ]\n}\n'
303322
} > "$SAVE_FILE"

0 commit comments

Comments
 (0)