fix: feat: persist red-team cross-patterns in repo for continuity across runs (#853)

- Move CROSS_PATTERNS_FILE from /tmp/red-team-cross-patterns.jsonl to
  tools/red-team/cross-patterns.jsonl (repo-tracked path)
- Remove the reset (> file) at sweep start so patterns accumulate across runs
- Generate a SWEEP_ID (sweep-YYYYMMDD-HHMMSS) at sweep start and stamp
  each new entry with sweep_id for traceability
- Deduplicate on (pattern, candidate, result): entries already present in
  the file are skipped; intra-batch duplicates are also suppressed
- Create tools/red-team/ directory with .gitkeep
- Add mkdir -p guards in both scripts so the directory is created on first run

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
openhands 2026-03-16 12:39:39 +00:00
parent 3d8bbb0975
commit fe3a3d7d94
3 changed files with 35 additions and 6 deletions

View file

@ -11,7 +11,7 @@ INJECT="$REPO_ROOT/tools/push3-transpiler/inject.sh"
ATTACKS_OUT="$REPO_ROOT/onchain/script/backtesting/attacks"
PROGRESS_FILE="/tmp/red-team-sweep-progress.json"
MEMORY_FILE="$REPO_ROOT/tmp/red-team-memory.jsonl"
CROSS_PATTERNS_FILE="/tmp/red-team-cross-patterns.jsonl"
CROSS_PATTERNS_FILE="$REPO_ROOT/tools/red-team/cross-patterns.jsonl"
SWEEP_TSV="/tmp/sweep-results.tsv"
OPT_SOL="$REPO_ROOT/onchain/src/OptimizerV3.sol"
TIMEOUT_PER="${1:-3600}"
@ -22,9 +22,11 @@ die() { log "FATAL: $*" >&2; exit 1; }
[[ -f "$INJECT" ]] || die "inject.sh not found at $INJECT"
mkdir -p "$ATTACKS_OUT"
mkdir -p "$(dirname "$CROSS_PATTERNS_FILE")"
# Reset cross-patterns file for this sweep invocation (prevents stale data from prior runs)
> "$CROSS_PATTERNS_FILE"
# Generate a unique sweep ID for traceability across runs
SWEEP_ID="sweep-$(date -u +%Y%m%d-%H%M%S)"
log "Sweep ID: $SWEEP_ID"
# Load progress
completed=()
@ -217,11 +219,12 @@ PYEOF
# 4c. Extract abstract patterns into cross-candidate file, then clear raw memory
if [[ -f "$MEMORY_FILE" && -s "$MEMORY_FILE" ]]; then
set +e
_extract_out=$(python3 - "$MEMORY_FILE" "$CROSS_PATTERNS_FILE" <<'PYEOF'
_extract_out=$(python3 - "$MEMORY_FILE" "$CROSS_PATTERNS_FILE" "$SWEEP_ID" <<'PYEOF'
import json, sys
mem_file = sys.argv[1]
cross_file = sys.argv[2]
sweep_id = sys.argv[3] if len(sys.argv) > 3 else "unknown"
new_entries = []
with open(mem_file) as f:
@ -237,11 +240,36 @@ if not new_entries:
print("No memory entries to extract")
sys.exit(0)
# Load existing (pattern, candidate, result) keys for deduplication
existing_keys = set()
try:
with open(cross_file) as f:
for line in f:
line = line.strip()
if line:
try:
e = json.loads(line)
existing_keys.add((e.get("pattern", ""), e.get("candidate", ""), e.get("result", "")))
except Exception:
pass
except FileNotFoundError:
pass
appended = 0
skipped = 0
with open(cross_file, 'a') as f:
for e in new_entries:
key = (e.get("pattern", ""), e.get("candidate", ""), e.get("result", ""))
if key in existing_keys:
skipped += 1
continue
e["sweep_id"] = sweep_id
existing_keys.add(key) # prevent intra-batch duplicates
f.write(json.dumps(e) + '\n')
appended += 1
print(f"Extracted {len(new_entries)} entr{'y' if len(new_entries)==1 else 'ies'} to cross-patterns file")
total = appended + skipped
print(f"Extracted {appended} new entr{'y' if appended==1 else 'ies'} ({skipped} duplicate{'s' if skipped!=1 else ''} skipped) to cross-patterns file")
PYEOF
)
_py_exit=$?

View file

@ -26,7 +26,7 @@ REPORT_DIR="$REPO_ROOT/tmp"
REPORT="$REPORT_DIR/red-team-report.txt"
STREAM_LOG="$REPORT_DIR/red-team-stream.jsonl"
MEMORY_FILE="$REPO_ROOT/tmp/red-team-memory.jsonl"
CROSS_PATTERNS_FILE="/tmp/red-team-cross-patterns.jsonl"
CROSS_PATTERNS_FILE="$REPO_ROOT/tools/red-team/cross-patterns.jsonl"
ATTACK_EXPORT="$REPORT_DIR/red-team-attacks.jsonl"
ATTACK_SNAPSHOTS="$REPORT_DIR/red-team-snapshots.jsonl"
DEPLOYMENTS="$REPO_ROOT/onchain/deployments-local.json"
@ -581,6 +581,7 @@ PROMPT=${PROMPT//\{\{MEMORY_SECTION\}\}/$MEMORY_SECTION}
# ── 7. Create output directory and run the agent ───────────────────────────────
mkdir -p "$REPORT_DIR"
mkdir -p "$(dirname "$MEMORY_FILE")"
mkdir -p "$(dirname "$CROSS_PATTERNS_FILE")"
log "Spawning Claude red-team agent (timeout: ${CLAUDE_TIMEOUT}s)..."
log " Report will be written to: $REPORT"

0
tools/red-team/.gitkeep Normal file
View file