Skip to content

perf(agent): drop the exhaustive-audit nudge that fired on ordinary English#749

Merged
ericleepi314 merged 1 commit into
mainfrom
perf/remove-exhaustive-audit-machinery
Jul 26, 2026
Merged

perf(agent): drop the exhaustive-audit nudge that fired on ordinary English#749
ericleepi314 merged 1 commit into
mainfrom
perf/remove-exhaustive-audit-machinery

Conversation

@ericleepi314

Copy link
Copy Markdown
Collaborator

clawcodex runs +26% more trajectory steps than the latest Claude Code on the same model at the same effort. This is iteration 1 of closing that gap.

The mechanism

#740 added a one-shot "exhaustive audit": when a request matched a bare quantifier, the loop appended a MUST-enumerate instruction and forced another model turn, backed by a matching system-prompt clause.

The trigger was \b(all|every|multiple|each|exhaustive|complete set|any other|others)\bplain English, not a request shape. Against the 89 terminal-bench 2.1 instructions it fired on 49%, almost all incidental: "each line of the file", "where each task is an async job", "in all years". One case inverted the instruction outright — regex-log says "If multiple dates are present in a line, the regex should match only the last one", and the nudge answered that by demanding exhaustive enumeration.

Removed, not tuned

I first tightened the regex and got the trigger rate to 3%. I threw that away: tuning a clawcodex-only heuristic against a benchmark is fitting to the scoreboard. The evidence says the mechanism shouldn't exist:

  • the latest Claude Code scores 1.0 on both tasks this was built for (chess-best-move, regex-chess) with no audit machinery at all;
  • only 1 of its 89 trials writes more than two verification files, against clawcodex's 57 temporary verification scripts across the run;
  • CC re-runs its single test more than clawcodex does (1.34 vs 1.00 per trial) — it iterates on one test where clawcodex spawns new ones.

What stays is the phrasing-independent half: "audit the result against every explicit requirement … do not treat producing a plausible result as proof that the task is complete." A genuine request for every qualifying result is an explicit requirement, so that already covers the case the nudge reached for — without keying off the word "each".

Removes EXHAUSTIVE_AUDIT_NUDGE, requests_exhaustive_results, the _EXHAUSTIVE_REQUIREMENT pattern, the QueryState.exhaustive_audit_performed latch, and the forced-turn branch.

Measured on 7 tb2.1 tasks (same model, effort, dataset)

Comparing only trials that ran clean in both iterations (a crash truncates step counts):

task before after Claude Code
cancel-async-tasks 38 11 6
fix-code-vulnerability 30 14 10
regex-log 28 19 9
distribution-search 6 9 5
mean 25.5 13.2 7.5

Step gap vs CC: +18.0 → +5.8 (−68%). Distinct verification files per trial: 2.50 → 0.75 (CC 0.25).

Reward went 0.857 → 1.000 with 0 errors (from 3), so the steps came off without losing correctness.

Caveat: 4 comparable tasks, one run each — directionally strong (3 of 4 improved substantially) but noisy at this n. The two iter0 crashes were the known OAuth-rotation issue, not this change.

Tests: 8842 passed. The replacement test pins the inverse — a completion claim on an exhaustive-sounding request must not buy an extra turn.

🤖 Generated with Claude Code

…nglish

#740 added a one-shot "exhaustive audit" pass: when a request matched a
bare quantifier, the loop appended a MUST-enumerate instruction and forced
another model turn, backed by a matching system-prompt clause.

The trigger was `\b(all|every|multiple|each|exhaustive|complete set|any
other|others)\b` — plain English, not a request shape. Measured against
the 89 terminal-bench 2.1 instructions it fired on 49% of them, almost all
incidental: "each line of the file", "where each task is an async job",
"in all years". One case inverted the instruction outright — regex-log
says "If multiple dates are present in a line, the regex should match only
the last one", and the nudge answered that by demanding exhaustive
enumeration.

Removed rather than tuned. Tightening the regex would have been fitting a
clawcodex-only heuristic to a benchmark; the evidence says the mechanism
should not exist:

* the latest Claude Code scores 1.0 on both tasks this was built for
  (chess-best-move, regex-chess) with no audit machinery at all;
* only 1 of its 89 trials writes more than two verification files, where
  clawcodex wrote 57 temporary verification scripts across the run;
* clawcodex is +26% on mean trajectory steps against the same model at
  the same effort, and forced audit turns are part of that.

What stays is the phrasing-independent half: "audit the result against
every explicit requirement in the user's request … do not treat producing
a plausible result as proof that the task is complete." A genuine request
for every qualifying result IS an explicit requirement, so that sentence
already covers the case the nudge was reaching for — without keying off
the word "each".

Removes: EXHAUSTIVE_AUDIT_NUDGE, requests_exhaustive_results, the
_EXHAUSTIVE_REQUIREMENT pattern, the QueryState.exhaustive_audit_performed
latch, and the forced-turn branch in the loop.

