mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
e431339c40
## What AgentOps 3.0 goes **fully hookless**. This removes the entire hook product surface — the product is now skills + the `ao` CLI with **zero hooks**. CI is the authoritative gate. ## Deleted - `hooks/` — 46 hook scripts + `hooks.json` + examples (whole directory) - `cli/embedded/hooks/` + embedded `hooks.json` + `embedded/lib/hook-helpers.sh` - `lib/hook-helpers.sh` - `ao hooks` CLI command: `cli/cmd/ao/hooks.go`, `hooks_run.go` + 5 hook test files; `cli/internal/bridge/hooks.go`; `cli/internal/doctor/fix_hooks.go` + test - Codex hook manifest (`hooks/codex-hooks.json`) + handler/audit scripts (`scripts/audit-codex-hooks.sh`, `install-dev-hooks.sh`, `test-hooks-output.sh`, `test-codex-hookless-lifecycle.sh`, `test-hookless-rpi-phased.sh`) - Hook lease surface: `docs/contracts/hook-lease-*`, `schemas/hook-lease.v1.schema.json`, `scripts/check-hook-lease-inventory.sh`, `check-hook-port-replacements.sh`, `generate-hook-lease-inventory.py` - Hook docs: `docs/HOOKS.md`, `cli/docs/HOOKS.md`, `docs/architecture/hook-noise-audit.md`, `docs/contracts/hook-runtime-contract.md` - `tests/hooks/` (whole dir) + hook test scripts; 5 hook eval suites + fixtures ## CI gates removed `hook-preflight`, `validate-hooks-doc-parity`, `hook-output-schema-lint` (+ scripts/bats), the hook eval suites, the `test-runtime-codex-smoke` / `test-codex-native-install` / `test-codex-plugin-install` hook-handler assertions, the cli-integration hook-lifecycle steps, the bats `tests/hooks/*` glob + orphan-hooks audit, and the `--with-hooks` install path. `embedded-sync` now validates only lib/skills. Both summary `needs:` lists + the summary echo + `docs/contracts/ci-jobs.yaml` updated; `validate-ci-policy-parity` passes (66 rows). `.codex-plugin/plugin.json` drops the "Hooks" capability. ## Load-bearing PRESERVED (reported, not forced) - **`cli/cmd/ao/codex_runtime.go`** — the codex runtime *lifecycle profile* (`HookCapable`/`HookConfigured` detection) is a runtime-capability abstraction used by 6 `validate-codex-*` CI gates, distinct from the hook product. Deleting it is a separate refactor. - **`hooks-authoring` skill** + `schemas/hooks-manifest.v1.schema.json` — reframed as an opt-in "author your own hooks" guide. Deleting the skill cascades into catalog/domain-map/dispositions/context-map golden files (skill-count sync), out of scope for the hook-product removal. - **`scripts/pre-push-gate.sh`** — retired local gate (not in CI); self-skips deleted hook scripts via `[[ -x ]]` guards; its 55 bats tests still pass. - Domain-enforcement audit keeps the `enforced`-mode schema for backward-compatible JSON readers, but the hookless resolver only returns `audited`/`unavailable`. ## Verification `go build` / `go vet` clean; `go test ./...` = **11849 passed, 0 failed** (68 pkgs). gofmt clean on all touched files. Green: registry `--check` (0 hooks), `regen-codex-hashes --check`, `validate-ci-policy-parity`, `check-wiring-closure`, `validate-embedded-sync`, `validate-manifests`, `validate-agents-split`, `doc-release` (0 broken links), `generate-cli-reference --check`, `heal.sh --strict`, codex/claude/plugin smoke tests, baseline-audit (0 stale). Diff: 231 files, +354 / −39803. Closes-scenario: soc-57b7f#remove-all-hooks Bounded-context: BC5-Runtime Evidence: .github/workflows/validate.yml
313 lines
12 KiB
Bash
Executable File
313 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Master test runner for AgentOps plugin
|
|
# Runs all test tiers based on flag
|
|
#
|
|
# Usage:
|
|
# ./tests/run-all.sh # Run tier 1 (fast) only
|
|
# ./tests/run-all.sh --tier=2 # Run tier 1 + tier 2 (smoke tests)
|
|
# ./tests/run-all.sh --tier=3 # Run tier 1 + 2 + 3 (functional tests)
|
|
# ./tests/run-all.sh --all # Run all tests
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
# Source shared colors and helpers
|
|
# shellcheck source=tests/lib/colors.sh
|
|
source "${SCRIPT_DIR}/lib/colors.sh"
|
|
# shellcheck source=tests/lib/run-with-timeout.sh
|
|
source "${SCRIPT_DIR}/lib/run-with-timeout.sh"
|
|
|
|
TIER="${1:-}"
|
|
total_passed=0
|
|
total_failed=0
|
|
total_skipped=0
|
|
|
|
RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS="${RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS:-120}"
|
|
RUN_ALL_CLAUDE_HELP_TIMEOUT_SECONDS="${RUN_ALL_CLAUDE_HELP_TIMEOUT_SECONDS:-10}"
|
|
RUN_ALL_SMOKE_TIMEOUT_SECONDS="${RUN_ALL_SMOKE_TIMEOUT_SECONDS:-300}"
|
|
RUN_ALL_CODEX_INTEGRATION_TIMEOUT_SECONDS="${RUN_ALL_CODEX_INTEGRATION_TIMEOUT_SECONDS:-600}"
|
|
RUN_ALL_FUNCTIONAL_LANE_TIMEOUT_SECONDS="${RUN_ALL_FUNCTIONAL_LANE_TIMEOUT_SECONDS:-600}"
|
|
RUN_ALL_RELEASE_SMOKE_TIMEOUT_SECONDS="${RUN_ALL_RELEASE_SMOKE_TIMEOUT_SECONDS:-900}"
|
|
RUN_ALL_INTEGRATION_SCRIPT_TIMEOUT_SECONDS="${RUN_ALL_INTEGRATION_SCRIPT_TIMEOUT_SECONDS:-300}"
|
|
|
|
# Override helpers to increment local counters
|
|
pass() { echo -e "${GREEN} ✓${NC} $1"; ((total_passed++)) || true; }
|
|
fail() { echo -e "${RED} ✗${NC} $1"; ((total_failed++)) || true; }
|
|
skip() { echo -e "${YELLOW} ⊘${NC} $1 (skipped)"; ((total_skipped++)) || true; }
|
|
|
|
lane_log_file() {
|
|
local name="${1//[^A-Za-z0-9_.-]/-}"
|
|
echo "/tmp/agentops-run-all-${name}.log"
|
|
}
|
|
|
|
report_lane_status() {
|
|
local label="${1:?label required}"
|
|
local status="${2:?status required}"
|
|
local log_file="${3:?log file required}"
|
|
local timeout_seconds="${4:?timeout required}"
|
|
|
|
if [[ "$status" -eq 124 ]]; then
|
|
fail "$label timed out after ${timeout_seconds}s"
|
|
else
|
|
fail "$label"
|
|
fi
|
|
|
|
if [[ -s "$log_file" ]]; then
|
|
tail -20 "$log_file" | sed 's/^/ /'
|
|
fi
|
|
}
|
|
|
|
run_lane() {
|
|
local label="${1:?label required}"
|
|
local timeout_seconds="${2:?timeout required}"
|
|
local log_file="${3:?log file required}"
|
|
shift 3
|
|
|
|
local status
|
|
if run_with_timeout "$timeout_seconds" "$label" "$log_file" "$@"; then
|
|
pass "$label"
|
|
else
|
|
status=$?
|
|
report_lane_status "$label" "$status" "$log_file" "$timeout_seconds"
|
|
fi
|
|
}
|
|
|
|
echo ""
|
|
echo "═══════════════════════════════════════════"
|
|
echo "AgentOps Plugin Test Suite"
|
|
echo "═══════════════════════════════════════════"
|
|
echo ""
|
|
|
|
# =============================================================================
|
|
# Tier 1: Static Validation (fast, no Claude CLI needed)
|
|
# =============================================================================
|
|
log "Tier 1: Static Validation"
|
|
|
|
# Validate manifests against canonical schemas
|
|
run_lane "Manifest schema validation" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "$(lane_log_file manifests)" \
|
|
bash "$REPO_ROOT/scripts/validate-manifests.sh" --repo-root "$REPO_ROOT"
|
|
|
|
# Validate JSON files
|
|
for jf in \
|
|
"$REPO_ROOT/.claude-plugin/plugin.json" \
|
|
"$REPO_ROOT/.codex-plugin/plugin.json" \
|
|
"$REPO_ROOT/plugins/marketplace.json"
|
|
do
|
|
if [[ ! -f "$jf" ]]; then
|
|
fail "$(basename "$jf") - not found"
|
|
continue
|
|
fi
|
|
if python3 -m json.tool "$jf" > /dev/null 2>&1; then
|
|
pass "$(basename "$jf") valid"
|
|
else
|
|
fail "$(basename "$jf") - invalid JSON"
|
|
fi
|
|
done
|
|
|
|
# Skill structure validation deferred to smoke-test.sh and validate-doc-release.sh (CI-active)
|
|
|
|
# Validate agents
|
|
agent_count=0
|
|
[[ -d "$REPO_ROOT/agents" ]] && agent_count=$(find "$REPO_ROOT/agents" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
if [[ $agent_count -gt 0 ]]; then
|
|
pass "Found $agent_count agents"
|
|
else
|
|
skip "No agents found (optional)"
|
|
fi
|
|
|
|
# Validate GOALS.yaml
|
|
if [[ -f "$SCRIPT_DIR/goals/validate-goals.sh" ]]; then
|
|
run_lane "GOALS.yaml validation" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "$(lane_log_file goals)" \
|
|
bash "$SCRIPT_DIR/goals/validate-goals.sh"
|
|
else
|
|
skip "GOALS.yaml validation (script not found)"
|
|
fi
|
|
|
|
# Validate documentation
|
|
if [[ -f "$SCRIPT_DIR/docs/validate-links.sh" ]]; then
|
|
run_lane "Doc link validation" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "$(lane_log_file doc-links)" \
|
|
bash "$SCRIPT_DIR/docs/validate-links.sh"
|
|
else
|
|
skip "Doc link validation (script not found)"
|
|
fi
|
|
|
|
# Skill count validation deferred to validate-doc-release.sh (CI-active, runs validate-skill-count.sh + sync-skill-counts.sh)
|
|
|
|
if [[ -f "$SCRIPT_DIR/docs/validate-goal-count.sh" ]]; then
|
|
run_lane "Doc goal count validation" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "$(lane_log_file doc-goal-count)" \
|
|
bash "$SCRIPT_DIR/docs/validate-goal-count.sh"
|
|
else
|
|
skip "Doc goal count validation (script not found)"
|
|
fi
|
|
|
|
# Validate token budgets (static, no CLI needed)
|
|
if [[ -f "$SCRIPT_DIR/skills/test-token-budgets.sh" ]]; then
|
|
run_lane "Token budget validation" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "$(lane_log_file token-budgets)" \
|
|
bash "$SCRIPT_DIR/skills/test-token-budgets.sh"
|
|
else
|
|
skip "Token budget validation (script not found)"
|
|
fi
|
|
|
|
# Validate artifact-consistency behavior (static, no CLI needed)
|
|
if [[ -f "$SCRIPT_DIR/skills/test-artifact-consistency.sh" ]]; then
|
|
run_lane "Artifact consistency behavior tests" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "$(lane_log_file artifact-consistency)" \
|
|
bash "$SCRIPT_DIR/skills/test-artifact-consistency.sh"
|
|
else
|
|
skip "Artifact consistency behavior tests (script not found)"
|
|
fi
|
|
|
|
# Validate OL integration fixture-only scripts (static, no real ol binary needed)
|
|
if [[ -d "$SCRIPT_DIR/ol-integration" ]]; then
|
|
for ol_test in "$SCRIPT_DIR"/ol-integration/*-ol-test.sh; do
|
|
[[ ! -f "$ol_test" ]] && continue
|
|
ol_name="$(basename "$ol_test" .sh)"
|
|
run_lane "$ol_name" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" "/tmp/${ol_name}.log" bash "$ol_test"
|
|
done
|
|
else
|
|
skip "OL integration tests (directory not found)"
|
|
fi
|
|
|
|
# Validate team-runner fixture scripts (static, no live runtime needed)
|
|
if [[ -d "$SCRIPT_DIR/team-runner" ]]; then
|
|
run_lane "Team runner fixture tests" "$RUN_ALL_STATIC_LANE_TIMEOUT_SECONDS" /tmp/team-runner-tests.log \
|
|
bash "$SCRIPT_DIR/team-runner/run-all.sh"
|
|
else
|
|
skip "Team runner tests (directory not found)"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# =============================================================================
|
|
# Tier 2: Smoke Tests (needs Claude CLI, fast)
|
|
# =============================================================================
|
|
if [[ "$TIER" == "--tier=2" ]] || [[ "$TIER" == "--tier=3" ]] || [[ "$TIER" == "--all" ]]; then
|
|
log "Tier 2: Smoke Tests"
|
|
|
|
if ! command -v claude &>/dev/null; then
|
|
skip "Claude CLI not available - skipping Claude load smoke"
|
|
else
|
|
# Test plugin loads
|
|
claude_load_log="$(lane_log_file claude-load)"
|
|
if run_with_timeout "$RUN_ALL_CLAUDE_HELP_TIMEOUT_SECONDS" "Claude CLI loads plugin" "$claude_load_log" \
|
|
claude --plugin-dir "$REPO_ROOT" --help; then
|
|
claude_load_status=0
|
|
else
|
|
claude_load_status=$?
|
|
fi
|
|
|
|
if [[ "$claude_load_status" -eq 124 ]]; then
|
|
report_lane_status "Claude CLI load smoke" "$claude_load_status" "$claude_load_log" "$RUN_ALL_CLAUDE_HELP_TIMEOUT_SECONDS"
|
|
elif grep -qiE "invalid manifest|validation error|failed to load" "$claude_load_log"; then
|
|
fail "Claude CLI failed to load plugin"
|
|
grep -iE "invalid|failed|error" "$claude_load_log" | head -3 | sed 's/^/ /'
|
|
elif [[ "$claude_load_status" -ne 0 ]]; then
|
|
report_lane_status "Claude CLI load smoke failed" "$claude_load_status" "$claude_load_log" "$RUN_ALL_CLAUDE_HELP_TIMEOUT_SECONDS"
|
|
else
|
|
pass "Claude CLI loads plugin"
|
|
fi
|
|
fi
|
|
|
|
# Run smoke-test.sh if exists
|
|
if [[ -f "$SCRIPT_DIR/smoke-test.sh" ]]; then
|
|
run_lane "smoke-test.sh" "$RUN_ALL_SMOKE_TIMEOUT_SECONDS" "$(lane_log_file smoke-test)" \
|
|
bash "$SCRIPT_DIR/smoke-test.sh"
|
|
fi
|
|
|
|
# Run Codex integration tests (requires Codex CLI)
|
|
if [[ -f "$SCRIPT_DIR/codex/integration/run-all.sh" ]]; then
|
|
if command -v codex &>/dev/null; then
|
|
log " Running Codex integration tests..."
|
|
run_lane "Codex integration tests" "$RUN_ALL_CODEX_INTEGRATION_TIMEOUT_SECONDS" /tmp/codex-tests.log \
|
|
bash "$SCRIPT_DIR/codex/integration/run-all.sh"
|
|
else
|
|
skip "Codex CLI not available - skipping Codex integration tests"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
fi
|
|
|
|
# =============================================================================
|
|
# Tier 3: Functional Tests (needs Claude CLI, slower)
|
|
# =============================================================================
|
|
if [[ "$TIER" == "--tier=3" ]] || [[ "$TIER" == "--all" ]]; then
|
|
log "Tier 3: Functional Tests"
|
|
|
|
if ! command -v claude &>/dev/null; then
|
|
skip "Claude CLI not available - skipping functional tests"
|
|
else
|
|
# Run explicit skill request tests
|
|
if [[ -d "$SCRIPT_DIR/explicit-skill-requests" ]]; then
|
|
log " Running explicit skill request tests..."
|
|
run_lane "Explicit skill request tests" "$RUN_ALL_FUNCTIONAL_LANE_TIMEOUT_SECONDS" /tmp/explicit-tests.log \
|
|
bash "$SCRIPT_DIR/explicit-skill-requests/run-all.sh"
|
|
fi
|
|
|
|
# Run natural language triggering tests
|
|
if [[ -d "$SCRIPT_DIR/skill-triggering" ]]; then
|
|
log " Running skill triggering tests..."
|
|
run_lane "Skill triggering tests" "$RUN_ALL_FUNCTIONAL_LANE_TIMEOUT_SECONDS" /tmp/triggering-tests.log \
|
|
bash "$SCRIPT_DIR/skill-triggering/run-all.sh"
|
|
fi
|
|
|
|
# Run claude-code unit tests
|
|
if [[ -d "$SCRIPT_DIR/claude-code" ]]; then
|
|
log " Running Claude Code unit tests..."
|
|
run_lane "Claude Code unit tests" "$RUN_ALL_FUNCTIONAL_LANE_TIMEOUT_SECONDS" /tmp/unit-tests.log \
|
|
bash "$SCRIPT_DIR/claude-code/run-all.sh"
|
|
fi
|
|
|
|
# Run release smoke tests (agents + skills)
|
|
if [[ -f "$SCRIPT_DIR/release-smoke-test.sh" ]]; then
|
|
log " Running release smoke tests..."
|
|
run_lane "Release smoke tests" "$RUN_ALL_RELEASE_SMOKE_TIMEOUT_SECONDS" /tmp/release-tests.log \
|
|
bash "$SCRIPT_DIR/release-smoke-test.sh"
|
|
fi
|
|
|
|
# Run integration tests (CLI commands, skill invocation, hook chain)
|
|
if [[ -d "$SCRIPT_DIR/integration" ]]; then
|
|
log " Running integration tests..."
|
|
for test_script in "$SCRIPT_DIR"/integration/test-*.sh; do
|
|
[[ ! -f "$test_script" ]] && continue
|
|
test_name="$(basename "$test_script" .sh)"
|
|
|
|
# Skip skill invocation tests if Claude CLI not available
|
|
if [[ "$test_name" == "test-skill-invocation" ]] && ! command -v claude &>/dev/null; then
|
|
skip "$test_name (claude CLI not available)"
|
|
continue
|
|
fi
|
|
|
|
# Skip CLI tests if Go not available
|
|
if [[ "$test_name" == "test-cli-commands" ]] && ! command -v go &>/dev/null; then
|
|
skip "$test_name (go not available)"
|
|
continue
|
|
fi
|
|
|
|
run_lane "$test_name" "$RUN_ALL_INTEGRATION_SCRIPT_TIMEOUT_SECONDS" "/tmp/${test_name}.log" \
|
|
bash "$test_script"
|
|
done
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
fi
|
|
|
|
# =============================================================================
|
|
# Summary
|
|
# =============================================================================
|
|
echo ""
|
|
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
|
|
total=$((total_passed + total_failed + total_skipped))
|
|
echo -e "Total: $total tests"
|
|
echo -e " ${GREEN}Passed:${NC} $total_passed"
|
|
echo -e " ${RED}Failed:${NC} $total_failed"
|
|
echo -e " ${YELLOW}Skipped:${NC} $total_skipped"
|
|
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
|
|
|
|
if [[ $total_failed -gt 0 ]]; then
|
|
exit 1
|
|
fi
|
|
exit 0
|