AI coding

Auditing Human Decisions in the Task Log

Antonio Evans8 min read

A split scene: on the left, a scrolling task log with rows showing reviewer avatars, timestamps, and approved/rejected tags attached to small diff snippets.
Key points

Key points

  1. 1A task log records what agents did, but an audit of sampled approved diffs and rejected prompts turns it into evidence about whether the humans reviewing those actions apply the same standard.
  2. 2The workable procedure is fixed sampling (for example 20 approved diffs and 20 rejected prompts per reviewer per period), a written rubric with explicit pass criteria, and a blind double-score on a random subset.
  3. 3Agreement is easier to interpret as a chance-corrected statistic such as Cohen's kappa than as raw percentage agreement, because raw agreement flatters reviewers when one outcome dominates.
  4. 4Disagreements should feed rubric rewrites and calibration sessions, not individual rankings, or reviewers start optimizing for the audit instead of for the code.

Why the log is the wrong place to look for agent quality alone

Most teams read a task log as a record of agent behavior: which tool was called, which file changed, which prompt the agent rejected. That reading misses half the system. Every entry in the log passed through a human decision, and that decision is what makes the entry trustworthy or not. If two reviewers would have scored the same diff differently, then the log is not documenting a consistent policy, it is documenting two policies.

The empirical case for auditing reviewers is straightforward. A large study of agent-generated review comments across 342 Python repositories looked at 54,791 comments from five coding agents and found that core developers resolved the majority of agent-generated feedback, particularly for design and evolvability comments, while peripheral developers were more involved with functional defect comments (the arXiv study on developer responses to agent review comments). Who reviews what changes what gets merged. That is a human variable, and it belongs in your measurement.

There is a second reason to sample the humans rather than only the agents. Agents already have automated evaluation: unit tests, trace inspection, judgment-based scoring. A recorded walkthrough of AI agent observability shows a procurement agent passing only about 40 percent of its grounding checks before anyone looked at prompts, then climbing as the prompts were iterated (the Arize walkthrough on tracing and evals). Automated evals are the right tool for the agent. The human approval step has no equivalent unless you build one.

Step 1: Define the population and draw a fixed sample

You cannot audit an unbounded stream. Define two populations before you draw anything.

  1. Approved diffs. Diffs that a named human reviewer approved for merge or deployment. Exclude anything merged automatically by a policy with no reviewer in the loop, because there is no human decision to audit.
  2. Rejected prompts. Cases where a reviewer overrode or declined what an agent proposed. Here you are testing whether rejections were justified, which means sampling rejections more heavily than their raw frequency might suggest.

Draw the sample on a schedule rather than when someone thinks there might be a problem. A defensible default is 20 approved diffs and 20 rejected prompts per reviewer per month, with a minimum of 30 total comparisons per reviewer so the agreement estimate is not noise; a published heuristic on kappa studies suggests no fewer than 30 comparisons and notes that samples in the thousands produce tight confidence intervals (McHugh on the kappa statistic and the discussion of sample size heuristics in this review of agreement sample sizes).

The accounting analogy is useful here: audit sampling applies a procedure to less than 100 percent of items to evaluate a characteristic of the whole population, and both statistical and nonstatistical approaches require judgment in planning and evaluating the sample (PCAOB AS 2315 on audit sampling). Twenty items per reviewer per month is not a statistical inference about defect rates. It is a consistency probe, and it is enough to detect a reviewer applying a different rule from everyone else.

Record the draw in a reproducible way so the same period can be re-scored later. The principle is the same one that governs reproducible model outputs: fix the inputs, the random seeds, and the parameters so results can be rechecked (strategies for reproducible AI outputs).

import random, json

def draw_sample(entries, n_approved=20, n_rejected=20, seed=42):
    rng = random.Random(seed)
    approved = [e for e in entries if e["decision"] == "approved"]
    rejected = [e for e in entries if e["decision"] == "rejected"]
    return {
        "approved": rng.sample(approved, min(n_approved, len(approved))),
        "rejected": rng.sample(rejected, min(n_rejected, len(rejected))),
    }

Step 2: Write a rubric with pass criteria you can argue about

A rubric that says "quality looks good" will produce disagreement that teaches you nothing. Each criterion needs a binary test and a worked example of a failure. The rubric should mirror what you expect the reviewer to check, which means it should be short enough to apply in minutes.

CriterionPasses whenCommon fail reasonReason code
Scope matchDiff touches only files named in the task descriptionAgent edited unrelated moduleSCOPE
Test coverageAt least one test added or updated for changed behaviorLogic change with no testTESTS
Intent matchImplementation does what the prompt asked, not a plausible neighborCorrect code, wrong requirementINTENT
Reversible failureFailure modes are explicit (errors raised, no silent fallback)Broad except that swallows errorsERRHANDLING
Evidence attachedReviewer linked the test run or trace to the approvalApproval with no verification recordEVIDENCE

