hooks-compact Eval System

April 16, 2026 · View on GitHub

A comprehensive A/B regression testing framework for the hooks-compact module.

Overview

The eval system compares two Amplifier sessions for each test scenario:

  • Session A (with hook): amplifier run --bundle <behavior-url> — hooks-compact active
  • Session B (baseline): amplifier run — no compression, raw output

It measures:

  1. Compression quality — input/output chars, savings %
  2. Model performance — bash tool calls, LLM turns
  3. Regression signal — did compression cause the model to retry commands?
  4. Qualitative notes — did the model understand compressed output correctly?

PASS criteria: Session A makes ≤1 more bash calls than Session B. Regression = model retrying commands due to insufficient compressed output.


Quick Start

Local A/B Test (single scenario)

./eval/run-eval.sh git-status-dirty

Local A/B Test (all scenarios)

./eval/run-eval.sh --all

DTU-based A/B Test (isolated containers)

# Launch two containers (with + without hooks-compact)
DTU_A=$(amplifier-digital-twin launch eval/profiles/hooks-compact-with.yaml | jq -r .id)
DTU_B=$(amplifier-digital-twin launch eval/profiles/hooks-compact-without.yaml | jq -r .id)

# Run all test cases
RESULTS="eval/results/$(date +%Y-%m-%d-%H-%M)-dtu"
mkdir -p "$RESULTS"
./eval/dtu-run-eval.sh "$DTU_A" "$DTU_B" "$RESULTS" ~/.amplifier/hooks-compact/telemetry.db

# Cleanup
amplifier-digital-twin destroy "$DTU_A"
amplifier-digital-twin destroy "$DTU_B"

Analyze an existing session pair

python3 eval/analyze_ab.py \
  --scenario git-status-dirty \
  --session-a <uuid-a> \
  --session-b <uuid-b> \
  --session-a-dir ~/.amplifier/projects/<slug>/sessions/<uuid-a> \
  --session-b-dir ~/.amplifier/projects/<slug>/sessions/<uuid-b> \
  --telemetry-db ~/.amplifier/hooks-compact/telemetry.db

Run the simulation (no API calls)

python3 eval/simulate_all_filters.py

Files

FilePurpose
test-cases.yaml26 test cases across all filter categories
run-eval.shLocal A/B runner (uses amplifier run --bundle)
analyze.shAnalyze a specific session pair
analyze_sessions.pyCore metrics extraction from events.jsonl
analyze_ab.pyNEW — Improved analyzer with full table format + qualitative notes
simulate_all_filters.pyRun all 26 filters against real command output (no API)
dtu-run-eval.shNEW — DTU-based A/B runner using isolated containers
profiles/hooks-compact-with.yamlNEW — DTU profile: Container A (hooks active)
profiles/hooks-compact-without.yamlNEW — DTU profile: Container B (baseline)
recipes/dtu-ab-test.yamlNEW — Recipe orchestrating full DTU A/B test cycle

Output Format

| Scenario                     | Input (chars) | Output (chars) |  Savings | With Turns | Without Turns | With Calls | Without Calls | Verdict |
| git-status-dirty             |           491 |            154 |    68.6% |          2 |             2 |          1 |             1 |    PASS |

The analyze_ab.py produces this exact table plus:

  • Compression detail per command (from telemetry.db)
  • Bash commands list for both sessions
  • Token usage comparison
  • Qualitative notes on model behavior
  • PASS/FAIL verdict with reasoning

Simulation Results (All 26 Scenarios)

Run with python3 eval/simulate_all_filters.py. Uses real command output from actual projects. No API calls required.

