From 1e0a17bbc00cfad9dc4ea5380a897878d91140e5 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Fri, 29 May 2026 21:35:16 -0700 Subject: [PATCH] test(agent-queue): tracker adapter selftest cases (P1-S4) Adds (never weakens) 7 stub-driven cases (AQ_TRACKER_API_CMD stub, no live service): from-tracker create + label mapping + idempotent; to-tracker shipped echo (PATCH done + metrics comment, asserts NO prompt body sent) + idempotent; HTTP 500 non-fatal; AQ_TRACKER_AUTO auto-echo on run. Full suite green (53 checks). --- agent-queue/selftest.sh | 103 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/agent-queue/selftest.sh b/agent-queue/selftest.sh index ffeb0be..29a663f 100755 --- a/agent-queue/selftest.sh +++ b/agent-queue/selftest.sh @@ -585,4 +585,107 @@ else fi unset AGENT_QUEUE_PROFILES +# ───────────────────────────────────────────────────────────────────── +# Phase 1 — Slice 4 cases (tracker adapter §10). No live service: a stub +# replaces tracker_api via AQ_TRACKER_API_CMD, records calls, returns canned JSON. +# ───────────────────────────────────────────────────────────────────── +trkstub="$tmp/trk-stub.sh" +cat > "$trkstub" <<'STUBEOF' +#!/usr/bin/env bash +# tracker API stub: records " :: " and returns canned output +# (body line + HTTP code line), keyed off the method. +[ -n "${AQ_STUB_CALLS:-}" ] && printf '%s %s :: %s\n' "$1" "$2" "$3" >> "$AQ_STUB_CALLS" +case "$1" in + GET) printf '%s\n%s\n' "${AQ_STUB_ITEM:-}" "${AQ_STUB_GET_CODE:-200}" ;; + *) printf '%s\n%s\n' '{}' "${AQ_STUB_CODE:-200}" ;; +esac +STUBEOF +chmod +x "$trkstub" +export AQ_TRACKER_API_CMD="$trkstub" +export AQ_TRACKER_CWD="$work" + +# 26. from-tracker materializes an inbox job with the derived frontmatter + body. +export AGENT_QUEUE_ROOT="$tmp/queue-ft1" +"$AQ" init >/dev/null +export AQ_STUB_CALLS="$tmp/ft1-calls.log"; : > "$AQ_STUB_CALLS" +export AQ_STUB_ITEM='{"id":"T-1","productId":"p","type":"task","status":"open","priority":"medium","title":"Title One","description":"BODY-DESC-ALPHA","labels":[]}' +"$AQ" from-tracker T-1 >/dev/null 2>&1 +ftf=$(find "$AGENT_QUEUE_ROOT/inbox" -maxdepth 1 -name '*.md' 2>/dev/null | head -1) +if [ -n "$ftf" ] && grep -q '^tracker-item: T-1$' "$ftf" \ + && grep -q '^idempotency-key: tracker-T-1$' "$ftf" && grep -q 'BODY-DESC-ALPHA' "$ftf"; then + pass "from-tracker: materializes inbox job (tracker-item + idempotency-key + body)" +else + [ -n "$ftf" ] && cat "$ftf" >&2; fail "from-tracker did not create the expected inbox job" +fi + +# 27. from-tracker maps labels -> manifest frontmatter. +export AGENT_QUEUE_ROOT="$tmp/queue-ft2" +"$AQ" init >/dev/null +export AQ_STUB_ITEM='{"id":"T-2","productId":"p","type":"task","status":"open","priority":"low","title":"Two","description":"desc two","labels":["engine-class:agentic-coder","priority:high","cap:os:mac"]}' +"$AQ" from-tracker T-2 >/dev/null 2>&1 +ftf2=$(find "$AGENT_QUEUE_ROOT/inbox" -maxdepth 1 -name '*.md' 2>/dev/null | head -1) +if grep -q '^engine-class: agentic-coder$' "$ftf2" && grep -q '^priority: high$' "$ftf2" \ + && grep -q '^capabilities: \[os:mac\]$' "$ftf2"; then + pass "from-tracker: label mapping (engine-class/priority/cap) -> frontmatter" +else + cat "$ftf2" >&2; fail "from-tracker label mapping incorrect" +fi + +# 28. from-tracker is idempotent on the derived key (no duplicate enqueue). +"$AQ" from-tracker T-2 >/dev/null 2>&1 +n=$(find "$AGENT_QUEUE_ROOT/inbox" -maxdepth 1 -name '*.md' 2>/dev/null | wc -l | tr -d ' ') +[ "$n" = "1" ] && pass "from-tracker: idempotent (T-2 twice -> one job)" \ + || fail "from-tracker not idempotent (inbox=$n)" + +# 29. to-tracker echoes a shipped outcome: PATCH status=done + metrics comment, +# and NEVER sends the prompt body. +export AGENT_QUEUE_ROOT="$tmp/queue-tt" +"$AQ" init >/dev/null +export AQ_STUB_CALLS="$tmp/tt-calls.log"; : > "$AQ_STUB_CALLS" +printf '%s\n' 'job=jt' 'tracker_item=T-9' 'result=shipped' 'attempts=1' 'duration_s=5' \ + 'tokens_in=10' 'tokens_out=3' 'cost_usd=0.001' > "$AGENT_QUEUE_ROOT/.state/jt.meta" +printf 'SECRET-PROMPT-SENTINEL\n' > "$AGENT_QUEUE_ROOT/.state/jt.body.md" +"$AQ" to-tracker jt >/dev/null 2>&1 +if grep -q 'PATCH /api/items/T-9/status :: {"status":"done"}' "$AQ_STUB_CALLS" \ + && grep -q 'POST /api/items/T-9/comments' "$AQ_STUB_CALLS" \ + && ! grep -q 'SECRET-PROMPT-SENTINEL' "$AQ_STUB_CALLS"; then + pass "to-tracker: shipped -> PATCH status=done + metrics comment; no prompt body sent" +else + cat "$AQ_STUB_CALLS" >&2; fail "to-tracker echo incorrect / leaked body" +fi + +# 30. to-tracker is idempotent: a second call for an unchanged outcome is a no-op. +: > "$AQ_STUB_CALLS" +"$AQ" to-tracker jt >/dev/null 2>&1 +[ ! -s "$AQ_STUB_CALLS" ] && pass "to-tracker: idempotent (unchanged outcome -> no PATCH/comment)" \ + || { cat "$AQ_STUB_CALLS" >&2; fail "to-tracker not idempotent (made calls on unchanged outcome)"; } + +# 31. echo failure is non-fatal: a 500 logs an error, exits 0, leaves job state intact. +export AGENT_QUEUE_ROOT="$tmp/queue-tt6" +"$AQ" init >/dev/null +printf '%s\n' 'job=jf' 'tracker_item=T-8' 'result=shipped' > "$AGENT_QUEUE_ROOT/.state/jf.meta" +printf '%s\n' '---' 'tracker-item: T-8' '---' '' '# x' > "$AGENT_QUEUE_ROOT/shipped/jf.md" +AQ_STUB_CODE=500 "$AQ" to-tracker jf >/dev/null 2>&1; rc=$? +if [ "$rc" = "0" ] && [ -f "$AGENT_QUEUE_ROOT/shipped/jf.md" ] \ + && [ -z "$(metaval "$AGENT_QUEUE_ROOT/.state/jf.meta" tracker_echoed)" ]; then + pass "to-tracker: HTTP 500 is non-fatal (exit 0, job unchanged, not marked echoed)" +else + fail "to-tracker 500 was not handled non-fatally (rc=$rc)" +fi + +# 32. auto-echo (AQ_TRACKER_AUTO=1): a tracker-derived job run echoes automatically. +export AGENT_QUEUE_ROOT="$tmp/queue-auto" +"$AQ" init >/dev/null +export AQ_STUB_CALLS="$tmp/auto-calls.log"; : > "$AQ_STUB_CALLS" +printf '%s\n' '---' 'engine: devin' "cwd: $work" 'yolo: true' 'tracker-item: T-7' '---' '' '# auto task' \ + > "$AGENT_QUEUE_ROOT/inbox/autojob.md" +AQ_TRACKER_AUTO=1 DEVIN_BIN="$stub" "$AQ" run --once >/dev/null 2>&1 +if grep -q 'PATCH /api/items/T-7/status' "$AQ_STUB_CALLS" 2>/dev/null \ + && ls "$AGENT_QUEUE_ROOT"/review/autojob.md >/dev/null 2>&1; then + pass "auto-echo: AQ_TRACKER_AUTO=1 echoes a transition during run (job still reaches review/)" +else + cat "$AQ_STUB_CALLS" 2>/dev/null >&2; fail "auto-echo did not fire / job did not complete" +fi +unset AQ_TRACKER_API_CMD AQ_TRACKER_CWD AQ_STUB_CALLS AQ_STUB_ITEM AQ_STUB_CODE AQ_STUB_GET_CODE + echo "self-test PASS"