This experiment provides a repeatable measurement baseline for comparing a real coding-agent run that uses Direct Tools with a run of the same task through Code Mode. It measures facts already recorded by WebCodex plus an optional bounded run-annotation sidecar. It does not infer model reasoning, intent, private chain-of-thought, or unrecorded tool arguments.
The deterministic scripts/eval_coding_loop.sh
harness remains responsible for runtime mechanics. This protocol extends that
existing Agent Loop baseline; it does not create a second benchmark or reporting
framework.
The Typed Surface v1 dogfood lane asks whether a typed callable/result surface changes actual task throughput without weakening correctness. The paired report is designed to expose whether Code Mode uses fewer meaningful model-facing outer calls (a round-trip-pressure proxy, not an exact model-turn count), incurs fewer avoidable contract repairs, keeps more mechanical work inside one cell, and compresses nested raw results into a smaller returned projection.
A lower call count is not a correctness verdict. A Direct/Code Mode comparison is decision-relevant only when both runs use the same exact case definition and 40-hex Git base and both satisfy the case correctness/validation gate. The report never emits a winner, score, or overall ranking.
New Code Mode samples identify the actual experimental surface as read_only,
validation, or guarded_edit. They are not pooled under a generic code_mode surface.
For schema-v1 replay, the reporter still accepts the historical e1 / e2a / e2b
aliases without rewriting the original case object or its fingerprint.
The profiler is scripts/agent_loop_report.py.
It accepts the following evidence sources:
- ActionAudit SQLite is the preferred source for outer tool calls. Select one
run with an exact Workflow Session id. Existing rows provide the hashed
ClientWindow, canonical meaningful classification, request-observed and response-handoff timestamps, serial/overlap classification, status, tool identity, andmodel_ergonomicsmetadata including serializedToolResultbytes. Code Mode outer rows also persist the payload-safecode_mode_compositionsummary: nested call/success/failure counts, nested tool distribution, maximum in-flight calls, consequential outcome counters, slot wait/internal duration, and nested/raw versus returned byte counts. - Per-trace
events.jsonlis an optional supplement for observed Runner enqueue events. The profiler reads only JSONL metadata; it never opens captured request/result payload files. - Run annotation JSON is optional and independent of ActionAudit. It records only bounded categorical facts needed when runtime metadata cannot prove them: repair-turn counts/reasons, explicit task start/end timestamps, and final correctness/validation verdicts. It stores no prompt completion, chain of thought, command, file content, credential, deployment identity, Project id, Workflow Session id, ClientWindow, tunnel id, or instance id.
Current WEBCODEX_TOOL_REQUEST_TRACE=true/metadata capture persists bounded
per-trace events.jsonl, including observed Runner request correlation and MCP
request-policy selection. Pass that directory with --trace-root; full capture
is not required and the profiler never opens raw payload blobs. Historical
journal-only metadata captures are not backfilled. A missing trace root makes
Runner-request metrics unavailable, not zero.
The deterministic coding-loop harness uses /api/tools/call; it is not an MCP
or Codex Apps client benchmark. Its canonical edit name is edit_project_files.
For live Agent comparisons record the connection path (Apps, direct MCP or native),
Host mode and model configuration separately; a Server manifest cannot prove which
schemas a Host loaded. See MCP client contracts.
The opt-in generic runtime verifier
requires case-specific actual runtime proof and the independent final-file
oracle for all six generic cases. It binds a successful path bootstrap to the
coordinator's exact fixture root, Session and Project. Bootstrap-only audits,
arbitrary/no-op scripts and driver-declared passes cannot qualify. Schema-2
proof must match the sample's fixture identity; old results remain readable
without automatically receiving new strict acceptance. host_code_mode is
an explicit candidate lane; the existing nested Code Mode default is unchanged.
Missing/unprovable evidence remains partial, including unsupported baseline CSV
output receipts. See the linked contract for the controlled script/structured
edit paths and disposable full-capture requirements.
Session-filtered counts cover only calls linked to that exact Session. Discovery
or rejected bootstrap calls made before a Session is selected can be unlinked.
An explicit business session_id also does not select the outer recorder: a
successful tool can write business Session events without a canonical ActionAudit
recording link. For recorder coverage, the Host must supply the authorized
_wc.record on relevant MCP invocations; see the Session model.
Unlinked calls are not retroactively attributed by time, Project or apparent
intent. Keep their Host observations separately when available. A Session-scoped
call count does not establish the complete conversation's call count or model turns.
Trace persistence is fail-open observability, so runner.requests_observed means
exactly that: enqueue records observed in the supplied trace tree. The report does
not claim that the trace tree is a complete Runner-request ledger.
For newly observed successful outer read_files and observe_jobs calls, the
optional additive model_ergonomics.output_transfer record holds counts and
UTF-8 text/log-tail byte totals from the final model-visible result. It
never persists file paths, Job identifiers, text, logs, or content hashes.
read_files: items, rendered text bytes, and the item/byte subset containing identical text from the same path within one returned batch. This does not detect duplicates across independent calls, and repeated text can be intentional.observe_jobs: number of baseline, delta, reset and unchanged observations, with the returned stdout/stderr tail bytes split by category. A reset tail may be necessary for recovery and is not automatically wasteful duplication.
The offline profiler's output_transfer section summarizes only the exact
outer calls that carry complete numeric evidence. It reports call counts,
measured counts, sample/missing counts, and nullable totals. Historical
ActionAudit rows, malformed/failed observations and trace-only evidence do
not become zero-valued measurements. Code Mode nested child transfers are
not individually measured by these outer-call counters.
These figures are a diagnostic for deciding whether further compression
is warranted. They are raw UTF-8 tail/text bytes rather than full serialized
JSON, HTTP bytes, tokens, model turns or end-to-end latency; compare them
alongside existing results.serialized_tool_result_bytes.
A repair turn is a model turn whose primary purpose is to correct a previous avoidable tool-contract, callable-surface, argument-shape, or result-field-use error. Typical examples are a wrong argument shape, attempting an unavailable callable, reading the wrong result projection field, a JavaScript runtime error caused by surface misuse, or a follow-up that repairs the preceding tool selection.
The following are not repair turns: a normal search-then-read decision, ordinary adaptive branching after new business information, fixing business code after a real validation failure, or normal Job continuation.
ActionAudit does not prove that semantic distinction. The profiler therefore never classifies repair turns from model text, tool payloads, or chain-of-thought. Repair counts come only from the optional sidecar using this intentionally small vocabulary:
invalid_argumentsunknown_callablewrong_result_shapejavascript_runtimetool_selection_repairother_contract_repair
The sidecar schema is version 1 and rejects unknown fields. Example:
{
"schema_version": 1,
"case_id": "<case-id>",
"variant": "<direct-or-code_mode>",
"surface": "<direct-or-read_only-or-validation-or-guarded_edit>",
"base_revision": "<40-hex-base>",
"case_fingerprint": "<64-hex-case-sha256>",
"repair_turns": {
"total": 1,
"by_reason": {
"invalid_arguments": 1
}
},
"task_timing": {
"started_at_ms": 1000,
"ended_at_ms": 1700
},
"correctness": {
"task_verdict": "pass",
"validation_verdict": "not_required"
}
}repair_turns, task_timing, and correctness are individually optional.
Missing sections stay unavailable; they are never coerced to zero. The identity
fields are required so the sidecar cannot be accidentally attached to another
case definition, variant, surface, or Git base. case_fingerprint must match the
exact deterministic fingerprint emitted by the benchmark metadata.
A practical flow is to summarize once without --run-annotation, copy the emitted
benchmark.case_fingerprint into the sidecar, then rerun the same summary with the
annotation attached.
task_wall_time_ms is reported only when the sidecar contains both explicit
independent task start and task end timestamps. observed_span_ms is never used
as a substitute.
For a non-streaming outer call i, WebCodex-owned service time is:
service_i = response_handed_at_i - request_observed_at_i
For two continuity-eligible, meaningful calls in the same hashed Window and principal, a canonical serial transition permits:
outside_webcodex_gap_i = request_observed_at_(i+1) - response_handed_at_i
The latter may include model inference, host scheduling, network delay, UI delay,
or user delay. It must not be named model_think_time or reasoning_time.
Non-meaningful calls do not consume the meaningful predecessor. When a report is
scoped to one Workflow Session or trace set, the profiler privately replays
same-Window/same-principal meaningful ActionAudit rows across the selected span so
an interleaved call outside the selection cannot be skipped over. Such context
rows never contribute call/tool/failure counts; if the real canonical predecessor
is outside the selection, that selected gap remains unavailable. Overlap is counted
separately and never converted into a negative gap. Streaming handoff does not
prove response completion. Continuity breaks remain missing evidence.
observed_span_ms is only the span covered by observed WebCodex outer-call
timestamps. It is not end-to-end task wall time.
Percentiles use deterministic nearest-rank semantics. For metrics with partially
missing samples, observed_total and sample counts remain visible, while total
is null; missing evidence is never substituted with zero.
The offline Agent Loop report now groups the existing ActionAudit
model_ergonomics.serialized_result_bytes by its already-exposed outer
tool name under results.serialized_tool_result_bytes_by_tool.
Each tool receives its observed byte sum, available/missing call counts and
deterministic nearest-rank p50/p95. Its total remains null if any
selected call has missing, invalid or pre-result evidence; a complete tool
remains usable even if another tool's evidence is incomplete.
availability.serialized_tool_result_bytes_by_tool reports overall
coverage and the number of outer calls without a tool name.
Use only fully measured groups (missing=0) when ranking output-volume
candidates for follow-up profiling. Missing tool names remain unattributed
rather than being guessed from raw traces. Trace-only evidence returns
an unavailable empty breakdown. This measure is the serialized model-facing
ToolResult projection, excluding HTTP envelopes, model tokens, unrelated
transport traffic, and nested Code Mode child results. It does not identify
repeated text across calls or establish any end-to-end latency improvement.
No runtime telemetry, tool schema or returned content is changed.
scripts/agent_loop_cases.json is the
authoritative case manifest. Each run starts from a fresh clean target at an exact
Git base revision. Direct, Host Code Mode, and Code Mode runs must use the same
case id, exact 40-hex base revision, prompt/correctness definition, and validation
expectation.
The profiler includes a deterministic case fingerprint so changed case definitions
cannot silently compare as the same pair.
The controlled-lane corpus contains seventeen cases: eleven coding/inspection cases
and six general file/command cases. Six additional tool_selection cases use
task-language prompts without prescribing an execution lane. The controlled
coding/inspection cases are:
readonly_review: read-only status/read/search/diff inspection.focused_edit_validation: one focused edit, diff review, and successfulcargo 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 failingcargo test, diagnostic inspection, fix, and successful rerun.long_validation_handoff: real same-execution Job handoff and terminal observation when the validation actually hands off.independent_observations: independent status/diff/search/read observations, intended to expose meaningful-outer-call reduction and actual child concurrency.adaptive_search_read: search first, then read only the result-dependent target ranges.native_batching_observations: several related reads and searches that have a natural native batch shape.result_shape_pressure: structured search-match output followed by a targeted read, exercising layered success/output/optional result fields without telling the model that field access is the subject of the test.known_business_failure: a safe expected missing-file result followed by the normal README fallback, distinguishing ordinarysuccess=falsebusiness behavior from host/protocol/JavaScript failure.compact_projection: larger child read evidence distilled into exactly three concise final facts.
The general cases are:
generic_mixed_files_conflict: copy mixed files, preserve inputs and a destination conflict, and independently verify bytes/hashes and file counts.generic_encoded_csv: reconcile encodings/columns and independently verify the actual CSV rows, statistics and output receipts.generic_failure_repair: inspect an intentional nonzero exit and repair it; expected business failures are not contract-repair turns.generic_pending_independent_join: do independent work before one readiness join, then observe the original interactive Job without redispatch.generic_stale_read_revision: reject a stale edit, reread, and preserve an external writer's exact bytes through successful recovery.generic_missing_output: verify that a declared missing output blocks closeout; this expected negative case requires the output-receipt contract.
The coding fixture cases reuse the disposable Rust project recipe already owned
by eval_coding_loop.sh; general cases reuse the fixture recipes in
e2e_generic_agent_ws.py. This protocol does not create a second runtime harness.
Read-only WebCodex-repository cases must leave the workspace clean.
The generic manifest entries specify preparation and independent checks. Real
stale-edit replay requires an operator write after the model's first read; do not
silently substitute a model-issued write. The scripted driver is deterministic
runtime acceptance, not a real ChatGPT sample. See
General Agent experience for the implementation,
replay protocol and observed acceptance results.
The corpus records an expected code_mode_surface for every current case:
read-only cases use read_only, the long validation/Job case uses validation,
and edit-oriented cases use guarded_edit with validation outside the mutating
cell where needed. The parser keeps code_mode_surface and dogfood_focus
optional for historical schema-v1 manifest compatibility, but a current case that
declares a surface rejects a Code Mode run labeled with another surface.
For one case, Direct, Host Code Mode, and Code Mode runs must satisfy all of these constraints:
- same exact case definition and 40-hex Git base revision;
- fresh clean workspace for each run;
- same user task prompt and correctness expectations;
- Direct uses
guidance_profile=direct; - Host Code Mode uses
guidance_profile=host_code_modeand is reported asvariant=host_code_mode,surface=host_code_mode; - Code Mode uses
guidance_profile=code_mode; - new Code Mode captures record
surface=read_only,validation, orguarded_editexplicitly; historical schema-v1e1/e2a/e2blabels remain replay-compatible aliases; - the only intended experimental variable is the guidance/surface behavior being evaluated.
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.
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, thencode_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, andunsupportedsamples. None are silently filtered from the aggregate; - non-unsupported
passrequires non-empty canonical ActionAudit evidence and the audited execution lane must match the requested variant/surface (direct,execute_code_mode,execute_effectful_code_mode, orexecute_mutating_code_modeas applicable); the read-only Code Mode lane additionally permits exactly one requiredwork_on_projectbootstrap and at most oneread_tool_manifestcontract-discovery call, but no Direct read/search fallback; Code Mode also requires complete persisted composition evidence; missing or mismatched capture ispartial, 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 pruneis used; - Host-driver process ownership currently uses POSIX process groups; Windows runs are retained explicitly as
unsupporteduntil equivalent descendant ownership can be guaranteed.
Example:
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.jsonFor 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.
The paired benchmark JSON also includes paired_delta_summary per case.
It aggregates only pairs whose Direct and Code Mode reports passed the existing
same-case/base and correctness/validation throughput gates. For task wall
time, model-visible outer-call count (outer_calls.total), serialized
ToolResult bytes, and annotated contract-repair turns, it reports the
candidate-minus-Direct delta count, observed sum, and deterministic nearest-rank
p50/p95. Each metric includes qualified-sample and missing counts; incomplete
metrics have total=null, and cases with no qualified pairs never report a
fabricated zero. The human summary prints the qualified pair count and a
task-wall p50 delta only when all qualified pairs have timing evidence.
These descriptive aggregates are not a causal speedup estimate, complete
HTTP/token measurements, or exact model-turn counts. Use paired sample order,
correctness, and end-to-end Host evidence before recommending defaults.
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.
The six selection_* cases in the same manifest measure task outcomes while
allowing any admitted mix of Direct tools, native batches, Host Code Mode, and
experimental WebCodex Code Mode. Native batching is an invocation shape, not a
fourth execution surface. These cases use experiment=tool_selection and the
report variant/surface tool_selection. They cannot be relabeled as controlled
Direct/Code Mode cases. The original forced-lane runtime evidence gates remain
unchanged.
selection_single_read: obtain one exact fixture value and preserve files.selection_batch_read: reconcile two fixture values and preserved sentinels.selection_cross_tool_review: inspect Git state and locate the current query matching implementation, without prescribing tools or a preferred conclusion.selection_compound_source_context: locate match-derived source-context reads, explain overlap coalescing with read/byte-budget qualifications and zero-match behavior, and cite current implementation and tests without prescribing tools.selection_failed_test_recovery: observe the deliberately failing isolated Rust fixture, repair its implementation, retain its test, and verify success.selection_session_recovery: save a decision/progress note, then explicitly recover the same Session in a second real ChatGPT Web conversation.
The intentionally failing Rust fixture has its own workspace and is not a production workspace test. The driver must verify the initial failed test and final passing test independently. A matching final file alone does not prove that a model observed the failure, selected useful tools, or recovered a Session. Unlike old exact-edit fixtures, a successful file oracle never supplies the free selection task verdict: the driver must provide independent answer/workflow correctness. A receipt verdict is an external annotation, not automatic proof that an answer is true. Retain the actual final answer and a separate check against source at the exact tested revision; for repository review also check actual Git state. The compound source oracle checks that the fixture contains the relevant implementation/tests, not that the model found or explained them. Missing correctness leaves a sample partial. Missing canonical Audit metadata cannot satisfy strict selection acceptance even when the driver declares pass. Tool counts prove neither correctness nor unnecessary reads.
The default selection suite contains the first four cases above. Any admitted tool mix is permitted: sufficient context returned by a compound operation needs no redundant follow-up read, and separate search/read calls remain valid. The compound regression must distinguish planned member counts from coalesced output and must not claim every search always produces one physical read. The two recovery cases remain explicit opt-ins. This suite is separate from the fixed three-task, three-pair efficiency experiment. Stage 2 depends on the generic runtime-evidence acceptance work in PR #1162; selection annotations do not replace that stage's case-specific proofs.
After the manifest is recorded at the tested checkout's exact HEAD, run:
python3 scripts/agent_loop_benchmark.py \
--experiment tool_selection --repo . --base-revision <40-hex-fixture-base> \
--driver '<real-host-driver-command>' --samples 3 \
--case-id selection_single_read --case-id selection_batch_read \
--case-id selection_cross_tool_review --case-id selection_compound_source_context \
--output /tmp/tool-selection.jsonThe caller-owned driver receives the existing receipt/workspace/prompt variables
plus WEBCODEX_BENCH_EXPERIMENT=tool_selection. It must leave tool choice free,
collect ordinary ActionAudit evidence, and produce the existing bounded receipt
and independent correctness verdict. Selection reports can be compared with
other selection reports for the exact same case fingerprint and fixture Git base;
controlled-lane reports cannot be mixed into that comparison. Repetitions retain
failed, partial and unsupported observations without declaring a winner.
There is no bundled authenticated ChatGPT Web driver. Scripted MCP or loopback tests are useful runtime validation and must not be reported as real model-choice or Web acceptance. For actual Web captures use an isolated candidate Server and Runner and a disposable registered Project; record model/mode, connection path, Server/Runner build identities and source changes separately. The report cannot prove which schemas the Host loaded or restore unsaved Host messages. A driver without two real conversation contexts must mark the recovery case unsupported.
scripts/agent_tool_discovery_cases.json contains 48 labeled English/Chinese
requests, including exact names, paraphrases, ambiguity, no-match and OAuth-scope
negatives. Every fourth case is the predetermined heldout set. Labels are scorer
inputs, never hints to the evaluated model or keywords to copy into production.
Scope fixtures describe OAuth authority and must be applied by the capture driver,
not passed as manifest arguments. Discovery is not execution authorization.
The capture JSON has schema_version=1, the exact corpus SHA-256
corpus_fingerprint, a 40-hex base_revision, and results containing
{case_id, returned_tools} rows in actual retrieval order. Capture real canonical
manifest responses; an exact-contract response contributes its returned tool name.
No-match captures use an empty array. Do not fill omitted cases with empty arrays.
python3 scripts/agent_loop_report.py discovery \
--results /private/path/discovery-capture.json --output /tmp/discovery-report.jsonThe scorer validates identity, bounds and labels, computes top-five relevance and forbidden leakage, and keeps missing split metrics unavailable. Low baseline relevance is an observation, not a harness failure or proof of a fixed bug.
New optional ModelErgonomics v13 native_batch records capture admitted outer
read_files requested items or search_project_texts requested queries, each
bounded to 1..8. They contain no paths, query text, results, or credentials.
The profiler's native_batch section distinguishes observed multi-item calls
from complete totals. Missing/legacy/malformed records stay unavailable, as does
coverage when an outer call lacks canonical identity. These counts prove requested
cardinality, not completed work; nested Code Mode children remain unmeasured.
The user operated the ChatGPT Web App against an isolated Server/Runner and a disposable Project. These are manual acceptance observations, not results from the automated benchmark driver. Each reported answer was checked against current fixture bytes, Git state, and persisted Session/ActionAudit evidence. The user confirmed that the continuity case used two distinct new Web conversations.
The source base was 8153ef8caace55ab5c385e9f70f371d1c0c421c0 with the
uncommitted PR1 telemetry changes, built with experimental-code-mode. The
fixture snapshot was cac416c3b2c33cd36597a7192cb216e4b2d398d3.
The running binaries were recorded separately by SHA-256:
webcodex-server d90da9a6cbba59e5bd8b1afab834e3697f5efc60b42290e6b864dc5ac23b90fc
webcodex-runner 7ed037ed0259e90704812e243e54ccef200b7ce96d669bafffcdc8a8114e9993
Later offline scorer/reporting and documentation changes did not change those Rust binaries. Connection credentials, exact Session identifiers, private chat links and original local evidence remain outside the repository. The model/effort was tentatively reported by the user as “6-sol, 极高”; its exact identity was not independently verified. One continuity conversation URL was supplied, with no stage mapping; other conversation URLs are unavailable.
| Case | Independently verified outcome | Selected evidence and limits |
|---|---|---|
selection_single_read |
Correct before value; unchanged files |
One successful outer read_files, requested cardinality 1 |
selection_batch_read |
Both values before, both sentinels keep; unchanged files |
One successful outer read_files, requested cardinality 2 |
selection_cross_tool_review |
Correct clean Git state, branch and source-supported AND matching conclusion | One successful outer search_project_texts, requested cardinality 4 |
selection_failed_test_recovery |
Test exit 101 before edit, same test target exit 0 after; unchanged test and unrelated function; independent local rerun passed | Session events and final bytes corroborate recovery; Session-linked audit coverage is partial |
selection_session_recovery |
Explicit resume reused the original Session and saved decision/progress; exact final after/keep bytes |
Fresh file read preceded guarded edit; only alpha changed from the pre-case byte snapshot; prior greeting repair remained intact |
The failed-test repair was preserved for the continuity case. A pre-case tracked file hash snapshot independently established that continuity changed only alpha; the inherited repair was not counted as a new continuity edit. This manual run therefore does not claim the automated fresh-worktree fixture oracle was used.
An earlier batch-read answer named a different Project and had no matching isolated-runtime Session. It remains an unavailable connection attempt; only the subsequent correctly bound run is accepted. During recovery, some successful business calls omitted the outer recorder. Their Session events verify business outcomes, but they do not establish complete Session-selected outer-call totals. These baseline limitations remain visible; this PR does not fix tool choice or change recorder authority. Exact model turns, whole-task timing and repair-turn counts are unavailable. No latency, token, speedup or framework comparison is claimed from these five samples.
Separately, actual canonical manifest retrievals on the unchanged discovery
implementation were scored for the 36 development cases: 9/25 positive Top-5
hits (36%), recall@5 32.67%, and 11/11 negative rejections with no forbidden
returns. These are local deterministic retrieval measurements, not Web model
performance. The 12 fixed heldout cases were not captured for this baseline;
their baseline metrics remain unavailable. The corpus fingerprint is
e03448281d1ab1fcb6c5447836eda07216257838175ed9542d7507a72c126d10.
A real self-hosted dogfood build from the Typed Surface v1 branch ran the three fixed acceptance tasks below. Each pair used the same task definition and Git base, and the bounded annotation recorded zero contract-repair turns. These are observations from this run, not a general speed claim.
These measurements predate the later search_and_read_project_texts compound Direct primitive
added on main. Future paired runs must include that tool when it is the simplest
sufficient Direct control. The A/B outer-call deltas below remain evidence for the
recorded Git base, not an estimate of the current-main advantage; rebaseline them
before drawing a new throughput conclusion.
The exact Code Mode callable contracts measured 9,209 bytes for read_only,
12,108 bytes for validation, and 11,766 bytes for guarded_edit. All stayed
below the 16 KiB hard cap; ordinary Direct discovery did not carry the sidecar.
| Task | Direct outer / meaningful | Code Mode outer / meaningful | Nested evidence | Result bytes | Outcome |
|---|---|---|---|---|---|
| A — bounded repository review | 4 / 4 | 3 / 2 | 3 children, max_in_flight=3; 86,298 raw bytes → 1,930 returned bytes |
90,987 → 19,773 | Both runs reached the same clean-worktree, no-diff, timing-contract, and search-location conclusions with zero repairs. |
| B — adaptive read → one guarded edit | 5 / 5 | 4 / 3 | 4 children, max_in_flight=2; 3,262 raw bytes → 295 returned bytes |
8,274 → 21,304 | Both edits succeeded on the first attempt, produced the same one-file change, preserved the unrelated function, and passed cargo check. The Code Mode result-byte total was larger because one progressive-discovery contract cost about 12 KiB on this tiny task. |
| C — validation launch → Job continuation | 11 / 11* | 5 / 4* | validation launched one validator child plus one independent read; job_handoffs=1; 46,882 raw bytes → 918 returned bytes |
70,722 → 29,326* | Both runs launched validation exactly once, retained the same execution/continuation identity through terminal success, and did not redispatch validation. |
* Task C's raw outer-call and result-byte counts are not a clean throughput
comparison. The client/tool wrapper used short waits while a roughly 50-second
validation ran, producing eight Direct and two Code Mode observe_jobs polls of
their respective same-execution continuations. That cadence is Host/tooling
behavior, not model reasoning. The decision-relevant correctness fact is that
both paths launched one validation execution, received one canonical Job
continuation identity, and followed that same execution to terminal success.
Across A and B, the observed model_round_trip_proxy fell by two meaningful
outer calls in each pair, with no invalid-argument, wrong-result-shape, or child
call repair. Task A also materially reduced model-visible result bytes. Task B
shows the opposite byte tradeoff for a very small edit: progressive typed
discovery can cost more bytes than it saves when the task itself has little raw
evidence. That is a reason to keep the contract progressive rather than preload it
into every startup response.
Record the exact Workflow Session id and 40-hex Git base revision transiently for
each real run. Session selection is authoritative only through ActionAudit;
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
calls that require a business Session should pass both fields with the same exact
benchmark Session id.
A Direct summary with optional sidecar:
python3 scripts/agent_loop_report.py summarize \
--audit-db <server-sqlite-db> \
--workflow-session-id <workflow-session-id> \
--case-id <case-id> \
--variant direct \
--surface direct \
--base-revision <40-hex-base> \
--run-annotation <direct-run-annotation.json> \
--output <direct-report.json>A Host Code Mode summary:
python3 scripts/agent_loop_report.py summarize \
--audit-db <server-sqlite-db> \
--workflow-session-id <workflow-session-id> \
--case-id <case-id> \
--variant host_code_mode \
--surface host_code_mode \
--base-revision <40-hex-base> \
--run-annotation <host-code-mode-run-annotation.json> \
--output <host-code-mode-report.json>A Code Mode summary:
python3 scripts/agent_loop_report.py summarize \
--audit-db <server-sqlite-db> \
--workflow-session-id <workflow-session-id> \
--case-id <case-id> \
--variant code_mode \
--surface <read_only-or-validation-or-guarded_edit> \
--base-revision <40-hex-base> \
--run-annotation <code-mode-run-annotation.json> \
--output <code-mode-report.json>When an events.jsonl trace tree was captured and Runner enqueue observations are
useful, add --trace-root <tool-request-trace-root>.
The schema-v1 JSON summary reports, when evidence is available:
- exact
model_round_tripsremains unavailable because ActionAudit does not persist a model response/turn identity; parallel meaningful outer calls may share one model response. model_round_trip_proxy: the existing meaningful outer-call count, retained only as an explicit round-trip-pressure proxy. Nested Code Mode children never count.- outer model-facing calls: total, meaningful, success/failure, and tool-name distribution;
- Direct and Host Code Mode canonical-call counts from outer
model_ergonomicsrecords; host_short_chain: exact same-Window serial transition count, multi-call chain count, calls participating in those chains, maximum chain length, and observed tool-pair distribution. An exact predecessor outside the selected benchmark run is a chain boundary; a declared serial transition whose exact predecessor cannot be resolved makes the aggregate unavailable. This is ordering evidence only;same_model_turn_provenis always false because ActionAudit has no Host-cell/model-response identity;- authoritative Code Mode composition: nested calls/successes/failures,
max_in_flight, nested tool counts, consequential known/Job/unknown outcomes, internal duration, slot wait, optional program input bytes, and nested raw versus returned bytes; child_calls.failed: authoritative Code Mode nested failure count when the composition summary is complete;- WebCodex service time, ToolRuntime duration, canonical outside-WebCodex serial gaps, and overlap;
- exact serialized outer
ToolResultbyte totals/distributions; - optional
repair_turns,task_wall_time_ms, and correctness verdicts from the bounded sidecar; - structured outer
error_kind,failure_kind, andrecovery_kinddistributions; - observed Runner enqueue count/request-kind distribution from trace JSONL.
The summary includes an explicit availability object. Consumers must inspect it
rather than assuming an absent metric is zero.
input_ergonomics reads the existing action_events.summary_json.model_ergonomics
record. It adds no production table or migration. The report envelope stays schema
v1, consistent with its existing additive metric sections; the persisted telemetry
producer moves from v12 to v13 so old missing fields are not counted as zero use.
The section reports normalization_events, normalization_by_code, and
normalization_by_tool, plus invalid_argument_rejections and
invalid_arguments_by_tool. Only successful canonical outer invocation records
with a known closed normalization code contribute to normalization counts. Success
is the invocation outcome, including successful durable admission, not a promise
that an asynchronous command eventually succeeds. Failed results do not contribute
even if malformed historical data contains a normalization field.
Coverage is explicit: measured_canonical_calls, eligible_events (v13+),
eligible_successful_events, legacy_schema_events, and
missing_or_invalid_record_events. The rate is exactly
normalization_events / eligible_successful_events; legacy v12 rows and records
missing canonical identity/outcome evidence never enter that denominator. Zero
eligible successes yields null, not zero. Unknown/malformed codes are omitted and
counted in unrecognized_normalization_events; they make rate availability false
rather than silently reporting an artificially low rate. The offline reader has a
closed v13 wire-contract allowlist, not a runtime normalization/alias registry.
Consult availability.input_ergonomics before interpreting the rate.
immediate_same_tool_repair_proxy considers each selected canonical meaningful
success=false, error_kind=invalid_arguments call. It inspects only the next
meaningful call in the same exact ClientWindow and principal correlation. Both
calls must have non-streaming, eligible continuity and ordered request/handoff
timestamps; the successor must persist the exact predecessor trace relation with
window_transition_kind=serial, have canonical telemetry, and not have ambiguous
trace/predecessor identity. Count only a same-tool successful successor. Never skip
an intervening meaningful call (including one without telemetry), cross principals,
or use an arbitrary seconds threshold. Existing continuity lookup may resolve an
unlinked intervening call or the exact successor outside the selected Session;
those context rows never expand the normalization denominator.
This is a WebCodex-observed immediate same-tool corrective-call proxy. It does
not prove model turn identity, a causal repair, or that field spelling caused the
failure. Legacy canonical records may contribute when they retain all necessary
continuity evidence. Missing successor, streaming/overlap, incomplete identities,
or context limits make the proxy available=false with null count/by_tool.
observed_count/observed_by_tool retain only the proven subset; coverage and
unavailable_by_reason explain the gap. A different immediate tool is a measured
non-match, not permission to search ahead for eventual same-tool success. Existing
manually annotated repair_turns remain separate and are never filled from this
proxy. Trace-only reports mark input ergonomics unavailable.
No raw arguments, parser error text, hints, stdout, Window/principal identities or per-event payloads are emitted by this section. Normalization counts describe use, not an experiment proving saved model turns. Collect v13 coverage after an explicit deployment, compare repeated correction patterns and known provider spellings, and measure proposed descriptor bytes before deciding whether another alias has concrete value. Do not infer the misspelled field from this aggregate alone.
Authoritative from ActionAudit: meaningful outer calls (also reported as the
model_round_trip_proxy), outer success/failure/tool distribution, service timing
when timestamps exist, serialized result bytes when persisted, canonical serial gaps
and Host short-chain ordering evidence when continuity evidence exists, and Code Mode
composition counts/timing/bytes/concurrency.
Manual bounded annotation: repair turns, full task wall time, and final correctness/validation verdicts.
Unavailable when not explicitly recorded:
- exact model round trips. ActionAudit can prove meaningful model-facing outer tool calls and overlap, but it does not persist the model response/turn identity needed to prove how many inference round trips produced those calls.
- whether two serial Host Code Mode calls came from one JavaScript cell or one model response.
host_short_chainintentionally does not infer that fact; - per-child Code Mode failure-kind distribution. Current composition persists the authoritative nested failure count but not each child failure category.
- native batch item counts. A
read_filesorsearch_project_textschild call is visible, but ActionAudit does not persist payload-safe item/query counts. - exact
Promise.allusage.max_in_flight > 1proves overlapping nested execution; it does not prove which JavaScript syntax created it. - generic same-execution Job handoff count and terminal-observation count outside the authoritative consequential-child receipt evidence.
- resolved recovery count.
recovery_kindis guidance on one failed result, not proof that a later call resolved it. - complete Runner-request total from trace files; trace persistence has no completeness fence.
Contract/surface failure analysis uses existing structured outer
error_kind/failure_kind/recovery_kind distributions directly. For
example, invalid_arguments, child_call_failed, or Code Mode runtime failure
kinds are counted when they are actually present. The profiler does not invent a
larger taxonomy or parse error prose to infer one.
python3 scripts/agent_loop_report.py compare \
--baseline <direct-report.json> \
--candidate <code-mode-report.json> \
--output <comparison.json>JSON is the authoritative comparison shape. A Direct baseline can be paired with
either a Host Code Mode candidate or a typed Code Mode candidate. Numeric entries
carry baseline, candidate, candidate-minus-baseline delta, and a comparable flag.
The paired output includes at least:
- meaningful outer-call/
model_round_trip_proxydelta; - Host short-chain serial-transition, multi-call-chain, participating-call, maximum-chain-length deltas, plus side-by-side observed tool-pair distributions;
- repair-turn delta and side-by-side repair reason counts;
- failed outer-call delta;
- failed Code Mode child calls;
- structured contract/surface failure and recovery distributions;
- outside-WebCodex gap and service time;
- Code Mode nested-call count and
max_in_flight; - nested raw-result bytes versus returned bytes;
- task wall time when independently annotated;
- full evidence availability for both runs.
case_compatibility requires the same case id, exact base revision, and exact
case fingerprint. pair_compatibility additionally requires Direct as the baseline
and either Host Code Mode with surface=host_code_mode, or Code Mode with an
explicit read_only, validation, or guarded_edit surface, as the candidate.
correctness_compatibility requires both runs to pass the case correctness gate
and any required validation. throughput_compatibility is true only when both
the pair and correctness gates pass.
The profiler still emits descriptive numeric deltas when a gate is closed so the raw evidence is inspectable, but those deltas are not treated as a valid throughput comparison. No metric ordering, score, winner, or automatic “better” judgment is produced.
The report never emits raw ClientWindow values, principal ids, Workflow Session
ids, trace ids, runtime Project ids, tunnel/instance ids, commands, patches, file
contents, credentials, or tool arguments. The run annotation rejects unknown
fields so it cannot become a catch-all payload store.
These measurements cannot establish model reasoning time, reasoning quality, intent, exact JavaScript source usage, causal attribution for outside-WebCodex gaps, or a general claim that Code Mode is faster. They provide bounded observations for controlled Direct-vs-Code-Mode experiments only.