bytelyst-devops-tools/agent-queue/selftest.sh
saravanakumardb1 af1bc6904e feat(agent-queue): build/ship lifecycle with auto-QA verify gate + manual ship
Redesign the kanban runner stages from inbox->doing->done/failed to
inbox->building->review->testing->shipped (+ failed):

- worker: agent rc=0 lands in review/, then runs the configurable
  verify command (frontmatter verify: / AGENT_QUEUE_VERIFY) in cwd;
  pass -> testing/ (QA), fail -> failed/, none -> parks in review/
- new commands: ship (testing->shipped, manual gate), promote
  (advance one stage), reject (review/testing->failed); requeue now
  also pulls from review/testing
- status + dashboard.mjs render all six stages; RECENT panel labels
  shipped/testing/review/verify_failed/timeout/rejected
- README: new lifecycle diagram, verify: frontmatter, result= glossary,
  command table + folder layout
- selftest: assert no-verify->review, verify-pass->testing->ship->shipped,
  verify-fail->failed
- rename queue/doing->building, queue/done->review; add testing/ shipped/
2026-05-29 16:03:01 -07:00

107 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# selftest.sh — quick, dependency-light verification for agent-queue.
#
# Runs:
# 1. shellcheck (if installed) at --severity=error on the runner
# 2. bash -n syntax check on the runner + this script
# 3. node --check on the dashboard (if node installed)
# 4. a live init/add/run --once cycle against a throwaway queue using a
# no-op engine stub (no real agent CLI is ever invoked)
#
# It uses its own temp AGENT_QUEUE_ROOT so it never touches a real queue.
# Exit 0 = all good. Run it before every commit.
#
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
AQ="$HERE/agent-queue.sh"
pass() { printf ' \033[32m✓\033[0m %s\n' "$*"; }
info() { printf ' \033[36m•\033[0m %s\n' "$*"; }
fail() { printf ' \033[31m✗ %s\033[0m\n' "$*" >&2; exit 1; }
tmp="$(mktemp -d "${TMPDIR:-/tmp}/aq-selftest.XXXXXX")"
cleanup() { rm -rf "$tmp"; }
trap cleanup EXIT
echo "agent-queue self-test"
# 1. shellcheck (optional)
if command -v shellcheck >/dev/null 2>&1; then
shellcheck --severity=error --shell=bash "$AQ" "${BASH_SOURCE[0]}" && pass "shellcheck (errors): clean"
else
info "shellcheck not installed — skipping"
fi
# 2. syntax
bash -n "$AQ" && pass "bash -n agent-queue.sh"
bash -n "${BASH_SOURCE[0]}" && pass "bash -n selftest.sh"
# 3. dashboard syntax (optional)
if command -v node >/dev/null 2>&1; then
node --check "$HERE/dashboard.mjs" && pass "node --check dashboard.mjs"
else
info "node not installed — skipping dashboard check"
fi
# 4. live no-op cycle
export AGENT_QUEUE_ROOT="$tmp/queue"
stub="$tmp/noop-engine"
printf '#!/usr/bin/env bash\n# no-op engine stub: drain stdin, succeed\ncat >/dev/null 2>&1 || true\nexit 0\n' > "$stub"
chmod +x "$stub"
work="$tmp/work"; mkdir -p "$work"
task="$tmp/task.md"
printf '%s\n' '---' 'engine: devin' "cwd: $work" 'yolo: true' '---' '' '# self-test no-op task' > "$task"
"$AQ" init >/dev/null
DEVIN_BIN="$stub" "$AQ" add "$task" >/dev/null
DEVIN_BIN="$stub" "$AQ" run --once >/dev/null 2>&1
if ls "$AGENT_QUEUE_ROOT"/review/*.md >/dev/null 2>&1; then
pass "no-verify cycle → task parked in review/"
else
echo "--- queue state ---" >&2
ls -R "$AGENT_QUEUE_ROOT" >&2 || true
fail "no-op cycle did not complete (expected a file in review/)"
fi
# 5. verify-pass gate: rc=0 + passing verify → testing/, then manual ship → shipped/
task2="$tmp/task-verify.md"
printf '%s\n' '---' 'engine: devin' "cwd: $work" 'yolo: true' 'verify: true' '---' '' '# self-test verify-pass task' > "$task2"
DEVIN_BIN="$stub" "$AQ" add "$task2" >/dev/null
DEVIN_BIN="$stub" "$AQ" run --once >/dev/null 2>&1
if ls "$AGENT_QUEUE_ROOT"/testing/*.md >/dev/null 2>&1; then
pass "verify-pass cycle → task promoted to testing/"
else
echo "--- queue state ---" >&2
ls -R "$AGENT_QUEUE_ROOT" >&2 || true
fail "verify-pass cycle did not reach testing/ (expected a file in testing/)"
fi
shipjob="$(basename "$(ls -1t "$AGENT_QUEUE_ROOT"/testing/*.md | head -1)" .md)"
"$AQ" ship "$shipjob" >/dev/null 2>&1
if ls "$AGENT_QUEUE_ROOT"/shipped/*.md >/dev/null 2>&1; then
pass "manual ship → task landed in shipped/"
else
fail "ship did not move job to shipped/"
fi
# 6. verify-fail gate: rc=0 + failing verify → failed/
task3="$tmp/task-verifyfail.md"
printf '%s\n' '---' 'engine: devin' "cwd: $work" 'yolo: true' 'verify: false' '---' '' '# self-test verify-fail task' > "$task3"
DEVIN_BIN="$stub" "$AQ" add "$task3" >/dev/null
DEVIN_BIN="$stub" "$AQ" run --once >/dev/null 2>&1
if ls "$AGENT_QUEUE_ROOT"/failed/*verifyfail*.md >/dev/null 2>&1; then
pass "verify-fail cycle → task routed to failed/"
else
echo "--- queue state ---" >&2
ls -R "$AGENT_QUEUE_ROOT" >&2 || true
fail "verify-fail cycle did not route to failed/"
fi
# status must not error
"$AQ" status >/dev/null 2>&1 && pass "status runs clean"
echo "self-test PASS"