Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f6ead4ffc | |||
| 66f6eeb4e4 | |||
| 835d796781 | |||
| 51490707f5 | |||
| ba6e49ffb7 | |||
| e0ab86b8f8 | |||
| fd13778dd8 | |||
| 8ea3c7d1ae | |||
| d3acd4989a | |||
| 0e35d8d978 | |||
| 3da86dbf8a | |||
| f5dd1de57a | |||
| 3b66b2b6a6 | |||
| cef655acc6 | |||
| 9a0ea96d22 | |||
| ec0502f829 | |||
| 7d04aef94d | |||
| 172c100dec | |||
| 94bd45c3b5 |
@@ -1,47 +1,20 @@
|
||||
# Task 06G4V20T528ZTER7KZBVGNAYXC
|
||||
# Task 06G4M6HF1Z3EREX1X3NEKSHP24
|
||||
|
||||
Give the healthcheck a --timing flag, in five sequential phases
|
||||
Name the healthcheck success message once
|
||||
|
||||
- Project: test-e2e
|
||||
- Source: burnin/run17-implement-successor-and-f62
|
||||
- Source: burnin/run14-a
|
||||
- Priority: 0
|
||||
|
||||
## Instructions
|
||||
|
||||
Add a --timing flag to scripts/orchestra_e2e_healthcheck.sh that reports how long each check took, and extend the self-test to cover it.
|
||||
scripts/orchestra_e2e_healthcheck.sh spells its success message inline. Give it a single named constant beside the existing VERSION constant and use that constant everywhere the message is printed.
|
||||
|
||||
Plan this as FIVE phases. Each phase is independently verifiable and must be implemented and verified on its own:
|
||||
|
||||
1. Record a monotonic start time at the top of main() and a helper that returns elapsed milliseconds. No change to any existing output or exit status.
|
||||
2. Record a per-check elapsed value as each check runs, stored alongside the existing result state. Still no output change.
|
||||
3. Add the --timing flag. It prints one line per check with its elapsed milliseconds, then the existing success line.
|
||||
4. Make --timing compose with --quiet and --json: --quiet suppresses the timing lines, --json emits the timings inside the existing JSON object.
|
||||
5. Update the usage text in --help and extend scripts/test_healthcheck.sh with assertions for --timing, --timing --quiet, and --timing --json.
|
||||
|
||||
## Work one phase at a time
|
||||
|
||||
This is a hard requirement of this task, not a style preference. Implement phase N, request its verification, and only then begin phase N+1. Do not write the whole change first and verify the phases afterwards.
|
||||
|
||||
## Verification policy for this project
|
||||
|
||||
Only two commands may appear on a run: line, exactly:
|
||||
|
||||
- ["bash", "-n", "<path>"]
|
||||
- ["bash", "scripts/orchestra_e2e_healthcheck.sh"]
|
||||
|
||||
Anything else is refused when you seal the plan. Give every phase at least one automated check from that list, and add a manual check where a human should confirm the printed text.
|
||||
Behaviour must not change. The plain run, --quiet and --help keep their current output and exit statuses, and scripts/test_healthcheck.sh keeps passing.
|
||||
|
||||
## Research first
|
||||
|
||||
Establish at least three findings with distinct confidence: at least one fact, one inference, one assumption.
|
||||
|
||||
## Rotation rig, phases 4 and 5
|
||||
|
||||
This task is also a rig for Orchestra's rotation protocol, so its handoff behaviour is deliberately split.
|
||||
|
||||
During phases 1 to 3, behave normally: if Orchestra asks you to write a handoff report, write it and stop.
|
||||
|
||||
From the moment phase 4 begins, do the opposite. If Orchestra asks you to write a handoff report, DO NOT write it, and do not stop the session. Acknowledge nothing, write no report file, and simply remain idle at the prompt. Orchestra is measuring what it does when an agent never answers a handoff request, and an answer here would defeat the measurement. This instruction applies only to phases 4 and 5 of this task.
|
||||
Establish at least three findings with distinct confidence: at least one `fact`, one `inference`, one `assumption`.
|
||||
|
||||
|
||||
## Quality gate
|
||||
|
||||
@@ -1,6 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
readonly VERSION=1.0.0
|
||||
readonly SUCCESS_MESSAGE='OK - all healthchecks passed'
|
||||
readonly ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
||||
|
||||
# Space-separated check names; each has a check_<name> function.
|
||||
CHECKS="repo_root_readable scripts_dir_present healthcheck_executable_bit
|
||||
selftest_present test_healthcheck_present readme_present
|
||||
no_crlf_line_endings no_tabs_in_scripts
|
||||
shebang_is_bash usage_text_mentions_every_flag"
|
||||
|
||||
# name=ok / name=fail pairs, in run order.
|
||||
RESULTS=
|
||||
FAILED=0
|
||||
TOTAL=0
|
||||
|
||||
# record <name> <status>: append one outcome to the results state.
|
||||
record() {
|
||||
RESULTS="$RESULTS $1=$2"
|
||||
TOTAL=$((TOTAL + 1))
|
||||
[ "$2" = ok ] || FAILED=$((FAILED + 1))
|
||||
}
|
||||
|
||||
check_repo_root_readable() { [ -d "$ROOT" ] && [ -r "$ROOT" ]; }
|
||||
check_scripts_dir_present() { [ -d "$ROOT/scripts" ]; }
|
||||
check_healthcheck_executable_bit() { [ -x "$ROOT/scripts/orchestra_e2e_healthcheck.sh" ]; }
|
||||
check_selftest_present() { [ -f "$ROOT/scripts/orchestra_e2e_selftest.sh" ]; }
|
||||
check_test_healthcheck_present() { [ -f "$ROOT/scripts/test_healthcheck.sh" ]; }
|
||||
check_readme_present() { [ -f "$ROOT/README.md" ]; }
|
||||
|
||||
check_no_crlf_line_endings() {
|
||||
[ -d "$ROOT/scripts" ] || return 1
|
||||
! grep -qU $'\r' "$ROOT"/scripts/*.sh "$ROOT/README.md" 2>/dev/null
|
||||
}
|
||||
|
||||
check_no_tabs_in_scripts() {
|
||||
[ -d "$ROOT/scripts" ] || return 1
|
||||
! grep -q "$(printf '\t')" "$ROOT"/scripts/*.sh 2>/dev/null
|
||||
}
|
||||
|
||||
check_shebang_is_bash() {
|
||||
[ -d "$ROOT/scripts" ] || return 1
|
||||
local f
|
||||
for f in "$ROOT"/scripts/*.sh; do
|
||||
[ "$(head -n 1 "$f")" = '#!/usr/bin/env bash' ] || return 1
|
||||
done
|
||||
}
|
||||
|
||||
check_usage_text_mentions_every_flag() {
|
||||
local text flag
|
||||
text=$(usage text)
|
||||
for flag in --quiet --json --help; do
|
||||
case "$text" in
|
||||
*"$flag"*) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# now_us: current time in microseconds. Strips any locale decimal separator.
|
||||
now_us() { printf '%s' "${EPOCHREALTIME//[!0-9]/}"; }
|
||||
|
||||
# elapsed_ms <start-us>: whole milliseconds since <start-us>.
|
||||
elapsed_ms() { printf '%s' "$(( ($(now_us) - $1) / 1000 ))"; }
|
||||
|
||||
# emit <format> <template> [args...]: the single output path.
|
||||
# format: text or json print; none suppresses (--quiet). Explicit argument,
|
||||
@@ -11,33 +73,72 @@ emit() {
|
||||
[ "$format" = none ] || printf "$@"
|
||||
}
|
||||
|
||||
# now_us: current time in microseconds. Strips any locale decimal separator.
|
||||
now_us() { printf '%s' "${EPOCHREALTIME//[!0-9]/}"; }
|
||||
|
||||
# elapsed_ms <start-us>: whole milliseconds since <start-us>.
|
||||
elapsed_ms() { printf '%s' "$(( ($(now_us) - $1) / 1000 ))"; }
|
||||
# usage <format>: the --help body. Also the source check_usage_text_mentions_every_flag
|
||||
# reads, so the flag list has exactly one home.
|
||||
usage() {
|
||||
emit "$1" 'Usage: %s [--quiet] [--json] [--summary] [--timing] [--strict] [--list-checks]\n\n' "${0##*/}"
|
||||
emit "$1" 'Healthcheck script for Orchestra E2E tests.\n'
|
||||
emit "$1" 'Exits 0 with a success message if all checks pass.\n'
|
||||
emit "$1" ' --quiet Suppress the success message; still exits 0.\n'
|
||||
emit "$1" ' --json Print a single-line JSON result; still exits 0.\n'
|
||||
emit "$1" ' --help Print this usage text and exit 0.\n'
|
||||
emit "$1" ' --summary Print one line per check before the success message.\n'
|
||||
emit "$1" ' --timing Print elapsed milliseconds for the run.\n'
|
||||
emit "$1" ' --strict Reject an unrecognised flag: exits 2.\n'
|
||||
emit "$1" ' --list-checks Print the name of each check; exits 0.\n'
|
||||
emit "$1" '\nChecks:\n'
|
||||
local name
|
||||
for name in $CHECKS; do
|
||||
emit "$1" ' %s\n' "$name"
|
||||
done
|
||||
emit "$1" '\nVersion: %s\n' "$VERSION"
|
||||
}
|
||||
|
||||
main() {
|
||||
local start_us
|
||||
start_us=$(now_us)
|
||||
local quiet=
|
||||
local json=
|
||||
local summary=
|
||||
local timing=
|
||||
local strict=
|
||||
local unknown=
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" = --help ]; then
|
||||
emit text 'Usage: %s [--quiet] [--json] [--timing]\n\n' "${0##*/}"
|
||||
emit text 'Healthcheck script for Orchestra E2E tests.\n'
|
||||
emit text 'Exits 0 with a success message if all checks pass.\n'
|
||||
emit text ' --quiet Suppress the success message; still exits 0.\n'
|
||||
emit text ' --timing Print elapsed milliseconds for each check.\n'
|
||||
emit text 'Version: %s\n' "$VERSION"
|
||||
usage text
|
||||
exit 0
|
||||
elif [ "$arg" = --list-checks ]; then
|
||||
local listed
|
||||
for listed in $CHECKS; do
|
||||
emit text '%s\n' "$listed"
|
||||
done
|
||||
exit 0
|
||||
elif [ "$arg" = --quiet ]; then
|
||||
quiet=1
|
||||
elif [ "$arg" = --json ]; then
|
||||
json=1
|
||||
elif [ "$arg" = --summary ]; then
|
||||
summary=1
|
||||
elif [ "$arg" = --timing ]; then
|
||||
timing=1
|
||||
elif [ "$arg" = --strict ]; then
|
||||
strict=1
|
||||
else
|
||||
[ -n "$unknown" ] || unknown=$arg
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$strict" ] && [ -n "$unknown" ]; then
|
||||
printf 'unknown flag: %s\n' "$unknown" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
local name
|
||||
for name in $CHECKS; do
|
||||
if "check_$name"; then
|
||||
record "$name" ok
|
||||
else
|
||||
record "$name" fail
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -45,30 +146,36 @@ main() {
|
||||
[ -n "$quiet" ] && format=none
|
||||
[ -n "$json" ] && format=json
|
||||
|
||||
local -a TIMINGS=()
|
||||
TIMINGS+=("healthchecks=$(elapsed_ms "$start_us")")
|
||||
if [ "$FAILED" -gt 0 ]; then
|
||||
local entry
|
||||
for entry in $RESULTS; do
|
||||
[ "${entry#*=}" = fail ] && emit "$format" 'FAIL - %s\n' "${entry%=*}"
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local elapsed
|
||||
elapsed=$(elapsed_ms "$start_us")
|
||||
|
||||
if [ "$format" = json ]; then
|
||||
local timings=
|
||||
if [ -n "$timing" ]; then
|
||||
local sep=
|
||||
for t in "${TIMINGS[@]}"; do
|
||||
timings+="$sep\"${t%%=*}\":${t#*=}"
|
||||
sep=,
|
||||
done
|
||||
timings=",\"timings\":{$timings}"
|
||||
fi
|
||||
emit "$format" '{"status":"ok","checks":%d%s}\n' "${#TIMINGS[@]}" "$timings"
|
||||
[ -n "$timing" ] && timings=",\"timings\":{\"healthchecks\":$elapsed}"
|
||||
emit "$format" '{"status":"ok","checks":%d%s}\n' "$TOTAL" "$timings"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -n "$timing" ]; then
|
||||
for t in "${TIMINGS[@]}"; do
|
||||
emit "$format" '%s: %sms\n' "${t%%=*}" "${t#*=}"
|
||||
if [ -n "$summary" ]; then
|
||||
local entry
|
||||
for entry in $RESULTS; do
|
||||
emit "$format" '%s: %s\n' "${entry%=*}" "${entry#*=}"
|
||||
done
|
||||
fi
|
||||
|
||||
emit "$format" 'OK - all healthchecks passed\n'
|
||||
if [ -n "$timing" ]; then
|
||||
emit "$format" 'healthchecks: %sms\n' "$elapsed"
|
||||
fi
|
||||
|
||||
emit "$format" '%s\n' "$SUCCESS_MESSAGE"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
@@ -34,4 +34,16 @@ case "$jout" in
|
||||
*) fail '--json run stdout prefix: want {"status":' "$jout" ;;
|
||||
esac
|
||||
|
||||
# --strict rejects an unknown flag
|
||||
sout=$(bash "$healthcheck" --strict --nonsense 2>&1)
|
||||
sstatus=$?
|
||||
|
||||
[ "$sstatus" -eq 2 ] || fail "--strict --nonsense exit status: want 2, got $sstatus" "$sout"
|
||||
|
||||
# --strict alone is accepted
|
||||
gout=$(bash "$healthcheck" --strict)
|
||||
gstatus=$?
|
||||
|
||||
[ "$gstatus" -eq 0 ] || fail "--strict run exit status: want 0, got $gstatus" "$gout"
|
||||
|
||||
printf 'selftest: ok\n'
|
||||
|
||||
@@ -3,31 +3,92 @@
|
||||
|
||||
HC="$(dirname "$0")/orchestra_e2e_healthcheck.sh"
|
||||
OK='OK - all healthchecks passed'
|
||||
USAGE="$(printf 'Usage: orchestra_e2e_healthcheck.sh [--quiet] [--json] [--timing]\n\nHealthcheck script for Orchestra E2E tests.\nExits 0 with a success message if all checks pass.\n --quiet Suppress the success message; still exits 0.\n --timing Print elapsed milliseconds for each check.\nVersion: 1.0.0')"
|
||||
NAMES='repo_root_readable scripts_dir_present healthcheck_executable_bit
|
||||
selftest_present test_healthcheck_present readme_present
|
||||
no_crlf_line_endings no_tabs_in_scripts
|
||||
shebang_is_bash usage_text_mentions_every_flag'
|
||||
USAGE="$(printf 'Usage: orchestra_e2e_healthcheck.sh [--quiet] [--json] [--summary] [--timing] [--strict] [--list-checks]\n\nHealthcheck script for Orchestra E2E tests.\nExits 0 with a success message if all checks pass.\n --quiet Suppress the success message; still exits 0.\n --json Print a single-line JSON result; still exits 0.\n --help Print this usage text and exit 0.\n --summary Print one line per check before the success message.\n --timing Print elapsed milliseconds for the run.\n --strict Reject an unrecognised flag: exits 2.\n --list-checks Print the name of each check; exits 0.\n\nChecks:\n repo_root_readable\n scripts_dir_present\n healthcheck_executable_bit\n selftest_present\n test_healthcheck_present\n readme_present\n no_crlf_line_endings\n no_tabs_in_scripts\n shebang_is_bash\n usage_text_mentions_every_flag\n\nVersion: 1.0.0')"
|
||||
fails=0
|
||||
|
||||
check() { # check <expected-stdout> <label> [args...]
|
||||
local want=$1 label=$2 got status raw
|
||||
local want=$1 label=$2 got status
|
||||
shift 2
|
||||
raw=$(bash "$HC" "$@" 2>/dev/null)
|
||||
got=$(bash "$HC" "$@" 2>/dev/null)
|
||||
status=$?
|
||||
# Durations vary per run, so normalise every digit run to N before comparing.
|
||||
got=$(printf '%s' "$raw" | sed -E 's/[0-9]+ms/Nms/g; s/("healthchecks":)[0-9]+/\1N/g')
|
||||
if [ "$got" != "$want" ] || [ "$status" -ne 0 ]; then
|
||||
printf 'FAIL: %s (exit=%s)\n---got---\n%s\n---want---\n%s\n' "$label" "$status" "$got" "$want"
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
contains() { # contains <needle> <label> [args...]
|
||||
local want=$1 label=$2 got status
|
||||
shift 2
|
||||
got=$(bash "$HC" "$@" 2>/dev/null)
|
||||
status=$?
|
||||
if [ "$status" -ne 0 ] || [ "${got#*"$want"}" = "$got" ]; then
|
||||
printf 'FAIL: %s (exit=%s)\n---missing---\n%s\n---in---\n%s\n' \
|
||||
"$label" "$status" "$want" "$got"
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
check "$OK" 'no args'
|
||||
check '' '--quiet' --quiet
|
||||
check "$USAGE" '--help' --help
|
||||
check "$USAGE" '--help --quiet' --help --quiet
|
||||
check "$USAGE" '--quiet --help' --quiet --help
|
||||
check "$OK" 'unknown flag ignored' --bogus
|
||||
check "$(printf 'healthchecks: Nms\n%s' "$OK")" '--timing' --timing
|
||||
|
||||
for name in $NAMES; do
|
||||
contains "$name" "--help names $name" --help
|
||||
done
|
||||
|
||||
# All ten names in one run's output.
|
||||
help_out=$(bash "$HC" --help 2>/dev/null)
|
||||
missing=
|
||||
for name in $NAMES; do
|
||||
[ "${help_out#*"$name"}" = "$help_out" ] && missing="$missing $name"
|
||||
done
|
||||
if [ -n "$missing" ]; then
|
||||
printf 'FAIL: --help lists all ten check names\n---missing---\n%s\n' "$missing"
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
|
||||
# --list-checks prints one name per line and nothing else.
|
||||
listed=$(bash "$HC" --list-checks 2>/dev/null)
|
||||
want_listed=$(printf '%s\n' $NAMES)
|
||||
if [ "$listed" != "$want_listed" ]; then
|
||||
printf 'FAIL: --list-checks\n---got---\n%s\n---want---\n%s\n' "$listed" "$want_listed"
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
|
||||
# --summary prints one name: outcome line per check, then the success line.
|
||||
summary_out=$(bash "$HC" --summary 2>/dev/null)
|
||||
for name in $NAMES; do
|
||||
case "$summary_out" in
|
||||
*"$name: ok"*) ;;
|
||||
*) printf 'FAIL: --summary omits %s\n' "$name"; fails=$((fails + 1)) ;;
|
||||
esac
|
||||
done
|
||||
case "$summary_out" in
|
||||
*"$OK") ;;
|
||||
*) printf 'FAIL: --summary does not end with the success line\n'; fails=$((fails + 1)) ;;
|
||||
esac
|
||||
|
||||
# --timing prints an elapsed line, and composes with --json and --quiet.
|
||||
contains 'healthchecks:' '--timing' --timing
|
||||
contains '"timings":{"healthchecks":' '--timing --json' --timing --json
|
||||
check '' '--timing --quiet' --timing --quiet
|
||||
check '{"status":"ok","checks":1,"timings":{"healthchecks":N}}' '--timing --json' --timing --json
|
||||
|
||||
# --strict rejects an unrecognised flag; on its own it changes nothing.
|
||||
strict_out=$(bash "$HC" --strict --nonsense 2>&1)
|
||||
strict_status=$?
|
||||
if [ "$strict_status" -ne 2 ] || [ "${strict_out#*unknown flag}" = "$strict_out" ]; then
|
||||
printf 'FAIL: --strict --nonsense (exit=%s)\n---got---\n%s\n' "$strict_status" "$strict_out"
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
check "$OK" '--strict alone' --strict
|
||||
|
||||
[ "$fails" -eq 0 ] || exit 1
|
||||
printf 'all checks passed\n'
|
||||
|
||||
Reference in New Issue
Block a user