Tests: 8842 passed. The replacement test pins the inverse — a completion
claim on an exhaustive-sounding request must not buy an extra turn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ericleepi314
ericleepi314 merged commit 9b2b274 into main Jul 26, 2026
2 checks passed
ericleepi314 added a commit that referenced this pull request Jul 26, 2026
…ance (#750)

Iteration 2 on the trajectory-step gap against the latest Claude Code
(same model, same effort). Iteration 1 (#749) took the subset mean from
25.5 to 13.2 steps against CC's 7.5; this addresses the largest remaining
structural difference.

Measured on the same tasks: clawcodex emits more than one tool call per
assistant turn in **5.7%** of steps, the latest Claude Code in **18.1%**.
Every independent pair it does not batch is an extra step, so that ratio
is most of what remains between the two step counts. Reading the
trajectories side by side shows it plainly — on regex-log CC issued 8
calls, all Bash, batching probes ("for c in node deno perl ruby; do
command -v $c; done") and creating files with heredocs; clawcodex issued
17, alternating Write then Bash and probing one command at a time.

Cause is a truncated port. The reference bullet has three parts:

    You can call multiple tools in a single response. If you intend to
    call multiple tools and there are no dependencies between them, make
    all independent tool calls in parallel. Maximize use of parallel tool
    calls where possible to increase efficiency. However, if some tool
    calls depend on previous calls to inform dependent values, do NOT call
    these tools in parallel and instead call them sequentially. ...

clawcodex kept only the first sentence. What was dropped is what turns a
permission into a practice: the imperative to maximize, and the
dependency carve-out. The carve-out matters as much as the push — without
a statement of when NOT to parallelize, "call them in parallel" is risky
advice a careful model will mostly decline, which is what the 5.7% looks
like.

Same defect class as #748 (dropped qualifiers on the file-creation
bullet), and general rather than benchmark-specific: batching independent
work is better agent behavior everywhere.

Tests: 8843 passed. The new test pins all three clauses, since restoring
only the push would leave the model without the safety half.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
ericleepi314 added a commit that referenced this pull request Jul 26, 2026
#754)

* perf(prompt): check the next action's assumptions before running it

Iteration 5. First one derived from classifying trajectory steps by PURPOSE
rather than by tool, which is what finally located the gap.

Seven shared terminal-bench 2.1 tasks, same model (claude-opus-5), same
effort (xhigh), per trial, two clawcodex runs against the latest Claude
Code:

                     clawcodex        Claude Code
    explore:inspect   1.71 / 1.57      2.43     <- Claude Code inspects MORE
    explore:read      0.86 / 1.14      0.57
    author:inline     2.71 / 2.29      1.14
    author:deliverable 1.29 / 2.43     1.14
    run:exec          2.29 / 3.57      1.14     <- the biggest single gap
    meta:memory       0.29 / 0.57      0.00
    meta:tasks        0.14 / 0.29      0.00
    TOTAL            12.14 / 15.43     8.43

Claude Code buys about 0.7 extra inspection steps and saves 1.2-2.4
execution steps. It looks at the actual data, then writes something that
works first time. clawcodex writes from assumptions, runs, and pays in
write-run-fix cycles -- run:exec and author:inline are each roughly double
Claude Code's, while inspection is LOWER.

Every tool-level metric already matches (Bash 78.8% vs 79.7%, Write 11.8%
vs 11.9%, per-call density 5.2 vs 5.5 statements, heredoc 20.9% vs 23.4%,
exact-repeat 2.4% vs 0.0%). Purpose-level classification is what separated
"same actions, more of them" into "fewer looks, more retries".

This also explains a failure. Iteration 3 added the opposite instruction --
act once you have enough information, do not re-check what the evidence
supports -- and made both step count (+3.2 -> +7.2) and reward (1.000 ->
0.857) worse. It was pushing clawcodex further toward acting before
looking, when under-inspection was the actual deficit. That bullet was
withdrawn; this is the corrected direction, and the earlier failure is
evidence for it.

Scope is deliberately narrow: the assumptions the NEXT action rests on, not
a survey of the environment. #749 had to remove exhaustive-audit machinery
that fired on ordinary English, so the limiter is load-bearing and pinned
by the test.

Not claimed: a verified step reduction. Same-code replicates on this task
set swing up to 11 steps per task and 3.43 in the mean, so at k=1 nothing
under ~3 mean steps is resolvable. Claude Code replicates are in flight to
establish a k=3 baseline; this change gets measured against it, not against
a single run.

* perf(prompt): restore the reference's skip conditions on the task tool

The port kept "Break down and manage your work with the TaskCreate tool"
and dropped the reference's gating, which reads: "Skip using this tool
when: There is only a single, straightforward task; the task is trivial and
tracking it provides no organizational benefit." What survived is an
unconditional imperative.

Measured over 14 clawcodex and 21 Claude Code trials on seven shared
terminal-bench 2.1 tasks, same model (claude-opus-5) and effort (xhigh),
steps per trial by purpose:

                    clawcodex   Claude Code   delta
    run:exec           3.36        2.52       +0.83
    other              1.43        0.67       +0.76
    author:inline      2.50        1.90       +0.60
    meta:memory        0.43        0.00       +0.43
    explore:env        1.07        0.67       +0.40
    meta:tasks         0.21        0.00       +0.21
    explore:inspect    1.64        2.29       -0.64
    author:file        2.00        2.19       -0.19
    TOTAL             13.79       11.38       +2.40

Claude Code spends ZERO steps on the task tool across 21 trials and zero on
memory writes. clawcodex spends 0.64 per trial on the two together -- 27% of
the whole remaining gap, on bookkeeping rather than the task. This commit
addresses the task-tool half, where the fix is a dropped reference qualifier
rather than a judgment call.

The memory half is deliberately untouched. Its "build up this memory system
over time" imperative IS in the reference, and memory is a shipped feature
whose quality this eval cannot see -- changing it on step-count evidence is
what made iteration 3 regress reward.

Also of note in the table: "Claude Code inspects more" (-0.64) survives
Claude Code's replication, so the iteration-5 premise was sound even though
the change built on it measured null and was dropped.

Not claimed: a verified step reduction. 0.21 steps/trial is far inside the
same-code noise floor (median 2, max 11 per task). This lands because the
dropped qualifier is a real port defect, not because the number is
measurable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant