* feat(gaia): pre-submission exploit audit + signed attestation (ADR-167) Motivated by UC Berkeley RDI's April-2026 finding that all 8 major agent benchmarks were gamed to ~98-100% without solving a single task (GAIA leaked ~98% of answers via public answer DBs + normalization collisions; o3/Claude-3.7 monkey-patch graders in 30%+ of runs per METR). Signing proves transport-integrity; this audit proves earning-integrity. The audit report is deterministic ($0, offline, pure-core) and is registered as an ADR-103 witness fix marker so its sha256 + "clean": true marker are signed INTO manifest.md.json. - ADR-167 (v3/docs/adr): threat model, check catalogue mapped to RDI/METR vectors, manifest-attestation design, honest harness-gap limitations. - gaia-audit.mjs: 7 pure checks (answer-leakage, no-work, oracle-leakage, grader-isolation, normalization-collision, voting-disclosure, split-integrity); CLI exit 0 clean / 1 CRITICAL / 2 usage. Schema-blocked checks return skip with a harness_gap note, never a false pass. - Tests: 27 passing; clean + dirty fixtures triggering every vector. - Wired --audit into /gaia validate; pre-sign gate into /gaia submit (refuses CRITICAL fail unless --allow-dirty) + gaia-submission skill. - Bump ruflo-workflows 0.4.0 → 0.5.0. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01V84YJJK7RBF9TuUo4eVSW7 * docs(adr): ADR-168 — GAIA harness evidence recording (implements ADR-167 §7 forward contract) Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-169 — benchmark reporting integrity standard (strict-EM headlines, view-labeled scaling, disclosed gaps) Codifies the discipline the FRAMES ablation self-audit measured against the Berkeley RDI vectors. Completes the integrity family: ADR-167 audits the submission, ADR-168 records the evidence, ADR-169 governs how numbers are reported. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(gaia): port static source-scan checks (AUD-8/9/10) into gaia-audit Ports the unique, non-overlapping checks from the reverted #2547 duplicate gaia-integrity.mjs into gaia-audit.mjs as a new static source-scan family, matching ADR-167's check-registry / status / harness_gap design: - AUD-8 answer-key-reads (CRITICAL, fail-closed): scans runner sources + produced artifacts for answer/gold/solution/ground-truth-shaped paths referenced outside the sanctioned dataset dir(s). - AUD-9 dynamic-eval (CRITICAL, fail-closed): static scan of the gaia-bench runner sources for eval()/new Function()/exec-family calls with a non-literal first arg. Preserves the #2547 false-positive refinements (multi-line aware, RegExp.prototype.exec excluded, fixed-string commands + comments ignored) — passes clean against ruflo's own multi-line `gcloud secrets … execSync`. - AUD-10 judge-injection (WARN): scans the agent's PRODUCED answer/outputs for judge-directed prompt-injection markers. Distinct from AUD-3 oracle-leakage (input-side gold-answer scan), so both run. Unlike AUD-1/3/4 these need no trajectory instrumentation — they enforce today and skip honestly (never false-pass) when the source population is absent (standalone/ejected run or --skip-source-scan). The #2547 provenance stamp and --allow-integrity-override are NOT ported: #2543's signed attestation and the `/gaia submit --allow-dirty` gate already own provenance + override, so the new checks flow through the same attestation.clean/strict_clean path. CLI adds --repo-root, --dataset-dir (repeatable), --skip-source-scan. Fixtures: planted evil runner (eval + interpolated exec), planted answer-key read, judge-injection results. Tests: 44 green (17 new). Docs: ADR-167 §3/§7 check table, gaia-validate.md, gaia-submission SKILL.md. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01S7GYqnVUVxBfZ5W8znqry3 * fix(ci): advance ruflo-workflows smoke version assertion to 0.5.0 The AUD-8/9/10 port bumped plugin.json to 0.5.0 but the plugin's own smoke step 1 still asserted 0.4.0 — the single failing step behind both smoke-all and the meta-smoke leg of smoke-without-metaharness on #2543. Co-Authored-By: RuFlo <ruv@ruv.net>
6.5 KiB
name, description, argument-hint
| name | description | argument-hint |
|---|---|---|
| gaia-validate | Pre-submit validation — TypeScript clean, dataset accessible, all required env keys present | [--strict] [--fix] |
/gaia validate
Run pre-submission integrity checks before executing a benchmark or packaging results for the HAL leaderboard.
Usage
/gaia validate
/gaia validate --strict
/gaia validate --fix
Options
| Flag | Default | Description |
|---|---|---|
--strict |
off | Fail on warnings (not just errors); with --audit, also fails on WARN audit findings |
--fix |
off | Attempt to auto-fix resolvable issues (e.g., install missing deps) |
--skip-hf |
off | Skip the HF dataset connectivity check (useful offline) |
--skip-build |
off | Skip the TypeScript build check |
--audit |
off | Run the pre-submission exploit audit (ADR-167) when a results file exists |
Checks performed
1. Environment keys
ANTHROPIC_API_KEY— required for model inferenceHF_TOKEN— required to download the GAIA dataset from Hugging FaceGOOGLE_AI_API_KEY— optional; warn if absent (Gemini model support disabled)GOOGLE_CUSTOM_SEARCH_API_KEY+GOOGLE_CUSTOM_SEARCH_CX— optional; warn if absent (web_search falls back to DuckDuckGo)
2. TypeScript build
cd v3/@claude-flow/cli && npx tsc --noEmit
All GAIA benchmark source files must be TS-error-free.
3. Dataset accessibility
Perform a dry-run fetch of 1 question from the HF GAIA dataset to confirm the token and network path work.
4. Witness manifest
Verify the witness manifest is up to date and valid:
node plugins/ruflo-core/scripts/witness/verify.mjs
5. Benchmark source files present
Confirm all required benchmark source files exist:
v3/@claude-flow/cli/src/commands/gaia-bench.tsv3/@claude-flow/cli/src/benchmarks/gaia-agent.tsv3/@claude-flow/cli/src/benchmarks/gaia-judge.tsv3/@claude-flow/cli/src/benchmarks/gaia-loader.tsv3/@claude-flow/cli/src/benchmarks/gaia-tools/index.ts
6. CLI binary resolvable
node v3/@claude-flow/cli/bin/cli.js --version
7. Submission integrity (exploit audit) — ADR-167
Only runs when --audit is passed and a results file is available
(default ~/.cache/ruflo/gaia/results-latest.json). Motivated by UC Berkeley
RDI's April-2026 finding that all 8 major agent benchmarks — GAIA included —
were gamed to ~98-100% without solving any task (GAIA leaked ~98% of answers
via public answer DBs + normalization collisions; o3/Claude-3.7 monkey-patch
graders in 30%+ of runs, per METR).
Signing proves the bytes are untampered; this audit proves the score was earned. It is a deterministic, $0, offline red-team of the known reward-hacking vectors:
node plugins/ruflo-workflows/scripts/gaia-audit.mjs \
--results ~/.cache/ruflo/gaia/results-latest.json \
--trajectories <submission>/trajectories.jsonl \
--metadata <submission>/metadata.json \
[--repo-root <dir>] [--dataset-dir <dir>]... [--skip-source-scan]
| Check | Severity | RDI/METR vector |
|---|---|---|
| answer-leakage | CRITICAL | gold answer appears in a fetched tool output (GAIA's #1 vector) |
| no-work-pass | CRITICAL | correct with zero turns / zero output tokens / no LLM call |
| oracle-leakage | CRITICAL | gold answer present in the agent-visible input prompt |
| grader-isolation | CRITICAL | tool call targets judge/grader/witness paths (monkey-patching) |
| normalization-collision | WARN | degenerate/generic answer credited under aggressive normalization |
| voting-disclosure | WARN | hidden best-of-N not disclosed in metadata |
| split-integrity | WARN/INFO | validation-split (public gold) presented as held-out |
| answer-key-reads | CRITICAL | answer/gold/solution/ground-truth-shaped path read outside the sanctioned dataset dir (runner sources + produced artifacts) |
| dynamic-eval | CRITICAL | eval() / new Function() / exec of a non-literal (task-derivable) command in the gaia-bench runner sources |
| judge-injection | WARN | prompt-injection markers in the agent's produced answer/output aimed at the LLM judge |
The last three form the static source-scan family (ported from the reverted
#2547 duplicate): they scan the harness sources + produced artifacts rather than
the trajectory, so they enforce today with no instrumentation. answer-key-reads
and dynamic-eval are fail-closed; both skip (never false-pass) when the
runner sources cannot be located (e.g. run standalone) or under
--skip-source-scan. --repo-root overrides where the runner sources are found;
--dataset-dir (repeatable) sets the sanctioned dataset dirs (default
~/.cache/huggingface, ~/.cache/ruflo/gaia/dataset). dynamic-eval is tuned
to pass ruflo's own multi-line gcloud secrets … execSync calls (fixed-string
commands and RegExp.prototype.exec are not flagged). judge-injection is
output-side and distinct from oracle-leakage (input-side), so both run.
Exit 0 clean · exit 1 on any CRITICAL fail (or WARN fail under --strict) ·
exit 2 usage error. Checks whose data the trajectory schema does not yet
capture return skip with a harness_gap note (see ADR-167 §7) — they never
report a false pass.
Expected output
Validating GAIA benchmark environment...
[PASS] ANTHROPIC_API_KEY set (sk-ant-...abc3)
[PASS] HF_TOKEN set (hf_...xyz9)
[WARN] GOOGLE_AI_API_KEY not set — Gemini routing disabled
[WARN] GOOGLE_CUSTOM_SEARCH_API_KEY not set — web_search using DuckDuckGo fallback
[PASS] TypeScript build clean (0 errors)
[PASS] HF dataset reachable (1 question fetched)
[PASS] Witness manifest valid (Ed25519 verified)
[PASS] All 5 benchmark source files present
[PASS] CLI binary resolves to v3.6.x
2 warnings (use --strict to fail on warnings)
Ready to run /gaia run
Steps Claude should follow
- For each env var, check
process.envfirst, then attemptgcloud secrets versions access latest --secret=<name>silently. - Run
npx tsc --noEmitin the CLI package directory; capture stderr. - Run a 1-question dry-run fetch:
node … gaia-bench run --smoke-only --limit=1 --dry-run. - Run the witness verify script.
- If
--auditis set and a results file exists, runplugins/ruflo-workflows/scripts/gaia-audit.mjs(ADR-167); treat a CRITICAL audit failure as an error and a WARN failure as a warning. - Print the validation table and exit with code 1 if any errors (not warnings)
are found, unless
--strictis set in which case warnings also cause exit 1.