ScenarioFilterInput (chars)Output (chars)SavingsNotes
git-status-dirtygit-status49115468.6%Live: 80.4% on larger dirty repos
git-diff-largegit-diff1,52875050.9%Live: 96.2% on 13KB diffs
git-loggit-log927926~0%Already compact (--oneline)
git-push-successgit-simple4243092.9%Short-circuits to branch ref
git-push-rejectedgit-simple44938713.8%Error lines preserved (correct)
git-commitgit-simple116114~0%Already minimal output
git-pullgit-simple47513272.2%Strips fetch noise
pytest-all-passpytest3402193.8%Live: 99.9% on 268 tests
pytest-failurespytest2,3321,33742.7%Tracebacks preserved
cargo-test-passcargo-test6111897.1%✓ 4 passed (0.00s)
cargo-test-failcargo-test1,12767440.2%Panic details preserved
npm-test-passnpm-test2271195.2%✓ 4 passing
npm-test-failnpm-test80170012.6%Mocha errors preserved
ruff-errorsruff1,62137876.7%Live: 83.4% on 16 violations
ruff-cleanruff19190%No violations = no compression (correct)
cargo-clippycargo-clippy84927268.0%Group-by-rule dedup
eslint-errorseslint65324362.8%Group-by-rule dedup
cargo-build-cleancargo-build1382085.5%ok (build succeeded)
cargo-build-errorscargo-build67523665.0%Error[E...] blocks preserved
tsc-errorstsc40118853.1%Error lines extracted
npm-build-successnpm-build1002080.0%ok (build succeeded)
pip-installpip (YAML)1,09139164.2%Progress bars stripped
brew-already-installedbrew (YAML)1008812.0%Small input, minimal savings
make-buildmake (YAML)136135~0%Simple Makefile, no noise to strip
docker-builddocker (YAML)1,07443459.6%CACHED/internal layers stripped
curl-verbosecurl (YAML)2,7151,52044.0%TLS handshake noise stripped

Key Design Principles

  • Asymmetric compression: All-pass → aggressive summary; failures → preserve details
  • Fail-safe: If filter errors, raw output passes through unchanged
  • Compound command guard: git status && git diff passes through (avoids over-compression)
  • Shell prefix stripping: cd /path && git status → strips cd /path && before matching
  • Tool wrapper prefixes: uvx, uv run, npx, poetry run, etc. stripped before matching

Live A/B Test Results

Sessions from live Amplifier runs (not simulation):

ScenarioSession ASession BInput (chars)Output (chars)SavingsWith TurnsWithout TurnsWith CallsWithout CallsVerdictQualitative
git-workflow74bc5c12e3dd920716,6371,83589%11151325PASSModel used 12 fewer bash calls — more efficient with compressed output
pytest (all pass)(session)(session)23,0382199.9%5522PASSIdentical behavior
pytest (failures)(session)(session)2,5201,52739.1%4411PASSError details preserved, model correctly identified failures
ruff (errors)(session)(session)4,12568683.4%5522PASSAll rule violations visible
git (compound)(session)(session)9729720%4411PASSCorrect passthrough of compound commands

DTU Setup

The DTU profiles provision full Amplifier environments for isolated A/B testing:

eval/profiles/hooks-compact-with.yaml:

  • Ubuntu 24.04
  • Amplifier installed
  • hooks-compact in bundle.app
  • Test fixtures pre-created (pytest fail file, Rust project, Node project)

eval/profiles/hooks-compact-without.yaml:

  • Same setup WITHOUT hooks-compact
  • Identical test fixtures for fair comparison

The DTU recipe (eval/recipes/dtu-ab-test.yaml) orchestrates the full lifecycle:

  1. Validate DTU available
  2. Create test fixtures
  3. Launch both containers
  4. Run all test cases in both
  5. Pull session data
  6. Analyze and report
  7. Cleanup containers

PASS/FAIL Criteria

CriterionThresholdRationale
Extra bash calls≤ 1Over-compression causes retries
Extra turns≤ 2Excessive turns indicate confusion
Compression (all-pass)≥ 80%Core value prop for successful runs
Compression (failures)≥ 0%Error details must be preserved

Adding New Test Cases

  1. Add to test-cases.yaml with id, prompt, working_dir, expected_commands
  2. Create any needed fixtures in /tmp/
  3. Run python3 eval/simulate_all_filters.py to verify filter output
  4. Run ./eval/run-eval.sh <your-test-id> for live A/B validation