Two things about this table matter more than its contents. First, every criterion is checkable from the diff plus the linked task; none of them requires knowing the reviewer's mind. Second, the reason codes are the unit of analysis later. When you compare two reviewers, you want to say "we disagree about TESTS twice and EVIDENCE five times," not "one of us is stricter."

A useful external anchor for the critic-era failure modes: an analysis of AI-co-authored pull requests in a 470-PR sample found 75 percent more logic and correctness issues alongside elevated security and error-handling flaws, and AI-assisted changes frequently exceed 400 changed lines, a point past which defect detection drops (CodeRabbit's guide to reviewing AI-generated diffs). If your rubric has no criterion for error handling and size, it is not testing the failure modes that actually appear.

Writing the criterion down also improves the agent side. The spec-driven approach to coding with an agent pushes requirements into a requirements.md file and a plan into plan.md before any code exists, precisely so the work can be checked against a stated target (JetBrains on the spec-driven approach). A rubric criterion like INTENT is easier to pass when the original task has a written statement of what the agent was supposed to achieve.

Step 3: Double-score a blind subset and measure agreement properly

Take a random subset of the sampled items, ideally 20 to 30 percent, and have a second reviewer score them without seeing the first reviewer's score or the final decision. Blind is the important word: an unblinded second score mostly measures deference.

Then compute agreement. Raw percent agreement is the wrong headline number for two reasons: it does not correct for chance, and chance agreement is high when one decision dominates the population. If 90 percent of sampled diffs are approved, two reviewers guessing from that base rate would agree on roughly 82 percent of items before any real consistency. Cohen's kappa corrects for that, so a kappa of 0.8 means 80 percent of the possible agreement beyond chance has been achieved (the sample size review discussing kappa under imbalance).

Kappa rangeLabelWhat to do with it
Below 0.21SlightStop the audit, rewrite the rubric
0.21 to 0.40FairRecalibrate on the top reason codes
0.41 to 0.60ModerateTighten 2 or 3 criteria only
0.61 to 0.80SubstantialTargeted fixes, keep sampling
0.81 to 1.00Almost perfectMaintain, spot-check quarterly

Those band labels come from the standard interpretation guidelines reproduced in sample size guidance for kappa agreement studies. Use them as a shared vocabulary for calibration decisions, not as a grade.

def cohen_kappa(a, b, labels=("pass", "fail")):
    n = len(a)
    observed = sum(x == y for x, y in zip(a, b)) / n
    expected = sum((a.count(l) / n) * (b.count(l) / n) for l in labels)
    return (observed - expected) / (1 - expected)

A worked example makes the value of kappa concrete. Suppose two reviewers score 30 items and agree on 26 of them, an agreement rate of 86.7 percent, which sounds fine. Suppose 22 of the 30 were scored pass by both scales' marginal rates. The expected agreement by chance is (22/30 × 23/30) + (8/30 × 7/30), which is 0.562 + 0.062, or about 0.62. Kappa is (0.867 − 0.62) / (1 − 0.62), roughly 0.65, which is substantial but well short of the number the raw percentage implied. If you instead had 24 agreements out of 30 with the same base rates, kappa lands near 0.55 and the calibration conversation changes.

For sample planning, kappa precision depends heavily on how close your confidence limit sits to the estimate. Tightening the nearer limit is expensive: distances of 0.20, 0.05 and 0.01 require roughly 118, 1,625 and 38,203 subjects respectively (the kappasizeci documentation on precision-driven sample size). That is why monthly samples of 20 plus a rolling pool across quarters is the practical design. You are not trying to publish a kappa with a narrow interval, you are trying to catch a reviewer drifting away from the rubric.

Step 4: Turn disagreements into a shorter calibration loop

Every disagreement gets a recorded reason before it gets a discussion. Tag it with the rubric criterion, not with a person. At the end of a month you should have something like: eight EVIDENCE disagreements, five TESTS, two SCOPE, one INTENT. That distribution tells you exactly what to fix.

Disagreement patternMost likely causeFix
Clustered on EVIDENCEReviewers disagree on what proof is requiredRewrite the criterion to name the artifact required
Clustered on TESTSThe test threshold is perceived, not writtenState "changed behavior requires one test touching the changed branch"
Spread across all criteriaRubric is unreadable or training is missingOne 30-minute session with three worked examples
Concentrated on one reviewerLocal norm has driftedPair-score with a second reviewer for one cycle
Zero disagreementsSampling is not blindSeparate the scoring from the decision record

The meeting itself should be 30 minutes and should never include a leaderboard. The moment reviewers learn that disagreement counts against them, they will agree with whatever the other score says, and kappa will rise while quality does not. Keep the metric at the level of the rubric criterion and the team, and use individual data only in a one-to-one conversation about a specific criterion the reviewer asked to understand better.

There is a good model for this in how agent review comments get triaged. When unresolved agent comments were analyzed, the most common reasons a comment went unaddressed were incorrect suggestions and intentional design decisions, and short comments with an inline code suggestion were the strongest predictor of being acted on (the same study of agent review comments). Your rubric criteria work the same way: short, specific, attached to a concrete artifact. A criterion that requires a paragraph of interpretation will produce disagreement even among careful reviewers.

What to do with the numbers, and what not to do

Three outputs belong on the team dashboard: kappa per rubric criterion, reason-code mix over time, and the count of rubric revisions. Three things do not belong there: individual reviewer rankings, approval rate as a target, and the number of agent changes reverted.

The reason approval rate is a trap deserves a sentence. If reviewers know their approval rate is watched, the cheapest way to improve the number is to reject more, which pushes the cost onto the people re-doing the work. A log-based audit that rewards rejection volume teaches the same behavior. Anchor the audit to consistency instead: are reviewers applying the written rule, and does the written rule predict a good merge?

When the rubric turns out to be wrong, the audit has done its job. If one criterion produces most of the disagreements and most of the failures the team later regrets, rewrite it, re-score the last two periods against the new version, and note the change. That is the loop. The humans in the loop are the thing being improved, and the log is just the substrate.

If you are running several teams with different reviewers and want the audit to compare like with like, one choice is a single model interface so the agent side stays constant while you calibrate the human side. Quanta Inference routes text, image, video, audio and embedding models through one OpenAI-compatible API, which keeps the agent behavior stable enough that reviewer disagreement is not confounded by model swaps: https://quantaintelligence.ai/inference.

FAQ

FAQ

How many items do I need to sample before agreement numbers mean anything?

Aim for at least 30 scored comparisons per reviewer before you interpret kappa at all, and treat anything below that as anecdote. Precision improves slowly and expensively: a confidence limit within 0.20 of your estimate needs roughly 118 subjects, while a limit within 0.05 needs around 1,625 (kappasizeci guidance). Monthly samples of 20 approved diffs and 20 rejected prompts per reviewer, pooled across a quarter, are a reasonable compromise for a team that wants to catch drift rather than publish research.

Should I score approved diffs and rejected prompts the same way?

No. Approved diffs need criteria that test whether the change was safe and in scope, such as test coverage and evidence of verification. Rejected prompts need criteria that test whether the rejection was justified, such as whether a documented policy or a stated requirement was actually violated. Use the same reason-code vocabulary for both so you can compare the mix, but write separate criterion definitions, because the failure modes are different.

Why not just report the percentage of items where reviewers agreed?

Percent agreement does not correct for chance, and it is highest exactly when the population is imbalanced. If most sampled diffs are approved, two reviewers applying loose heuristics will agree most of the time without sharing a rule, and the percentage will look healthy while the underlying consistency is weak. Cohen's kappa removes the agreement you would expect from the base rates alone, which is why the standard bands treat 0.61 to 0.80 as substantial and anything under 0.21 as slight (McHugh on kappa).

What if the second reviewer cannot score blind because they already saw the merge?

Draw a subset that the second reviewer has no personal history with, or score on a criterion level where the merge outcome does not reveal the answer. If neither is possible, have the second reviewer score from the diff and the linked task only, with the decision field stripped from their view. Non-blind double scoring inflates kappa and hides exactly the disagreements you need.

How do I keep the audit from becoming a performance review?

Publish results at the level of the rubric criterion and the team, never per person, and say so in writing before the first cycle. Route individual data into one-to-one conversations only when the reviewer asks for it. If leaders start using disagreement counts in promotion or compensation conversations, the metric becomes worthless within one cycle, because the cheapest way to reduce disagreement is to copy the other reviewer's score.

Sources

Sources

  1. Understanding Developer Responses to Agent-Generated ...
  2. How To Debug AI Agents: Tracing, Observability & Evals
  3. Interrater reliability: the kappa statistic - PMC - NIH
  4. Assessing interrater agreement in meta-analyses - what sample size ...
  5. AS 2315: Audit Sampling
  6. Proven Strategies for Reproducible AI Outputs
  7. Code review best practices for AI-generated diffs
  8. How to Use a Spec-Driven Approach for Coding with AI
  9. Sample Size Calculations for Interobserver Agreement Studies
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles