feat(agent-queue): tracker adapter — task <-> job round-trip (P1-S4)
Implements §10 single-host tracker integration, closing the last Phase-1 §14 item: - tracker_api: one curl-only HTTP wrapper (base URL + bearer + productId header), overridable via AQ_TRACKER_API_CMD so tests need no live service. Emits the response body + a trailing HTTP-code line; _api_call splits into API_BODY/API_CODE. - aq from-tracker <ITEM_ID>: GET the Item, map title/description -> job body, labels (engine-class:/profile:/priority:/cap:) + Item priority -> frontmatter, and stamp tracker-item + a stable idempotency-key tracker-<id>. Materializes a .md into inbox/ via cmd_add; idempotent (Slice 1 dedupe) so a re-pull never dups. JSON parsed with POSIX awk (no jq) — mac + linux safe. - aq to-tracker <job>: one-way echo (child -> tracker, §24.5). PATCHes the Item status (building/review/testing->in_progress, shipped->done, failures->wont_fix, all overridable) and posts a metrics-only comment (result/attempts/duration/ tokens/cost/diff — NEVER prompt content or secrets). Idempotent via meta tracker_echoed; an echo failure (e.g. HTTP 500) is logged and non-fatal — the tracker is downstream, never authoritative for execution. - Opt-in auto-echo (AQ_TRACKER_AUTO=1, default OFF): the worker echoes on each transition (building via cmd_run, review/testing/failed via run_worker, shipped via ship/promote); never blocks or fails a job. - status + insights surface tracker-item and the last echoed status. curl-only HTTP; no new runtime deps; conventional + backward-compatible.
This commit is contained in:
parent
d0348f23de
commit
b7a9ea1b7a
@ -66,6 +66,25 @@ CLAUDE_BIN="${CLAUDE_BIN:-$(command -v claude || echo claude)}"
|
|||||||
CODEX_BIN="${CODEX_BIN:-$(command -v codex || echo codex)}"
|
CODEX_BIN="${CODEX_BIN:-$(command -v codex || echo codex)}"
|
||||||
COPILOT_BIN="${COPILOT_BIN:-$(command -v copilot || echo copilot)}"
|
COPILOT_BIN="${COPILOT_BIN:-$(command -v copilot || echo copilot)}"
|
||||||
|
|
||||||
|
# ── Tracker integration (§10) — task <-> job round-trip via the items API ──
|
||||||
|
# Base URL of the platform-service items API; the items routes live under /api.
|
||||||
|
AQ_TRACKER_API="${AQ_TRACKER_API:-http://localhost:4003}"
|
||||||
|
# Bearer token (required for real calls; never hardcode). productId stamps Items.
|
||||||
|
AQ_TRACKER_TOKEN="${AQ_TRACKER_TOKEN:-}"
|
||||||
|
AQ_PRODUCT_ID="${AQ_PRODUCT_ID:-}"
|
||||||
|
# cwd a tracker-derived job runs in (Items carry no cwd); defaults to the invoking dir.
|
||||||
|
AQ_TRACKER_CWD="${AQ_TRACKER_CWD:-$PWD}"
|
||||||
|
# Auto-echo job outcomes back to the tracker on each transition (opt-in, default OFF).
|
||||||
|
AQ_TRACKER_AUTO="${AQ_TRACKER_AUTO:-0}"
|
||||||
|
# Item status the API uses for each bucket (the items API has no blocked/failed
|
||||||
|
# status, so failures map to wont_fix by default — all overridable).
|
||||||
|
AQ_TRACKER_STATUS_INPROGRESS="${AQ_TRACKER_STATUS_INPROGRESS:-in_progress}"
|
||||||
|
AQ_TRACKER_STATUS_DONE="${AQ_TRACKER_STATUS_DONE:-done}"
|
||||||
|
AQ_TRACKER_STATUS_FAILED="${AQ_TRACKER_STATUS_FAILED:-wont_fix}"
|
||||||
|
# Test seam: a stub script that replaces the real curl HTTP (see selftest.sh).
|
||||||
|
AQ_TRACKER_API_CMD="${AQ_TRACKER_API_CMD:-}"
|
||||||
|
CURL_BIN="${CURL_BIN:-$(command -v curl || echo curl)}"
|
||||||
|
|
||||||
# ── Colors ──────────────────────────────────────────────────────────
|
# ── Colors ──────────────────────────────────────────────────────────
|
||||||
if [[ -t 1 ]]; then
|
if [[ -t 1 ]]; then
|
||||||
C_RESET=$'\033[0m'; C_DIM=$'\033[2m'; C_BOLD=$'\033[1m'
|
C_RESET=$'\033[0m'; C_DIM=$'\033[2m'; C_BOLD=$'\033[1m'
|
||||||
@ -613,6 +632,7 @@ run_worker() {
|
|||||||
} >> "$logf"
|
} >> "$logf"
|
||||||
mv "$doing_file" "$FAILED/" 2>/dev/null
|
mv "$doing_file" "$FAILED/" 2>/dev/null
|
||||||
{ echo "result=capability_mismatch"; echo "ended=$(date +%s)"; } >> "$metaf"
|
{ echo "result=capability_mismatch"; echo "ended=$(date +%s)"; } >> "$metaf"
|
||||||
|
_auto_echo "$job"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -628,6 +648,7 @@ run_worker() {
|
|||||||
} >> "$logf"
|
} >> "$logf"
|
||||||
mv "$doing_file" "$FAILED/" 2>/dev/null
|
mv "$doing_file" "$FAILED/" 2>/dev/null
|
||||||
{ echo "result=no_engine"; echo "ended=$(date +%s)"; } >> "$metaf"
|
{ echo "result=no_engine"; echo "ended=$(date +%s)"; } >> "$metaf"
|
||||||
|
_auto_echo "$job"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -642,6 +663,7 @@ run_worker() {
|
|||||||
echo "FATAL: cwd does not exist: $cwd" >> "$logf"
|
echo "FATAL: cwd does not exist: $cwd" >> "$logf"
|
||||||
mv "$doing_file" "$FAILED/" 2>/dev/null
|
mv "$doing_file" "$FAILED/" 2>/dev/null
|
||||||
echo "result=failed" >> "$metaf"; echo "ended=$(date +%s)" >> "$metaf"
|
echo "result=failed" >> "$metaf"; echo "ended=$(date +%s)" >> "$metaf"
|
||||||
|
_auto_echo "$job"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -773,6 +795,9 @@ run_worker() {
|
|||||||
echo "FAILED (rc=$rc): $(date)" >> "$logf"
|
echo "FAILED (rc=$rc): $(date)" >> "$logf"
|
||||||
_finish_failure "$job" "$doing_file" "$metaf" "$logf" "crash" "$rc" "$started"
|
_finish_failure "$job" "$doing_file" "$metaf" "$logf" "crash" "$rc" "$started"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Opt-in echo of the resting/terminal outcome back to the tracker (§10).
|
||||||
|
_auto_echo "$job"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Resilience & insights helpers (Phase 1 — single-host §25/§26) ────
|
# ── Resilience & insights helpers (Phase 1 — single-host §25/§26) ────
|
||||||
@ -1029,6 +1054,222 @@ _insights_line() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ── Commands ────────────────────────────────────────────────────────
|
# ── Commands ────────────────────────────────────────────────────────
|
||||||
|
# ── Tracker integration (§10) — task <-> job round-trip ─────────────
|
||||||
|
#
|
||||||
|
# tracker_api <METHOD> <PATH> [JSON] -> emits the response body, then a final
|
||||||
|
# line with the HTTP status code. ALL HTTP goes through here (curl only). Tests
|
||||||
|
# replace it wholesale via AQ_TRACKER_API_CMD so no live service is needed.
|
||||||
|
tracker_api() {
|
||||||
|
local method=$1 path=$2 body=${3:-}
|
||||||
|
if [[ -n "$AQ_TRACKER_API_CMD" ]]; then
|
||||||
|
"$AQ_TRACKER_API_CMD" "$method" "$path" "$body"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
local url="${AQ_TRACKER_API}${path}"
|
||||||
|
local -a args=(-sS -m "${AQ_TRACKER_TIMEOUT:-30}" -X "$method"
|
||||||
|
-H "Content-Type: application/json" -w '\n%{http_code}')
|
||||||
|
[[ -n "$AQ_TRACKER_TOKEN" ]] && args+=(-H "Authorization: Bearer $AQ_TRACKER_TOKEN")
|
||||||
|
[[ -n "$AQ_PRODUCT_ID" ]] && args+=(-H "X-Product-Id: $AQ_PRODUCT_ID")
|
||||||
|
[[ -n "$body" ]] && args+=(--data "$body")
|
||||||
|
local out rc
|
||||||
|
out=$("$CURL_BIN" "${args[@]}" "$url" 2>/dev/null); rc=$?
|
||||||
|
if [[ $rc -ne 0 ]]; then printf '%s\n000\n' "$out"; else printf '%s\n' "$out"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# _api_call <METHOD> <PATH> [JSON] -> sets globals API_BODY + API_CODE.
|
||||||
|
_api_call() {
|
||||||
|
local out; out=$(tracker_api "$@")
|
||||||
|
API_CODE=$(printf '%s' "$out" | tail -n1)
|
||||||
|
API_BODY=$(printf '%s' "$out" | sed '$d')
|
||||||
|
}
|
||||||
|
|
||||||
|
# _json_str <key> (reads JSON on stdin) -> the top-level string value, unescaped.
|
||||||
|
# Pure awk (POSIX) — mac + linux safe, no jq dependency.
|
||||||
|
_json_str() {
|
||||||
|
awk -v key="$1" '
|
||||||
|
{ json = json $0 }
|
||||||
|
END {
|
||||||
|
pat = "\"" key "\""
|
||||||
|
i = index(json, pat); if (i == 0) exit
|
||||||
|
rest = substr(json, i + length(pat))
|
||||||
|
sub(/^[ \t]*:[ \t]*/, "", rest)
|
||||||
|
if (substr(rest, 1, 1) != "\"") exit
|
||||||
|
rest = substr(rest, 2); n = length(rest)
|
||||||
|
for (j = 1; j <= n; j++) {
|
||||||
|
c = substr(rest, j, 1)
|
||||||
|
if (c == "\\") { j++; e = substr(rest, j, 1)
|
||||||
|
if (e == "n") out = out "\n"; else if (e == "t") out = out "\t"
|
||||||
|
else if (e == "r") out = out "\r"; else out = out e }
|
||||||
|
else if (c == "\"") break
|
||||||
|
else out = out c
|
||||||
|
}
|
||||||
|
printf "%s", out
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# _json_labels (reads JSON on stdin) -> one labels[] entry per line.
|
||||||
|
_json_labels() {
|
||||||
|
awk '
|
||||||
|
{ json = json $0 }
|
||||||
|
END {
|
||||||
|
i = index(json, "\"labels\""); if (i == 0) exit
|
||||||
|
rest = substr(json, i); lb = index(rest, "["); rb = index(rest, "]")
|
||||||
|
if (lb == 0 || rb == 0 || rb < lb) exit
|
||||||
|
arr = substr(rest, lb + 1, rb - lb - 1)
|
||||||
|
while (match(arr, /"([^"\\]|\\.)*"/)) {
|
||||||
|
tok = substr(arr, RSTART + 1, RLENGTH - 2)
|
||||||
|
gsub(/\\"/, "\"", tok); print tok
|
||||||
|
arr = substr(arr, RSTART + RLENGTH)
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# _json_escape <text> -> the text as a JSON string body (no surrounding quotes).
|
||||||
|
_json_escape() {
|
||||||
|
printf '%s' "$1" | awk '
|
||||||
|
{ line = $0; gsub(/\\/, "\\\\", line); gsub(/"/, "\\\"", line); gsub(/\t/, "\\t", line)
|
||||||
|
out = out (NR > 1 ? "\\n" : "") line }
|
||||||
|
END { printf "%s", out }'
|
||||||
|
}
|
||||||
|
|
||||||
|
# _tracker_status_for <result> -> the Item status for a job result/stage.
|
||||||
|
_tracker_status_for() {
|
||||||
|
case "$1" in
|
||||||
|
shipped) printf '%s' "$AQ_TRACKER_STATUS_DONE";;
|
||||||
|
failed|timeout|verify_failed|retries_exhausted|capability_mismatch|no_engine|rejected)
|
||||||
|
printf '%s' "$AQ_TRACKER_STATUS_FAILED";;
|
||||||
|
*) printf '%s' "$AQ_TRACKER_STATUS_INPROGRESS";;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# _tracker_note <job> <metaf> <result> <status> -> a metrics-only summary line.
|
||||||
|
# NEVER includes prompt/body content or secrets — only run metrics (§24.5/§26).
|
||||||
|
_tracker_note() {
|
||||||
|
local jn=$1 metaf=$2 result=$3 status=$4 s attempts dur ti to cost la ld
|
||||||
|
attempts=$(_meta_val "$metaf" attempts); dur=$(_meta_val "$metaf" duration_s)
|
||||||
|
ti=$(_meta_val "$metaf" tokens_in); to=$(_meta_val "$metaf" tokens_out)
|
||||||
|
cost=$(_meta_val "$metaf" cost_usd)
|
||||||
|
la=$(_meta_val "$metaf" lines_added); ld=$(_meta_val "$metaf" lines_deleted)
|
||||||
|
s="agent-queue: job ${jn} -> ${result:-$status} (status=${status})."
|
||||||
|
[[ -n "$attempts" ]] && s+=" attempts=${attempts}."
|
||||||
|
[[ -n "$dur" ]] && s+=" duration=${dur}s."
|
||||||
|
[[ -n "$ti$to" ]] && s+=" tokens=${ti:-0}/${to:-0}."
|
||||||
|
[[ -n "$cost" ]] && s+=" cost_usd=${cost}."
|
||||||
|
[[ -n "$la$ld" ]] && s+=" diff=+${la:-0}/-${ld:-0}."
|
||||||
|
printf '%s' "$s"
|
||||||
|
}
|
||||||
|
|
||||||
|
# from-tracker <ITEM_ID> — pull a tracker Item and materialize a job in inbox/.
|
||||||
|
# Idempotent on the derived key `tracker-<ITEM_ID>` (Slice 1 dedupe).
|
||||||
|
cmd_from_tracker() {
|
||||||
|
ensure_dirs
|
||||||
|
local item_id="${1:-}"
|
||||||
|
[[ -n "$item_id" ]] || die "usage: from-tracker <ITEM_ID>"
|
||||||
|
_api_call GET "/api/items/$item_id"
|
||||||
|
case "$API_CODE" in 2*) :;; *) die "from-tracker: items API returned HTTP ${API_CODE:-error} for item $item_id";; esac
|
||||||
|
|
||||||
|
local title desc iprio
|
||||||
|
title=$(printf '%s' "$API_BODY" | _json_str title)
|
||||||
|
desc=$(printf '%s' "$API_BODY" | _json_str description)
|
||||||
|
iprio=$(printf '%s' "$API_BODY" | _json_str priority)
|
||||||
|
[[ -n "$title$desc" ]] || die "from-tracker: item $item_id has no title/description (HTTP $API_CODE)"
|
||||||
|
|
||||||
|
# labels carry optional manifest hints: engine-class:, profile:, priority:, cap:
|
||||||
|
local engine_class="" profile="" prio="" caps_list="" label
|
||||||
|
while IFS= read -r label; do
|
||||||
|
[[ -n "$label" ]] || continue
|
||||||
|
case "$label" in
|
||||||
|
engine-class:*) engine_class=${label#engine-class:};;
|
||||||
|
profile:*) profile=${label#profile:};;
|
||||||
|
priority:*) prio=${label#priority:};;
|
||||||
|
cap:*) caps_list+="${label#cap:}, ";;
|
||||||
|
esac
|
||||||
|
done < <(printf '%s' "$API_BODY" | _json_labels)
|
||||||
|
prio=${prio:-${iprio:-medium}}
|
||||||
|
case "$prio" in critical|high|medium|low) :;; *) prio=medium;; esac
|
||||||
|
|
||||||
|
# Materialize into a .md file (so cmd_add/the queue recognize it). mktemp -d is
|
||||||
|
# the portable way to get a unique path with a fixed (.md) basename on mac+linux.
|
||||||
|
local safe_id tmpdir tmp
|
||||||
|
safe_id=$(printf '%s' "$item_id" | tr -c 'A-Za-z0-9._-' '_')
|
||||||
|
tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/aq-fromtracker.XXXXXX")
|
||||||
|
tmp="$tmpdir/tracker-$safe_id.md"
|
||||||
|
{
|
||||||
|
echo "---"
|
||||||
|
echo "cwd: $AQ_TRACKER_CWD"
|
||||||
|
echo "yolo: true"
|
||||||
|
echo "priority: $prio"
|
||||||
|
[[ -n "$engine_class" ]] && echo "engine-class: $engine_class"
|
||||||
|
[[ -n "$profile" ]] && echo "profile: $profile"
|
||||||
|
[[ -n "$caps_list" ]] && echo "capabilities: [${caps_list%, }]"
|
||||||
|
echo "tracker-item: $item_id"
|
||||||
|
echo "idempotency-key: tracker-$item_id"
|
||||||
|
echo "---"
|
||||||
|
echo
|
||||||
|
[[ -n "$title" ]] && { echo "# $title"; echo; }
|
||||||
|
printf '%s\n' "$desc"
|
||||||
|
} > "$tmp"
|
||||||
|
|
||||||
|
cmd_add "$tmp"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
local created; created=$(grep -lE "^tracker-item:[[:space:]]*${item_id}[[:space:]]*\$" "$INBOX"/*.md 2>/dev/null | head -1)
|
||||||
|
if [[ -n "$created" ]]; then
|
||||||
|
log "from-tracker: item $item_id -> $C_BOLD$(basename "$created")$C_RESET"
|
||||||
|
else
|
||||||
|
log "from-tracker: item $item_id already queued elsewhere (deduped)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# to-tracker <job> — one-way echo of a job's CURRENT outcome to its tracker Item
|
||||||
|
# (child -> tracker, §24.5). Idempotent via meta `tracker_echoed`; never fatal.
|
||||||
|
cmd_to_tracker() {
|
||||||
|
ensure_dirs
|
||||||
|
local job="${1:-}"
|
||||||
|
[[ -n "$job" ]] || die "usage: to-tracker <job>"
|
||||||
|
local metaf="$STATE/$job.meta"
|
||||||
|
[[ -f "$metaf" ]] || metaf=$(ls -1t "$STATE"/*"$job"*.meta 2>/dev/null | head -1)
|
||||||
|
[[ -f "$metaf" ]] || die "to-tracker: no meta for job '$job'"
|
||||||
|
local jn; jn=$(basename "$metaf"); jn=${jn%.meta}
|
||||||
|
|
||||||
|
local item_id; item_id=$(_meta_val "$metaf" tracker_item)
|
||||||
|
if [[ -z "$item_id" ]]; then
|
||||||
|
log "to-tracker: $jn has no tracker-item — nothing to echo"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local result status last
|
||||||
|
result=$(_meta_val "$metaf" result)
|
||||||
|
status=$(_tracker_status_for "$result")
|
||||||
|
last=$(_meta_val "$metaf" tracker_echoed)
|
||||||
|
if [[ "$last" == "$status" ]]; then
|
||||||
|
log "to-tracker: $jn already echoed status=$status to $item_id (no-op)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1) status transition
|
||||||
|
_api_call PATCH "/api/items/$item_id/status" "{\"status\":\"$status\"}"
|
||||||
|
case "$API_CODE" in
|
||||||
|
2*) :;;
|
||||||
|
*) err "to-tracker: status PATCH for $item_id failed (HTTP ${API_CODE:-error}) — non-fatal; job state unchanged"; return 0;;
|
||||||
|
esac
|
||||||
|
# 2) metrics-only comment (never prompt content / secrets)
|
||||||
|
local note; note=$(_tracker_note "$jn" "$metaf" "$result" "$status")
|
||||||
|
_api_call POST "/api/items/$item_id/comments" "{\"body\":\"$(_json_escape "$note")\"}"
|
||||||
|
case "$API_CODE" in
|
||||||
|
2*) :;;
|
||||||
|
*) err "to-tracker: comment for $item_id failed (HTTP ${API_CODE:-error}) — non-fatal";;
|
||||||
|
esac
|
||||||
|
# 3) record echoed status (idempotency)
|
||||||
|
{ echo "tracker_echoed=$status"; echo "tracker_echoed_at=$(date +%s)"; } >> "$metaf"
|
||||||
|
log "to-tracker: echoed $jn -> item $item_id (status=$status)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# _auto_echo <job> — opt-in (AQ_TRACKER_AUTO=1) best-effort echo on a transition.
|
||||||
|
# Never blocks or fails the job: the tracker is downstream, not authoritative.
|
||||||
|
_auto_echo() {
|
||||||
|
[[ "$AQ_TRACKER_AUTO" == 1 ]] || return 0
|
||||||
|
cmd_to_tracker "$1" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
cmd_init() { ensure_dirs; log "queue initialized at $C_BOLD$QUEUE_ROOT$C_RESET"; }
|
cmd_init() { ensure_dirs; log "queue initialized at $C_BOLD$QUEUE_ROOT$C_RESET"; }
|
||||||
|
|
||||||
cmd_add() {
|
cmd_add() {
|
||||||
@ -1215,6 +1456,7 @@ cmd_run() {
|
|||||||
run_worker "$doing_file" &
|
run_worker "$doing_file" &
|
||||||
{ echo "pid=$!"; echo "pidstart=$(_pidstart "$!")"; } >> "$STATE/$job.meta"
|
{ echo "pid=$!"; echo "pidstart=$(_pidstart "$!")"; } >> "$STATE/$job.meta"
|
||||||
log "▶ launching $C_BOLD$job$C_RESET (engine=$w_eng, lock=$w_key)"
|
log "▶ launching $C_BOLD$job$C_RESET (engine=$w_eng, lock=$w_key)"
|
||||||
|
_auto_echo "$job" # building -> in_progress (opt-in)
|
||||||
sleep 1
|
sleep 1
|
||||||
running=$(active_workers)
|
running=$(active_workers)
|
||||||
done
|
done
|
||||||
@ -1269,10 +1511,12 @@ cmd_status() {
|
|||||||
local m_prio m_prof m_caps m_trk extra=""
|
local m_prio m_prof m_caps m_trk extra=""
|
||||||
m_prio=$(grep '^priority=' "$f" | cut -d= -f2-); m_prof=$(grep '^profile=' "$f" | cut -d= -f2-)
|
m_prio=$(grep '^priority=' "$f" | cut -d= -f2-); m_prof=$(grep '^profile=' "$f" | cut -d= -f2-)
|
||||||
m_caps=$(grep '^capabilities=' "$f" | cut -d= -f2-); m_trk=$(grep '^tracker_item=' "$f" | cut -d= -f2-)
|
m_caps=$(grep '^capabilities=' "$f" | cut -d= -f2-); m_trk=$(grep '^tracker_item=' "$f" | cut -d= -f2-)
|
||||||
|
local m_echo; m_echo=$(grep '^tracker_echoed=' "$f" | tail -1 | cut -d= -f2-)
|
||||||
[[ -n "$m_prio" ]] && extra+="prio=$m_prio "
|
[[ -n "$m_prio" ]] && extra+="prio=$m_prio "
|
||||||
[[ -n "$m_prof" ]] && extra+="profile=$m_prof "
|
[[ -n "$m_prof" ]] && extra+="profile=$m_prof "
|
||||||
[[ -n "$m_caps" ]] && extra+="caps=$m_caps "
|
[[ -n "$m_caps" ]] && extra+="caps=$m_caps "
|
||||||
[[ -n "$m_trk" ]] && extra+="tracker=$m_trk "
|
[[ -n "$m_trk" ]] && extra+="tracker=$m_trk "
|
||||||
|
[[ -n "$m_echo" ]] && extra+="echoed=$m_echo "
|
||||||
[[ -n "$extra" ]] && printf ' %s%s%s\n' "$C_DIM" "$extra" "$C_RESET"
|
[[ -n "$extra" ]] && printf ' %s%s%s\n' "$C_DIM" "$extra" "$C_RESET"
|
||||||
printf ' %s%s%s\n' "$C_DIM" "$(_insights_line "$f")" "$C_RESET"
|
printf ' %s%s%s\n' "$C_DIM" "$(_insights_line "$f")" "$C_RESET"
|
||||||
done
|
done
|
||||||
@ -1315,7 +1559,7 @@ cmd_insights() {
|
|||||||
for k in engine result attempts started ended duration_s exit verify_exit \
|
for k in engine result attempts started ended duration_s exit verify_exit \
|
||||||
model tokens_in tokens_out tokens_cached cost_usd turns tool_calls usage_estimated \
|
model tokens_in tokens_out tokens_cached cost_usd turns tool_calls usage_estimated \
|
||||||
files_changed lines_added lines_deleted wip_branch wip_base wip_commit \
|
files_changed lines_added lines_deleted wip_branch wip_base wip_commit \
|
||||||
next_eligible retry_class recovered; do
|
next_eligible retry_class recovered tracker_item tracker_echoed tracker_echoed_at; do
|
||||||
val=$(_meta_val "$f" "$k")
|
val=$(_meta_val "$f" "$k")
|
||||||
[[ -n "$val" ]] && printf ' %-15s %s\n' "$k" "$val"
|
[[ -n "$val" ]] && printf ' %-15s %s\n' "$k" "$val"
|
||||||
done
|
done
|
||||||
@ -1428,6 +1672,7 @@ cmd_ship() {
|
|||||||
mv "$f" "$SHIPPED/$base"
|
mv "$f" "$SHIPPED/$base"
|
||||||
[[ -f "$STATE/$name.meta" ]] && echo "result=shipped" >> "$STATE/$name.meta"
|
[[ -f "$STATE/$name.meta" ]] && echo "result=shipped" >> "$STATE/$name.meta"
|
||||||
log "shipped $C_BOLD$base$C_RESET (testing → shipped)"
|
log "shipped $C_BOLD$base$C_RESET (testing → shipped)"
|
||||||
|
_auto_echo "$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
# promote <job> — advance one stage forward: review → testing → shipped.
|
# promote <job> — advance one stage forward: review → testing → shipped.
|
||||||
@ -1447,6 +1692,7 @@ cmd_promote() {
|
|||||||
mv "$f" "$dest/$base"
|
mv "$f" "$dest/$base"
|
||||||
[[ -f "$STATE/$name.meta" ]] && echo "result=$result" >> "$STATE/$name.meta"
|
[[ -f "$STATE/$name.meta" ]] && echo "result=$result" >> "$STATE/$name.meta"
|
||||||
log "promoted $C_BOLD$base$C_RESET ($from → $result)"
|
log "promoted $C_BOLD$base$C_RESET ($from → $result)"
|
||||||
|
_auto_echo "$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
# reject <job> — move a review/testing job to failed/ (manual gate rejection).
|
# reject <job> — move a review/testing job to failed/ (manual gate rejection).
|
||||||
@ -1516,6 +1762,8 @@ ${C_BOLD}COMMANDS${C_RESET}
|
|||||||
watch [interval] live status (default 2s, bash)
|
watch [interval] live status (default 2s, bash)
|
||||||
insights [job] per-job metrics, or recent table + per-engine rollup
|
insights [job] per-job metrics, or recent table + per-engine rollup
|
||||||
recover reclaim orphaned building/ jobs (dead worker) -> inbox
|
recover reclaim orphaned building/ jobs (dead worker) -> inbox
|
||||||
|
from-tracker <ITEM_ID> pull a tracker Item -> materialize a job in inbox/ (§10)
|
||||||
|
to-tracker <job> echo a job's outcome to its tracker Item (one-way)
|
||||||
dash [--interval N] richer live Node dashboard (recent shipped/failed too)
|
dash [--interval N] richer live Node dashboard (recent shipped/failed too)
|
||||||
stop kill running workers + the run loop
|
stop kill running workers + the run loop
|
||||||
logs <job> [-f] print (or follow) a job's log
|
logs <job> [-f] print (or follow) a job's log
|
||||||
@ -1565,6 +1813,12 @@ ${C_BOLD}ENV${C_RESET}
|
|||||||
AGENT_QUEUE_ROOT (=$QUEUE_ROOT) AGENT_QUEUE_MAX (=$MAX_CONCURRENCY)
|
AGENT_QUEUE_ROOT (=$QUEUE_ROOT) AGENT_QUEUE_MAX (=$MAX_CONCURRENCY)
|
||||||
AGENT_QUEUE_ENGINE (=$DEFAULT_ENGINE) AGENT_QUEUE_VERIFY (default verify cmd)
|
AGENT_QUEUE_ENGINE (=$DEFAULT_ENGINE) AGENT_QUEUE_VERIFY (default verify cmd)
|
||||||
DEVIN_BIN / CLAUDE_BIN / CODEX_BIN / COPILOT_BIN
|
DEVIN_BIN / CLAUDE_BIN / CODEX_BIN / COPILOT_BIN
|
||||||
|
|
||||||
|
${C_BOLD}TRACKER${C_RESET} (§10 — from-tracker / to-tracker; real use needs platform-service + a token)
|
||||||
|
AQ_TRACKER_API (=$AQ_TRACKER_API) AQ_TRACKER_TOKEN (bearer) AQ_PRODUCT_ID
|
||||||
|
AQ_TRACKER_AUTO=1 to auto-echo outcomes on each transition (default OFF)
|
||||||
|
AQ_TRACKER_CWD (cwd for tracker-derived jobs) AQ_TRACKER_API_CMD (test stub seam)
|
||||||
|
label hints on an Item: engine-class:<x> profile:<x> priority:<x> cap:<token>
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1578,6 +1832,8 @@ main() {
|
|||||||
watch) cmd_watch "$@";;
|
watch) cmd_watch "$@";;
|
||||||
insights) cmd_insights "$@";;
|
insights) cmd_insights "$@";;
|
||||||
recover) cmd_recover "$@";;
|
recover) cmd_recover "$@";;
|
||||||
|
from-tracker) cmd_from_tracker "$@";;
|
||||||
|
to-tracker) cmd_to_tracker "$@";;
|
||||||
dash|dashboard) cmd_dash "$@";;
|
dash|dashboard) cmd_dash "$@";;
|
||||||
stop) cmd_stop "$@";;
|
stop) cmd_stop "$@";;
|
||||||
logs) cmd_logs "$@";;
|
logs) cmd_logs "$@";;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user