Files
boshu2__agentops/scripts/validate-codex-cli-skills.sh
Bo 8061085c89 Ship native evidence helpers and fresh-family review defaults (#1110)
AO now performs intent snapshots, subject manifests, strict evidence
verification, atomic verdict storage, and orphan inspection through the
Go binary. The command handler keeps verification separate from
presentation so it meets the existing complexity limit. These operations
preserve the existing evidence formats, require explicit protected
storage where applicable, and run outside a checkout without Python. The
unchanged Python implementation remains a developer oracle; agents still
provide semantic judgment.

Codex and Claude skills now default to a fresh reviewer from the
author’s model family. Callers can explicitly request cross-model review
or pin its model. Reviewer adapters use a finite caller timeout or
remaining deadline instead of a fixed ten-minute default, while
retaining output limits and abnormal-termination cleanup.

Validation: Go build, vet, tests and race/shuffle tests; 1,334 shell
tests; aggregate runner; regeneration check; 72 full-mode gates.
Independent checks exercised 84 storage-boundary rejections and 21
evidence operations with an empty PATH. Both canonical and generated RPI
reference suites pass all 48 tests after updating the migrated oracle
import without weakening assertions.

Change-sensitive checks explicitly compare the final committed candidate
with the original PR base. Linux, Windows, installer, security, and
required summary checks are green.
2026-09-08 16:06:33 -04:00

132 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Shared fail-closed codex runner (STALL/ECHO/MISSING defenses + distinct exit
# codes). age-gate-the-ungated-egwt.8. `CDPATH=` is an intentional env-prefix
# (clears CDPATH for that one cd), not a botched assignment.
# shellcheck disable=SC1007
. "$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/codex-exec.sh"
EXPECTED_CSV="using-agentops,swarm,research"
WORKDIR="/tmp"
PROFILE="${CODEX_VALIDATE_PROFILE:-safe}"
usage() {
cat <<'EOF'
validate-codex-cli-skills.sh
Open a fresh non-interactive Codex session and verify that expected AgentOps
skills are visible to the runtime.
Options:
--expected <a,b,c> Comma-separated skill names to require
--workdir <dir> Working directory for the ephemeral Codex session
--profile <name> Codex profile to use (default: safe)
--timeout <seconds> Positive finite execution budget; no default
--deadline-epoch <seconds> Absolute Unix deadline for the caller's whole run
--help Show this help
Declare at least one execution bound with these options or the corresponding
CODEX_EXEC_TIMEOUT / CODEX_EXEC_DEADLINE_EPOCH environment variables. The earlier
bound wins when both are set. Reuse the same absolute deadline across retries.
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--expected)
EXPECTED_CSV="${2:-}"
shift 2
;;
--workdir)
WORKDIR="${2:-}"
shift 2
;;
--profile)
PROFILE="${2:-}"
shift 2
;;
--timeout)
# shellcheck disable=SC2034 # consumed by the sourced codex_exec_guarded.
CODEX_EXEC_TIMEOUT="${2-}"
shift 2
;;
--deadline-epoch)
# shellcheck disable=SC2034 # consumed by the sourced codex_exec_guarded.
CODEX_EXEC_DEADLINE_EPOCH="${2-}"
shift 2
;;
--help|-h)
usage
exit 0
;;
*)
echo "Unknown arg: $1" >&2
usage >&2
exit 2
;;
esac
done
command -v codex >/dev/null 2>&1 || {
echo "codex CLI not found in PATH" >&2
exit 1
}
mkdir -p "$WORKDIR"
OUTPUT_FILE="$(mktemp)"
cleanup() {
rm -f "$OUTPUT_FILE"
}
trap cleanup EXIT
PROMPT="List the available skill names you can see in this session. Return only a comma-separated list."
# The runner reads CODEX_EXEC_EXTRA_ARGS as an ARRAY from the current shell scope
# (it runs as a sourced function, not a subprocess) — a bash array cannot be set
# via a `VAR=... cmd` command-prefix, so assign it here before the call.
# shellcheck disable=SC2034 # consumed by codex_exec_guarded in lib/codex-exec.sh (sourced).
CODEX_EXEC_EXTRA_ARGS=(--profile "$PROFILE" --json)
if ! CODEX_EXEC_SANDBOX=read-only CODEX_EXEC_SKIP_GIT_CHECK=1 \
CODEX_EXEC_PROMPT_ARG="$PROMPT" CODEX_EXEC_OUT_FILE="$OUTPUT_FILE" \
codex_exec_guarded; then
echo "headless codex run failed while checking skill discovery" >&2
exit 1
fi
python3 - "$OUTPUT_FILE" "$EXPECTED_CSV" <<'PY'
import json
import sys
from pathlib import Path
path = Path(sys.argv[1])
expected = [item.strip() for item in sys.argv[2].split(",") if item.strip()]
messages = []
for line in path.read_text().splitlines():
line = line.strip()
if not line:
continue
try:
payload = json.loads(line)
except json.JSONDecodeError:
continue
item = payload.get("item")
if payload.get("type") == "item.completed" and isinstance(item, dict) and item.get("type") == "agent_message":
text = item.get("text", "").strip()
if text:
messages.append(text)
if not messages:
print("No agent message found in headless codex output", file=sys.stderr)
sys.exit(1)
visible = {part.strip() for part in messages[-1].split(",") if part.strip()}
missing = [name for name in expected if name not in visible]
if missing:
print("Missing expected skills: " + ", ".join(missing), file=sys.stderr)
print("Visible skills: " + ", ".join(sorted(visible)), file=sys.stderr)
sys.exit(1)
print("Visible skills: " + ", ".join(sorted(visible)))
print("Required skills present: " + ", ".join(expected))
PY