Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
*.sh text eol=lf
*.toml text eol=lf
# Benchmark fixture bytes are part of the independent oracle.
tests/fixtures/agent-loop-multi-file/*.txt text eol=lf

# Frontend freshness checks compare these generated assets byte-for-byte.
frontend/dist/** text eol=lf
Expand Down
79 changes: 78 additions & 1 deletion docs/experiments/agent-loop-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,15 @@ expectation.
The profiler includes a deterministic case fingerprint so changed case definitions
cannot silently compare as the same pair.

The corpus contains sixteen cases: ten coding/inspection cases and six general
The corpus contains seventeen cases: eleven coding/inspection cases and six general
file/command cases. The coding/inspection cases are:

- `readonly_review`: read-only status/read/search/diff inspection.
- `focused_edit_validation`: one focused edit, diff review, and successful
`cargo check`.
- `guarded_multi_file_edit`: search → selected reads → one guarded two-file edit →
post-edit reads/diff, with an independent fixture-side oracle for both changed
files and preserved unrelated sentinels.
- `failed_validation_recovery`: a deliberately failing `cargo test`, diagnostic
inspection, fix, and successful rerun.
- `long_validation_handoff`: real same-execution Job handoff and terminal
Expand Down Expand Up @@ -255,6 +258,79 @@ Runtime Project, Workflow Session, Window, tunnel, and host-internal identifiers
may be used transiently to select authoritative evidence. They must not be written
into the manifest, docs, tests, run annotation, or durable benchmark result.

## Reproducible paired benchmark command

`scripts/agent_loop_benchmark.py` is a thin orchestration layer over this existing
manifest and `agent_loop_report.py`. It does not contain another agent loop or a
benchmark-only WebCodex execution path. A caller-supplied Host driver performs the
real task using the ordinary Direct or Code Mode contracts. The orchestrator owns
only reproducibility mechanics:

- one fresh detached Git worktree per sample at one exact base revision;
- the requested base revision must equal the benchmark checkout's current `HEAD`, so the manifest, fixtures, and code under test come from one revision;
- the same case fingerprint/prompt/correctness definition for both variants;
- alternating pair order (`direct/code_mode`, then `code_mode/direct`) to expose
one-sided process/cache ordering effects;
- bounded annotation and the existing report/correctness compatibility gates;
- fixture-side disk/diff oracles where the manifest provides one; changed-path capture is bounded to 64 KiB / 512 paths, and the multi-file case additionally requires persisted evidence for one successful guarded edit plus its search/read phases;
- explicit `pass`, `fail`, `partial`, and `unsupported` samples. None are
silently filtered from the aggregate;
- non-unsupported `pass` requires non-empty canonical ActionAudit evidence and the audited execution lane must match the requested variant/surface (`direct`, `execute_code_mode`, `execute_effectful_code_mode`, or `execute_mutating_code_mode` as applicable); the read-only Code Mode lane additionally permits exactly one required `work_on_project` bootstrap and at most one `read_tool_manifest` contract-discovery call, but no Direct read/search fallback; Code Mode also requires complete persisted composition evidence; missing or mismatched capture is `partial`, never fabricated success;
- cleanup of only the worktrees/temp state created by the orchestrator, including targeted rollback of an owned worktree registration when checkout setup fails; no global `git worktree prune` is used;
- Host-driver process ownership currently uses POSIX process groups; Windows runs are retained explicitly as `unsupported` until equivalent descendant ownership can be guaranteed.

Example:

```bash
python3 scripts/agent_loop_benchmark.py \
--base-revision "$(git rev-parse HEAD)" \
--driver "python3 /path/to/real_host_driver.py" \
--pairs 2 \
--output /tmp/webcodex-agent-loop-benchmark.json
```

For each invocation the driver receives `WEBCODEX_BENCH_WORKSPACE`,
`WEBCODEX_BENCH_CASE_ID`, `WEBCODEX_BENCH_VARIANT`,
`WEBCODEX_BENCH_SURFACE`, `WEBCODEX_BENCH_BASE_REVISION`,
`WEBCODEX_BENCH_CASE_FINGERPRINT`, `WEBCODEX_BENCH_PROMPT`, and
`WEBCODEX_BENCH_DRIVER_RESULT`. It writes one bounded JSON receipt to the last
path. The receipt is capped at 64 KiB; malformed/decode-pathological JSON fails closed as a retained failed sample, and driver stdout/stderr is not retained by the orchestrator. `status` is required and is one of `pass/fail/partial/unsupported`. Relative `audit_db` and `trace_root` paths are resolved against the fresh sample workspace; absolute paths remain absolute.
Non-unsupported samples also provide the authoritative ActionAudit database path
and Workflow Session id; optional trace root, repair-turn annotation, and task timing
use the existing reporter semantics. Correctness verdicts are optional only when an
independent fixture oracle can establish the task result. For non-oracle cases, a
driver-reported pass needs `correctness.task_verdict="pass"`; validation-required
cases also need the corresponding passing validation verdict, otherwise the sample
remains partial. The durable benchmark result does not persist runtime Project,
Window, tunnel, Job, or Host-private ids. Job identity is correlated only through
the existing payload-safe salted ActionAudit relation; the benchmark driver does not
supply or certify a second Job-identity receipt.

The default lane is exactly `readonly_review`, `guarded_multi_file_edit`, and
`long_validation_handoff`, matching #822. The handoff case requires exactly one
`cargo_test` launch. Direct and Code Mode both require one canonical pending
relation, a correlated follow-up, and same-relation terminal timing from ActionAudit.
For Code Mode, the canonical ModelErgonomics producer derives that pending relation
from the nested `effect_receipt.children` Job handoff. The reporter joins that salted
relation internally and emits only payload-safe counts/timing grouped by the pending
origin tool. Continuity context may support the relation/timing join, but benchmark
success additionally requires the terminal evidence row itself to belong to the
selected ActionAudit run; for Code Mode that selected chain must originate from
`execute_effectful_code_mode`. Persisted composition must independently show exactly
one consequential validator handoff and no known or unknown substitute result. A
synchronous completion, redispatch, unrelated outer Job, uncorrelated/substitute
process, or pending without terminal evidence remains `partial`/`unsupported`,
never upgraded to success.
The guarded multi-file case is likewise not a pass from final bytes alone: persisted Direct canonical-call or Code Mode composition evidence must show exactly one `edit_project_files` call, at least one admitted search call, and at least two `read_files` calls (pre-edit and post-edit phases). Direct additionally requires the existing authoritative ModelErgonomics edit outcome to be exactly `applied`. Code Mode requires exactly one consequential known-result child, zero Job handoffs/outcome-unknown/nested failures, and the aggregate canonical mutation evidence to show one `state_changed=true` mutation and zero known no-change mutations, in addition to the fixture-side exact-byte oracle. A dry-run/no-op edit plus shell/process/write fallback therefore cannot be promoted to a pass. Current composition does not prove nested child ordering, so the benchmark does not claim stronger sequencing evidence than is persisted.

This command coordinates real captures; it is not itself evidence that a model made
fewer inference turns. Deterministic runtime/script acceptance and fixture oracles
prove runtime mechanics and final state. Direct-vs-Code Mode ergonomics require a
real Host/model capture. Exact model round trips remain unavailable unless the Host
records turn identity; meaningful outer calls remain only the documented proxy.
Report cold/warm context, pair order, sample count, and dispersion rather than
treating one run or one ordering as causal proof.

## Typed Surface v1 observed dogfood — 2026-09-18

A real self-hosted dogfood build from the Typed Surface v1 branch ran the three
Expand Down Expand Up @@ -302,6 +378,7 @@ trace-only input cannot apply `--workflow-session-id`.

Start each benchmark run with its fresh `work_on_project` bootstrap; that call
links its own ActionAudit row through the canonical `WorkOnProject` relation.
For `readonly_review`, the benchmark gate admits the one bootstrap plus at most one `read_tool_manifest` discovery call when the selected Code Mode callable contract is not already retained. That contract-discovery call is not Direct repository inspection; any outer `read_files`, search, or other fallback still fails the lane check closed.
Once the bootstrap returns the exact run Session id, every subsequent model-facing
outer call in the run must pass that id as `recording_session_id`. A business
`session_id` does not substitute for ActionAudit recorder provenance. Code Mode
Expand Down
Loading
Loading