SuperAPI AI Directory

harness-trace

Agents & models

View repository

Updated 10-16 06:45

About this skill

ABOUTME: Structured execution trace capture and token baselining for claude-forge ABOUTME: Extracts traces from session JSONL, counts tokens with tiktoken, generates baselines Harness Trace

Structured execution trace capture and token baselining for the claude-forge harness. Based on Meta-Harness (arxiv 2603.28052): measure before optimizing.

Quick Start

cd skills/harness-trace

# Install
uv sync

# Extract traces from a session JSONL
uv run -- harness-trace extract ~/.claude/projects/PROJECT/SESSION.jsonl
Count tokens in harness files

uv run -- harness-trace count-tokens rules/

Generate full baseline

uv run -- harness-trace baseline --base-dir /path/to/claude-forge


## Commands

| Command | Purpose | Output |
|---------|---------|--------|
| `extract <session.jsonl>` | Parse session into trace JSONL | Trace entries (stdout or file) |
| `count-tokens <path>` | Count tokens per file | Token counts per file |
| `baseline --base-dir <dir>` | Full harness token baseline | TSV with tier classification |

## Extraction strategy

`extract` uses two signal sources, in order of precision:

1. **Tool-use blocks** (primary, high precision). Walks every `tool_use` block in the assistant messages, then resolves outcomes from the paired `tool_result` blocks (matched by `tool_use_id`) in the user messages:

   | Tool / pattern | Emits |
   |----------------|-------|
   | `Agent(subagent_type=*-reviewer)` | `ROUTE` + `REVIEW`; findings parsed from the reviewer's returned report (section-style `### MAJOR` + one bullet per finding, or explicit `MAJOR: 1` counts) |
   | `Agent(subagent_type=*)` (non-reviewer) | `ROUTE` |
   | `Bash` matching `pytest\|make test\|go test\|npm test\|cargo test\|rspec` | `VERIFY`, `tests_pass` resolved from the result |
   | `Bash` matching `make check` | `VERIFY`, `lint_clean` resolved from the result |
   | `Bash` matching `ast-grep\|sg --pattern` | `BLAST_RADIUS` |
   | `Edit` / `Write` / `MultiEdit` | counted into `IMPLEMENT` aggregate |
   | `WebFetch` to `arxiv\|docs` | `RESEARCH` |
   | `AskUserQuestion` | counted into `safety_compliance.hitl_gates_hit` |

   Outcome resolution is fail-safe: a result that never arrives (truncated session, async agent) or says nothing about an axis leaves it unknown; failure markers in output override a clean exit (`pytest || true` chains); counts are never fabricated from prose.

2. **Text regex** (fallback). Applied only to messages whose tool stream did not already surface the step, and only for steps that are typically pure text (`SCORE`, `FIX`, `LOOP`, `UAT`, plus `VERIFY`/`REVIEW` when no tool signal exists). This avoids the v1 problem where prose like "tests pass" in a chat triggered fake VERIFY entries.

`SUMMARY` is always synthesized last from JSONL aggregates: `duration_min` (last_ts - first_ts), `files_changed` (Edit+Write count), and the 6-dimension `metrics` object (paper §5.2.1). No `SUMMARY` is emitted for sessions with zero other entries.

## Trace Schema (v2)

One JSONL line per orchestrator step. `v2` adds `rejected_alternatives` (top-level, attaches to any step), two new step types (`PERMISSION_EVENT`, `ROUTE`), and an end-of-task `metrics` mini-report inside `SUMMARY`. Based on "Code as Agent Harness" (arxiv 2605.18747 §3.5.1, §5.2.1).

**Step taxonomy.** `step` mixes two kinds intentionally:
- **Lifecycle phases** (`REFINE`, `RESEARCH`, ..., `SUMMARY`): at most once per round, sequential.
- **Cross-cutting events** (`PERMISSION_EVENT`, `ROUTE`): fire opportunistically, possibly many per phase. Consumers that care about the distinction should filter by step name.

```jsonl
{"v":2,"session":"slug","ts":"ISO8601","step":"STEP","data":{...},"rejected_alternatives":[...]}
Step Data fields
REFINE ambiguities_found, questions_asked
RESEARCH complexity, sources_consulted
LOCALIZE files_planned, files_proposed, files_actually_changed, precision, recall, mismatches
REPRODUCE script, fails_before_fix, passes_after_fix
IMPLEMENT agents, files_changed, subtask_count, localization_precision
DRIFT_CHECK subtask_id, verdict, deviations
VERIFY tests_pass, lint_clean, build_ok (each tri-state: true/false/null, null = unknown), retries, reproduction_confirmed
REVIEW agents, findings (CRITICAL/MAJOR/MINOR), review_validity
FIX findings_addressed, deviations
BLAST_RADIUS triggered, trigger_reason, files_scanned, contradictions
SCORE score, threshold, gate
LOOP round, total_rounds, exit_reason
UAT performed, items, passed, failed
SUMMARY tokens_in/out, model, duration, final_score, metrics (v2)
PERMISSION_EVENT (v2) tool, action, outcome (granted/denied/denied_by_settings/auto_approved/error/timeout/bypassed), reason. Callers must redact secrets in action.
ROUTE (v2) router, target, alternatives_considered, decision_basis

v2 cross-cutting fields

  • rejected_alternatives (top-level on TraceEntry): list of {description, reason_rejected, cost_estimate?}. Captures paths the agent considered but discarded. Useful for diagnosing decision quality without rerunning the agent.

v2 SUMMARY.metrics (6 harness dimensions, paper §5.2.1)

Each dimension is an optional dict; populate only what was measured. None = not measured (do not infer 0).

Dimension Suggested keys
trajectory_efficiency tool_calls, tokens, edits, executions, active_min (gap-clamped working time, paired with SUMMARY.duration_min calendar span)
verification_strength test_coverage_pct, oracles_count, false_accept_rate
recovery_ability failures, recovered, escalations
state_consistency memory_repo_synced, drift_detected
safety_compliance permission_denials, hitl_gates_hit, sandbox_used
replayability full_trace_captured, artifacts_persisted

Token Baseline TSV

file	tokens	words	lines	tier	loaded
rules/orchestrator-protocol.md	1247	450	67	rule	always
skills/golang/SKILL.md	2890	1050	145	skill	on-demand

Tiers: rule (always-on), skill/skill-ref (on-demand), agent (on-demand), config (always-on).

Common Issues

Issue Solution
VERIFY outcomes all null Session predates outcome capture, or results truncated: re-extract from the raw session JSONL with the current extractor
REVIEW findings {} despite a visible report Async-launched reviewer (metadata-only tool_result): the report never passed through the Agent result; expected, not a bug
No SCORE entries Step 6 must report SCORE: <n>/100 literally (rules/orchestrator-protocol.md, Score Reporting)
Extraction slow or hangs Session over ~500 MB or malformed JSONL: check file size, extractor scans bounded windows of tool output by design

Architecture

src/harness_trace/
  models.py         <- Pydantic trace schema (TraceEntry, step data models)
  extractor.py      <- Session JSONL -> trace JSONL (heuristic parser)
  token_counter.py  <- tiktoken counting, directory scanning, TSV generation
  cli.py            <- CLI entry point (extract, count-tokens, baseline)
tests/              <- pytest suite