Technical write-upCo-Researcher project · October 2026

Every Claim Traced

Deterministic evidence checks for agent-written literature reviews, and how to test them against live agents

Poe Poe Myint Swe
Co-Researcher project
13 October 2026 · runs at commits eca0b37, 21c3777, 154c26f and 5802823 (release 2.7.0) · gate described at cb54321

Abstract

Recent tools check that an AI-generated reference exists, or ask a model whether a cited source supports a statement. A literature review written by an agent can pass both checks and still misreport its evidence, because many of the errors that matter sit in the synthesis prose. A dropped negation, a number added between a claim and its summary, or a finding cited to a background source all pass a reference check. I describe a deterministic gate that runs inside the agent's writing loop over a ledger of claims. It authenticates each quote against the submitted source text, binds each claim to one corpus record, and checks that each cited synthesis sentence matches a verified claim in its numbers, negation parity and direction words. These are surface checks with known gaps, which I state and demonstrate. I also show how to test such a gate against live agents, whose output may never contain the planted error. On 13 attack families and two controls, the gate flagged every family on the first pass in every run, with Claude Opus 5.5 and GPT Codex as writers. A fourteenth family, a finding overstated without changing any number or negation, went undetected in both release runs, as the design predicts. In a single-run comparison, repair passed all 10 original repair-target cases for both writers once the repair step pointed at the validator's artifact contract and the skill, against 8 and 4 without them. A rubric judge that sees the task and the synthesis but not the evidence scored byte-identical short syntheses up to 38.5 points apart. These results come from a synthetic pilot, and I outline a test on real papers that would check each of them.

Keywords: evidence integrity · citation verification · LLM agents · systematic review · fail-closed validation · evaluation methodology

1Introduction

A sentence such as “the trial found no change in recall (Lumen, 2024)” makes three assertions. Lumen wrote the paper, the paper says this, and the sentence says no more than the paper does. An agent drafting a review produces hundreds of such sentences in one pass, quoting, paraphrasing, aggregating numbers and binding citations with no human reading every source. Language models fabricate references at measurable rates [1], and a growing set of tools now checks that references exist [2–5]. Fewer check the third assertion, that the review's own prose stays inside its evidence. I describe a gate that checks part of it. The writing agent records each claim it draws from a source, with the quote that supports it, in a claim ledger. The gate traces cited sentences and uncited numbers through that ledger, and §3 states which statements it checks and which it does not.

Figure 1 shows six versions of one evidence chain. Four come from my public attack set, and in each a planted error breaks one link. The sixth is a counterexample from §7, in which the claim reverses its quote and every link still passes. In all of them the prose reads as fluently as the authentic version.

Figure 1. The evidence chain behind each cited sentence, from synthesis sentence to claim, supporting quote and source. The gate compares a claim with its quote only on numbers, so the middle link is a number check, and the last variant shows a reversed claim that passes. The four planted-error variants come from cases in the public attack set (§4.1), and the last from §7. Select a variant to see which link breaks and the finding the gate raises.

I make three contributions.

I treat these results as a pilot. The test set is synthetic and I wrote it alongside the gate, so each limitation in §7 becomes a question for a test on real papers, sketched in §8.

2Related work

Reference existence. Generated bibliographies contain references that do not exist or carry substantive errors [1]. CiteAudit [2] and CiteCheck [3] detect fabricated or corrupted references by retrieval and model-based judgment. HALLMARK [4] benchmarks such verifiers on 2,526 BibTeX entries and finds that false-positive rates, not recall, decide whether a verifier is usable. Badalova and Mayr [5] trace the failures of five existing tools to extraction errors, incomplete metadata, database coverage and inconsistent results. My bibliography check belongs to this family and is the least novel part of the gate.

Attribution and support. Rashkin et al. define output as attributable when a human judges it supported by an identified source [6]. ALCE [7] scores generated citations with an entailment model, FActScore [8] checks atomic facts against a knowledge source, and SciFact [9] retrieves abstracts that support or refute a scientific claim. SourceCheckup [10] found that 50% to 90% of LLM answers to medical questions are not fully supported by the sources they cite. Onweller et al. [11] parse citations in deep-research reports deterministically and then judge each against its source with a model or a human. ResearchQA [12] checks deterministically that a quoted span is a substring of a single paper, and reports that citation metrics separate models better than LLM-judge scores. Goo et al. [13] measure citation faithfulness in agentic scientific synthesis on public benchmarks and bound the rate of unsupported citations that escape flagging. Hirsch et al. [14] trace citation errors in multi-agent deep-research systems to the agent that introduced them, and one of their error types, output left uncited, matches a gap in my gate (§7). My quote matcher shares ResearchQA's premise, and ALCE and Onweller et al. already judge whether generated statements are supported by their sources. What differs here is the mechanism. The writer maintains an intermediate claim ledger, every decision is a specified deterministic check rather than a model judgment, the checks cover the whole review workspace, and the same checks drive an instrumented repair loop. The price is depth. A model-based support checker can judge meaning that my surface checks cannot, and comparing the two on the same reviews is part of the real-paper test in §8.

Integrity gates. Nam et al. [15] gate each stage of LLM-assisted clinical manuscript preparation with deterministic detectors that halt on failure. Their detectors target fabricated citations and numbers that drift from source tables, and they caught all 27 defects the authors injected, against 11 for a single-prompt LLM review. Academic Research Skills [16], a widely used Claude Code plugin for writing papers, adds an opt-in audit in which a language model judges whether each cited source supports its claim, and its documentation reports that no live calibration of that judge has been run yet. My gate follows each claim from source text through quote to synthesis sentence, and I test it against live writers, which may alter a planted error before the gate sees it.

Repair and judges. Self-Refine [17] and Reflexion [18] improve outputs by feeding critiques back to the model. My controller is an instance of this pattern with deterministic feedback and explicit stopping rules. LLM judges show position, verbosity and self-enhancement biases [19], and §5.3 adds a narrower point, that a judge given the task and the review text but not the claims or sources has no access to the evidence it would need.

3The gate

A review workspace W holds a protocol, a corpus of screened records, source texts for included papers, a claim set, a synthesis and a bibliography. Each claim is a tuple

c=(t,p,k,q,ρ),ρ∈{evidence,background} (1)

with claim text t, cited paper p, citation identity k (an author–year key or a reference number), supporting quote q and role ρ. Each cited synthesis sentence s carries a set of identities K(s). The gate checks five properties. Every quote occurs in its submitted source text (authenticity). Every claim names one corpus record, and its citation matches that record (binding). Every number in a claim occurs in its quote (grounding). Every cited synthesis sentence matches a verified claim in similarity, numbers, negation parity and direction words, and every uncited number is a finding (coverage). A sentence that states a number cannot rest on a background source (role).

Five things lie outside these checks, and §7 demonstrates the first four. The gate does not compare a claim's meaning with its quote beyond numbers, so a claim that drops the quote's “no” still verifies. An uncited sentence with no number is not checked. A background source may support a sentence that states no number. Numbers are compared as multisets, so “40 adults and 60 children” and “60 adults and 40 children” agree. And the visible author–year citation is checked against the claimed record only, not for uniqueness across the corpus.

I model the writing agent's own errors and assume no malicious attacker. I also assume the source texts and corpus metadata were acquired independently and are faithful. Authentication is against the submitted source bytes, the manifest records what was checked rather than proving it matches the publication, and nothing stops a repair round from editing a source file. I found no source edits in the published repairs. The agent may alter, trim, stitch or re-encode quotes, misattribute citations, add or alter numbers, misuse roles, and leave artifacts missing or malformed. The engine loads the workspace without following symbolic links, hashes every artifact into a canonical manifest, and runs four validators, for artifacts, claims, citations and PRISMA reporting, which Figure 2 divides into eight conceptual stages. A check that cannot complete emits validator_incomplete, which is critical. The exception is bibliography resolution, an optional external report. When the bibliography lists references and the report is absent or a resolver is unavailable, the gate records the warning citation_resolution_unavailable, which does not require repair, so a review can pass with that check unrun. An empty bibliography makes the check not applicable, and it raises nothing. None of the evaluated runs supplied the report.

Figure 2. The checks as eight conceptual stages. The engine runs its artifact, claim, citation and PRISMA validators in that order, and the claim validator performs binding, quote, number and coverage checks. Select a stage to see what it verifies and which reason codes it can raise. Stages marked “can invalidate” can emit critical findings.

3.1Quotes, citations and claim numbers

All comparisons run on normalized text

N(x)=lower(ws(dehyph(μ(NFKC(x))))) (2)

where μ maps typographic quotes and dashes to ASCII and removes soft hyphens, dehyph joins words split by a line-end hyphen, and ws collapses whitespace. NFKC folds ligatures and full-width forms [20] but leaves cross-script look-alikes such as Cyrillic “о” distinct from Latin “o” [21], so extraction noise is tolerated and confusable substitutions are not. A quote is authentic if one of three matchers accepts it. The exact matcher requires N(q) to occur in N(Sp) with its numbers aligned. The fuzzy matcher requires a source window w with

cov(q,w)=∑b∈M(q,w)|b||q|≥τq=0.90 (3)

over the matching blocks M of a sequence alignment, plus constraints on the unaligned text. No edit on the quote side may contain meaningful text, and no meaningful source text may sit inside the aligned span except page or header artifacts. Coverage alone would accept a quote with “not” or “%” deleted, and these constraints are what reject it. The per-sentence matcher accepts a multi-sentence quote only if its sentences match in source order, within a span of 3|q|, with only page or header artifacts between them, which rejects stitched quotes. Quotes under 40 characters or 8 words are rejected as too short to authenticate.

Each claim names a paper ID, which must select exactly one corpus record, and that record must be the quote's source. The claim's citation, an author–year key or a reference number, must then match that record. Surname particles are kept, so “de la Cruz” and “La Cruz” differ. A reference whose title matches two records is rejected as ambiguous, but two records sharing an author and a year are not detected. With Num(x) the multiset of numeric tokens in N(x) after citation spans are removed, a claim is grounded when

Num(t)⊆Num(q) (4)

with multiset inclusion. Tokens keep sign and decimals, so 6.4 and 64 differ, and years count as numbers.

3.2Synthesis coverage

Coverage links the synthesis to the claim ledger. The synthesis is split into prose sentences paragraph by paragraph, after removing headings, numbered-list markers and any reference section. Let V be the claims that passed §3.1. A unit u = (s, k) pairs a cited sentence with one of its identities and is covered when

M(s,k)={c∈V:k∈K(c)∧match(s,t)∧pol(s)=pol(t)}M(s,k)≠∅∧Num(s)⊆⋁c∈M(s,k)Num(t) (5)

where match(s, t) holds when a sequence-similarity ratio reaches τc = 0.80 or when one text, at 30 or more characters, contains the other, and M(s, k) is the set of matching claims. The polarity pol(x) pairs negation parity with the set of directional poles, so “rose” and “stronger” point up and “fell” and “weaker” point down. The union takes, for each number, its largest count across M(s, k). A background claim covers a sentence only when the sentence states no number. A prose sentence with no parsed citation that states a number yields coverage_number_missing, except inside inline code, file paths, URLs and DOIs.

Equation 5 is deliberately shallow. It cannot recognize a faithful paraphrase that falls below the similarity threshold and is not contained in its claim, which is why the writing skill asks each claim to restate its synthesis sentence. It rejects a cited sentence when no claim with its citation matches it in text and polarity, or when the sentence states numbers the matching claims lack. A sentence that drops some of its claim's numbers still passes. It does not represent scope, which quantity a direction word applies to, or which entity a number belongs to, and it compares the sentence with the claim, not with the quote.

3.3Status, score and repair

The status ignores the score. A review is invalid if any finding is critical, valid_with_warnings if any finding remains, and valid otherwise, so a workspace can score 91.7 and still be invalid. The score reports progress during repair. Findings map onto units in six dimensions with nominal weights wd (Table 1), dimensions with no units drop out, and with nd evaluated and md passed units

I=∑d∈Dappwd·100mdnd∑d∈Dappwd (6)

Table 1. Integrity dimensions and nominal weights. The resolver that produces the optional bibliography report consults OpenAlex [22], Crossref [23], Europe PMC and Retraction Watch [24], and any reported retraction is critical. The evaluated runs did not supply the report. Run by title on the 23 scholarly references of an earlier draft of this paper, all of which exist, the resolver verified 19. It did not find two arXiv papers whose titles contain a question mark, which breaks OpenAlex's phrase search. It returned two correct entries as mismatched, one because OpenAlex attaches its DOI to another record and one because the DOI's own registration carries a shorter title. In a review each of those four would be a critical finding, so a false alarm here forces a needless repair. Release 2.7.1 fixes the first three, and the resolver now verifies 22. Reporting checks follow a subset of PRISMA 2020 [25].

DimensionPropertyWeight
Quote authenticityauthenticity25
Citation and source bindingbinding20
Quantitative groundinggrounding20
Synthesis claim coveragecoverage, role15
Bibliography verificationresolution, retraction10
PRISMA and artifact completenessreporting, contract10

A review requires repair when it has a critical finding or one of three warnings that editing can fix (claim_needs_review, bibliography_incomplete, prisma_exclusion_reason_missing). The controller (Algorithm 1) returns each finding's reason code, severity, artifact and message, plus the flagged sentence for coverage findings, and never any expected answer or scorer data.

Algorithm 1. Bounded repair controller (R = 3 rounds, P = 2 rounds without progress)
  1. input workspace W, writer M
  2. F ← Validate(W); best ← I(F); seen ← {hash(W)}; stall ← 0
  3. if not RepairRequired(F) then return pass(F)
  4. for r = 1 … R do
  5.   W ← M.repair(W, Feedback(F), contract) ▷ public findings only
  6.   if W cannot be loaded then return invalid ▷ fail closed
  7.   F ← Validate(W)
  8.   if not RepairRequired(F) then return pass(F)
  9.   if hash(W) ∈ seen or I(F) ≤ best then stall ← stall + 1 else stall ← 0; best ← I(F)
  10.   seen ← seen ∪ {hash(W)}
  11.   if stall ≥ P then break
  12. return invalid if F has a critical finding else pass(F)

4Testing a gate against live agents

Offline, a detector is tested on fixtures it is handed. Inside a writing loop, the detector sees whatever the agent wrote, and the agent may silently fix the planted error, fail to produce a workspace at all, or introduce errors of its own. Every unit and offline test of my gate passed before the first live run, and that run still failed all 15 cases. This section describes how I test the gate so that its numbers mean what they say.

4.1Attack set

The public set holds 14 attack cases, one per family, and two controls. Case 014 was added for release 2.7.0 as a known gap. Its synthesis says a study “proved” what the source says it “suggested”, which keeps every number and polarity and so stays inside the coverage check (Eq. 5). One control is a clean review, and the other seeds a 73 percent figure where the source supports 7.3 percent. Papers, authors and findings are invented, so no model can recall them. Each content attack plants one change into an input the writer is told to preserve exactly, and the harness applies the four workspace attacks to the writer's first-pass workspace (Table 2, Figure 3).

Table 2. Attack families and the expected finding. Workspace attacks marked † make the workspace unloadable, so their expected outcome is invalid with no repair round. The case marked ‡ is a known implementation miss. Its scorecard still requires detection and repair, so it counts as unmet.

CaseFamilyPlanted changeExpected finding
001Look-alike letterCyrillic о (U+043E) inside a quotefabricated_quote
002Negation deletion“no” removed from a quotefabricated_quote
003Stitched quotetwo sentences joined across a gapfabricated_quote
004Wrong sourcequote credited to another authorcitation_identity_mismatch
005Ambiguous titlereference matching two recordscitation_ambiguous
006Compound surname“La Cruz” for “de la Cruz”citation_identity_mismatch
007Added number64% in the synthesis onlycoverage_number_missing
008Altered number64% where the claim says 6.4%coverage_number_missing
009Background rolea finding cited to a background sourcecoverage_role_invalid
010Missing artifact †refs.json deletedartifact_missing
011Malformed artifactclaims.json corruptedartifact_malformed
012Symlink †claims.json replaced by a linkartifact_symlink
013Path traversal †manifest entry outside the workspaceartifact_traversal
014Overstated finding ‡“suggested” restated as “proved”coverage_claim_missing
Figure 3. Specimens from the public attack set. Highlights and ellipses are added for display, and mark what changed between the source and the submitted review.

4.2Assessability

A detection miss should mean the detector missed. Two rules make that true. An attack case whose first pass never loaded for a reason the case did not plant is not assessable (first_pass_unloadable). So is a content attack whose first pass did not keep the planted input (attack_not_reproduced), meaning that some planted claim, synthesis sentence, source passage, corpus record or reference no longer appears, after normalization, in what the writer submitted. The check is containment, not equality, so a writer that appended text to a source could make a corrupted quote authenticate and still count as assessable. In all 65 loadable content-attack first passes across the seven runs, the sources match the planted text apart from surrounding whitespace. Both are excluded from confusion counts and reported separately. Without these rules, a weak writer reads as a weak detector. Claude Haiku, which I tried early, rarely produced a loadable workspace and registered 0% recall on attacks the detector never saw.

Three further rules keep runs comparable. Each case runs in a fresh workspace outside the repository and sees only the public skill, fixture and task. The harness retains every loaded snapshot with its bytes and hashes, and records the target commit, whether the tree was clean, the validator versions and the concrete model the CLI reported. A model error such as a usage limit is recorded under execution_errors, and --resume re-runs only those cases, on the same model and the same clean commit.

4.3Writers, runs and metrics

Claude Opus 5.5 ran in Claude Code's print mode with edit permission and read access to the staged skill. GPT Codex ran as gpt-6-astra in Codex's non-interactive mode with a workspace-write sandbox. Each writer ran the full set once per harness commit (Table 3). The repair prompt on eca0b37 carries only findings, while on 21c3777 it also points the writer at the skill's artifact contract. The run at 154c26f includes 9b51b90, which adds one sentence to the skill stating that a paper directory must be named by its record's key. Commit 5802823 is the state evaluated for release 2.7.0. It includes the template fix a868689 (§5.1) and adds case 014, and its two runs are published with the release.

Table 3. Evaluation runs. Codex runs were completed with --resume after usage limits, and the 154c26f run took two resumes. Opus was not rerun on 154c26f. Commits before 5802823 are preserved in the history of pull request #28, which reached main as the squashed commit 905a482.

Writer (resolved model)CommitRunCases
Claude Opus (claude-opus-5-5)eca0b37run_20261007_143121_20320315
GPT Codex (gpt-6-astra)eca0b37run_20261007_192519_55960515
Claude Opus (claude-opus-5-5)21c3777run_20261008_015639_16678715
GPT Codex (gpt-6-astra)21c3777run_20261008_070048_88983415
GPT Codex (gpt-6-astra)154c26frun_20261008_155105_86615615
Claude Opus (claude-opus-5-5[1m])5802823run_20261008_182253_95230816
GPT Codex (gpt-6-astra)5802823run_20261008_205523_88551516

Detection is measured on the first pass as reason-level confusion counts against each case's expectations. Repair success is the share of the 10 original repair-target cases (001–009 and 011) that end in a passing status within three rounds. Case 014, added for the release, also requires a repair under its scorecard, so across every release case that requires one the count is 10 of 11. Expected outcome met requires the expected final status and a repair-round count within the case's bounds. Repairable cases expect passing, which accepts valid or valid_with_warnings, because which of the two a correct repair reaches depends on incidental choices such as whether a bibliography was written. This rule was introduced after the eca0b37 runs, and Table 5 applies it to every run. The eca0b37 scorecards, which required the exact status, recorded 6 of 15 expected outcomes met for Opus and 4 of 15 for Codex. Throughout, valid and passing mean only that a workspace satisfies this validator's policy, not that the review is correct.

5Results

5.1Detection

On the release commit 5802823, each writer's run counted 13 true positives, 1 false negative, 14 true negatives and 7 false positives over the 14 attack cases. The miss is case 014, whose first pass ended valid with an integrity score of 100. On the 13 original families the gate raised the planted finding on the first pass in every run on every commit, and no case was marked not assessable. The true negatives count the expected-absent reason codes inside each attack case, not clean reviews, so they say nothing about specificity on real work.

Of the 7 false positives per run, 6 follow from the planted attack (Table 4). When a quote or citation fails, the sentence citing that claim correctly becomes uncovered, and the claim check cannot complete on a corrupted claims.json. The seventh, citation_resolution_unavailable in case 005, records the missing resolver report and persists after repair. Strict reason-level precision is 13/20 = 0.65. Excluding the six cascades gives 13/14 = 0.93, and 1.0 only if unavailable external checks are also excluded, a policy a real-paper test has to fix in advance. HALLMARK's observation that false positives decide a verifier's usability [4] applies here, and follow-on findings belong in the expectations of a real-paper test.

The confusion counts cover the attack cases only, and that hides one false positive the controls exposed. On 154c26f, Codex's first pass on the clean control placed its reference list under the heading “Annotated bibliography”. The gate skips only sections headed References, Reference list, Bibliography or Works cited, so it read the seven annotated entries as synthesis sentences and raised seven critical coverage_claim_missing findings on a review with no integrity error. Repair cleared them by adding an empty References heading, which hid the problem instead of fixing it. The cause was the skill's own output template, which asked for an annotated bibliography that the gate deliberately checks as prose, since annotations can carry findings. Commit a868689 replaces it with a references list and moves each study's contribution into the checked synthesis. On 5802823, which includes that fix, Codex's clean control passed on the first pass.

Opus's clean control on 5802823 failed its first pass for two other reasons, with an integrity score of 51.9. Opus repeated a claim under several quotes, each holding only some of the claim's numbers, and the gate checks every claim entry against its own quote. That raised 7 critical claim_needs_review findings and left 7 sentences uncovered. Commit 2329249 now tells the writer that each claim's numbers must appear in its own quote and that a sentence drawing on several quotes must be split. The other 4 findings are a gate bug. The synthesis listed its open questions as a numbered list, and the paragraph splitter read each marker, “1.” to “4.”, as a sentence holding an uncited number. Commit cb54321 fixes the splitter, and re-validating the retained workspace with it removes all four while the 14 multi-quote findings remain. Repair cleared every critical finding in one round, leaving the resolver warning, and both runs count as meeting the control's expected outcome because it ended in a passing status. A real-paper test should score controls for false positives on the first pass.

Table 4. First-pass false positives on the attack cases on commits 21c3777 and 5802823, identical for both writers. Six are cascades of the planted error, and one records an external check that was not run.

FindingCasesCountCause
coverage_claim_missing001, 002, 003, 005, 0065the cited claim failed, so its sentence is uncovered
citation_resolution_unavailable0051no citation report supplied, so it is recorded as unresolved
validator_incomplete0111claim check cannot run on a corrupted file

5.2Repair with the contract and skill access

With findings alone, writers repaired by guessing. Asked to fix a malformed claims.json, Opus rebuilt it in a schema it invented (id, citations, evidence[]). Told that a citation role was invalid, it chose supporting, a role that does not exist. Once the repair prompt pointed at the artifact contract, repair success rose from 8 to 10 of 10 for Opus and from 4 to 10 of 10 for Codex (Table 5, Figure 5). The change was more than a sentence of prompt. Between eca0b37 and 21c3777, 16 files changed, and the repair step also gained the staged skill and permission to read it. Each configuration ran once. The combined change coincided with more passing repairs, and the comparison cannot say which part of it mattered.

Repair success is judged by the same gate that supplies the feedback, and passing does not guarantee a good repair. In the release run, Opus repaired case 009 by replacing “42% of sessions” with “a share of sessions”. That satisfies the role check by removing the number, and the review loses the information along with the error. A real-paper test should score repairs independently for correctness and retained information.

Table 5. Outcomes per run. Detection counts families flagged on the first pass, and repair counts the 10 original repair-target cases ending in a passing status. Expected-met counts apply the passing rule to every run (§4.3). On 5802823 the one unmet outcome in each run is case 014.

WriterCommitFamilies detectedRepaired (of 10)Unloadable invalid (of 3)Controls passing (of 2)Expected met
Opuseca0b3713/1383213/15
Codexeca0b3713/134307/15
Opus21c377713/13103215/15
Codex21c377713/13103013/15
Codex154c26f13/13103215/15
Opus580282313/14103215/16
Codex580282313/14103215/16

On 21c3777, Codex's two misses were the controls, whose first passes failed to load. Codex named paper directories SYN01 and so on while each record's key was a slug of its title, and the validator links a record to its source only by key or ID. The skill had never stated that rule. Commit 9b51b90 states it, and on 154c26f, which includes it, both controls loaded and Codex met all 15 expected outcomes, with every repairable case fixed in one round.

Figure 4. Final state of every case in every run. A tick marks an expected outcome met, which is a passing status within the allowed one to three repair rounds for repairable cases, a passing status for controls, and invalid for the three unloadable workspaces. Case 014 ends passing but is unmet, because its scorecard requires at least one repair round and the gate never triggered one. Case 014 exists only on 5802823, and a dash marks a case a run did not include.
Figure 5. Repairable cases fixed (of 10) without and with the artifact contract in the repair prompt, and on the release commit. Hover a bar for its run.

Repair is not monotonic. On the seeded-number control, Opus's score on 21c3777 fell in round 2 before reaching 90 in round 3, and Codex on eca0b37 held at 86.2 for three rounds and ended invalid (Figure 6). The no-progress rule in Algorithm 1 tolerates one bad round for this reason.

Figure 6. Integrity score (Eq. 6) through repair on the seeded-number control, for three selected runs. The workspace also loaded on Codex at 154c26f and in both release runs. Hover a round for its values.

5.3An evidence-blind quality judge cannot stand in for the gate

The harness also scores each synthesis with a rubric judge, the common way to grade generated reviews. The judge uses the same model as the writer and weights research quality, analytical quality and structure 70/20/10. It reads the task prompt and synthesis.md, never the quotes, claims or sources, so a fabricated quote in claims.json is outside its input by construction. For most number attacks the judge sees the wrong number but has no source to compare it with. The seeded-number control is an exception, since its task prompt states both 73 and 7.3 percent.

I then asked whether the judge's scores carry any signal on my cases. In 5 of the 10 repaired cases, repair left the synthesis byte-identical, changing only claims.json in four and protocol.md and refs.json in the fifth, yet the in-run quality score moved by as much as 17.8 points. I re-scored with the production judge, invoked as claude:opus, 3 more times each the first-pass and final syntheses of all 10 repaired cases on 21c3777, and the clean control 5 more times (Table 6). Those 20 snapshots hold 15 distinct texts, because five syntheses were unchanged by repair. The full clean review scored within 3 points across 6 judgments. The attacked syntheses, one or two sentences each, scored with a pooled standard deviation of 9.6 points on identical text, and one varied from 27.5 to 66.0. On these short texts the judge is unreliable, and it cannot see an integrity error that lies in artifacts it is not given. One clean review is too little to say how stability depends on length.

Table 6. Quality-judge scores on byte-identical text from the Opus run on 21c3777, grouped by text content. Re-scores invoked the judge as claude:opus, and the model that alias resolved to was not recorded. Each snapshot contributes its in-run score plus three re-scores, so the five texts that repair left unchanged have 8 judgments. The pooled SD weights each text by its degrees of freedom.

TextsLength (chars)Judgments per textSD (points)Median rangeMax range
Clean control (1 text)5,09061.02.92.9
Attacked first pass and final (15 texts)96–1354 or 89.6 (pooled)18.638.5

6What live runs exposed

Most failures in the first live runs came from gaps between what the harness assumed and what an agent does with real instructions (Figure 7). Two were rules the validator enforced and the skill never stated, a required project file and paper directories named by record key. Several were parsing false positives that appeared only on real model output, where headings, reference lists and file paths produced spurious uncited numbers. One was the measurement gap that §4.2 closes. Later runs found two more contract gaps, a skill template that asked for exactly the section the gate rejects and claims whose numbers were spread across quotes, and one parsing bug, numbered list markers read as numbers (§5.1). The general lesson is that a validator's implicit contract has to be written down for the writer, and the only reliable way I found to discover that contract was to run the gate against live agents.

Figure 7. Harness and skill failures exposed by live runs, 6–8 October 2026, with the commit that fixed each. The date column gives when each failure appeared, and the fixes landed through 11 October. Expand an entry for details.

7Limitations

Circularity. I wrote the attacks and the detector, and each family was built with its check in mind. Detecting 13 of 13 families shows that the gate catches what it was designed to catch, and says nothing about errors outside those families. The one family I built outside its checks, case 014, it missed.

Synthetic, small cases. Papers are invented to rule out memorization, and most attacked syntheses are one or two sentences. Real reviews bring PDF noise, tables, messy citations and long prose that the set barely exercises.

One run per configuration. Repair outcomes varied between runs of the same writer, so the counts describe the observed runs. I do not estimate model-level differences or isolate intervention effects.

Expectations set by me. The scorecards and passing labels are mine, Table 4 shows they omit follow-on findings, and the passing rule was adopted after the first runs and applied to them retrospectively (§4.3).

Self-judged repair. Repair success is decided by the gate that gave the feedback, and a repair can pass by deleting information (§5.2). The content attacks also ask the writer to preserve supplied text exactly, so they test packaging and repair of constructed errors, not errors that arise naturally in writing.

Strictness. Counting every uncited number, years included, flags some values a human would accept. The test sketched in §8 scores these flags as their own unit type so their cost is visible.

Unmeasured meaning. The gate checks surface agreement. Some overstatements keep every checked number and polarity and stay similar enough to their claim to pass Equation 5, as case 014 did in both release runs.

Unchecked statements. I ran four edits of the repaired case 001 workspace at fc9061c, whose gate code is unchanged since cb54321, and each returned valid with integrity 100. Changing the claim and synthesis to “found a change” while the quote still says “found no change” passed, because the claim is compared with its quote only on numbers. Appending the uncited sentence “This treatment conclusively cures dementia.” passed, because uncited sentences are checked only for numbers. Giving a cited qualitative finding a background role passed, because the role check applies only to numeric sentences. Adding “among 40 adults and 60 children” to the source, quote and claim and writing “60 adults and 40 children” in the synthesis passed, because numbers are compared as multisets. The workspaces have an empty bibliography, so the resolver check was not applicable. Codex found all four while reviewing a draft of this paper, and I reproduced each. These are the gate's largest gaps, and the claim-to-quote polarity check is the first I plan to close.

Trusted sources. Authentication is only as good as the submitted source text. Extraction errors, a wrong source file, or a repair that edits a source and a claim together are outside the threat model.

8What a real-paper test would need

The pilot leaves four questions open, one for each main limitation. Below them is a draft of how I would run a test on real papers to answer them. It is a sketch, and I have not scheduled it.

  1. Accuracy on real reviews. Against independent human labels, what are the gate's precision and recall for each unit type, including uncited-number units?
  2. Errors outside the design. How often do agent-written reviews of real papers contain integrity errors that none of the 14 families anticipates, and does the gate catch them?
  3. Judges on full-length text. On full reviews, do evidence-blind quality scores track human integrity labels at all, and how does a source-aware model judge compare with the gate?
  4. Repair at scale. In repeated, controlled comparisons across more writers, does pointing the repair step at the contract and the skill improve repairs scored independently for correctness and retained information, with intervals around each rate?

The test would use 20 real papers, five in each of four domains, split per domain into two development and three test papers. Public inputs would fix the split, so no one picks which papers are held out. A split key

κ=SHA-256(“claim-verifier-split-v1”‖0x00‖β‖h) (7)

combines the ASCII prefix and a zero byte with a 64-byte randomness-beacon value β [26], published after the plan is made public, and the SHA-256 digest h of the sealed construction archive, both hex-decoded to raw bytes. A known-answer fixture in the repository fixes the expected key. Within each domain, papers are ordered by a hash of κ and their IDs, and the first two become development papers. Manifests use RFC 8785 canonical JSON [27]. Figure 8 runs the split in the browser and reproduces the reference implementation byte for byte. A reproducible draw keeps me from choosing the held-out papers, but it does not by itself show that the cases were built independently of the gate. Two annotators, blind to verifier output, would label every claim and coverage unit and mark any factual assertion in the synthesis that no unit covers, including uncited qualitative statements, claims that contradict their quote, and information a repair removed, with agreement reported as raw agreement and Cohen's κ [28]. Uncited sentences that state a number would form their own unit type, labelled exempt when the number describes the review itself, restated when a cited sentence states the same number and finding, and unsupported otherwise.

Figure 8. The canonical split for placeholder paper IDs. Changing one hex digit of β reassigns the split.

9Conclusion

Reference checkers ask whether a citation exists, and model judges ask whether a source supports a statement. A review written by an agent also has to keep its own prose inside its evidence. Part of that question can be checked deterministically. My gate does so for quotes, claim numbers, and the numbers, negation parity and direction words of cited sentences, inside the writing loop. It flagged all 13 attack families it was designed for with two frontier writers, missed the overstated finding it was not designed for, and with one run per configuration, repair passed all 10 original repair-target cases for both writers once the repair step pointed at the artifact contract and the skill, against 8 and 4 before. Testing it against live agents exposed failures that no offline test had found, and adversarial review of the implementation exposed gaps I had not stated. Whether the gate holds on real papers, and how much of the remaining question a model must answer, is what the test sketched in §8 would measure.

AAppendix. An interactive gate

Figure 9 reimplements four checks from §3.1 and §3.2 in the browser, for illustration. It uses only the exact matcher after normalization, without the fuzzy and per-sentence matchers, and omits citation binding and the workspace contract. It also differs from the gate in four smaller ways. It rejects any non-Latin letter in a quote, even one present in the source, it skips the 40-character and 8-word minimum, it does not check number alignment within the quote, and its direction vocabulary is shorter. Its verdict means only that these four checks pass. Edit any field and the checks rerun.

Figure 9. Simplified live gate covering quote authenticity (Eq. 2, exact matcher, with cross-script letters reported as look-alikes), claim grounding (Eq. 4), and the number and polarity conditions of synthesis coverage (Eq. 5).

References

  1. W. H. Walters and E. I. Wilder. Fabrication and errors in the bibliographic citations generated by ChatGPT. Scientific Reports 13, 14045 (2023).
  2. K. Shi, W. Sun, Z. Zhang, L. Sun, N. V. Chawla and Y. Ye. CiteAudit: you cited it, but did you read it? A benchmark for verifying scientific references in the LLM era. arXiv:2602.23452 (2026).
  3. K. Khajavi, S. Sadeghi, R. Adhikari and A. Tessier. CiteCheck: retrieval-grounded detection of LLM citation hallucinations in scientific text. arXiv:2605.27700 (2026).
  4. P. Reizinger and W. Brendel. HALLMARK: diagnosing three failure modes in LLM citation verifiers. arXiv:2607.18360 (2026).
  5. F. Badalova and P. Mayr. Detecting hallucinated and suspicious citations: what current tools can and cannot do. arXiv:2607.22693 (2026).
  6. H. Rashkin, V. Nikolaev, M. Lamm, L. Aroyo, M. Collins, D. Das, S. Petrov, G. S. Tomar, I. Turc and D. Reitter. Measuring attribution in natural language generation models. Computational Linguistics 49(4), 777–840 (2023).
  7. T. Gao, H. Yen, J. Yu and D. Chen. Enabling large language models to generate text with citations. In Proceedings of EMNLP (2023).
  8. S. Min, K. Krishna, X. Lyu, M. Lewis, W. Yih, P. W. Koh, M. Iyyer, L. Zettlemoyer and H. Hajishirzi. FActScore: fine-grained atomic evaluation of factual precision in long form text generation. In Proceedings of EMNLP (2023).
  9. D. Wadden, S. Lin, K. Lo, L. L. Wang, M. van Zuylen, A. Cohan and H. Hajishirzi. Fact or fiction: verifying scientific claims. In Proceedings of EMNLP (2020).
  10. K. Wu, E. Wu, K. Wei, A. Zhang, A. Casasola, T. Nguyen, S. Riantawan, P. Shi, D. Ho and J. Zou. An automated framework for assessing how well LLMs cite relevant medical references. Nature Communications 16 (2025). doi:10.1038/s41467-025-58551-6.
  11. H. Onweller, E. Lumer, A. Huber, P. Ramchandani, V. K. Subbiah and C. Feld. Cited but not verified: parsing and evaluating source attribution in LLM deep research agents. arXiv:2605.06635 (2026).
  12. S. Imran and D. S. Solanky. ResearchQA: benchmarking citation-grounded question-answering on scientific papers. arXiv:2607.11074 (2026).
  13. T. Goo, J. Kim, K. Han, G. Jo, J.-S. Kim and T.-H. Kim. Evaluating and guarding citation faithfulness in agentic scientific synthesis. arXiv:2607.20527 (2026).
  14. E. Hirsch, D. Wan, H. Wang, E. Stengel-Eskin, M. Bansal and I. Dagan. Who is the agent to blame? Localizing faithfulness and citation mistakes in agentic deep research. arXiv:2608.24306 (2026).
  15. Y. Nam, J. Jeong and N. Kim. Deterministic integrity gates for LLM-assisted clinical manuscript preparation: an auditable biomedical informatics architecture. arXiv:2606.09500 (2026).
  16. C.-I. Wu. Academic Research Skills for Claude Code, version 3.23.0. Zenodo (2026). doi:10.5281/zenodo.20696614.
  17. A. Madaan, N. Tandon, P. Gupta, S. Hallinan, L. Gao, S. Wiegreffe, U. Alon, N. Dziri, S. Prabhumoye, Y. Yang, S. Gupta, B. P. Majumder, K. Hermann, S. Welleck, A. Yazdanbakhsh and P. Clark. Self-Refine: iterative refinement with self-feedback. In Advances in NeurIPS (2023).
  18. N. Shinn, F. Cassano, A. Gopinath, K. Narasimhan and S. Yao. Reflexion: language agents with verbal reinforcement learning. In Advances in NeurIPS (2023).
  19. L. Zheng, W.-L. Chiang, Y. Sheng, S. Zhuang, Z. Wu, Y. Zhuang, Z. Lin, Z. Li, D. Li, E. P. Xing, H. Zhang, J. E. Gonzalez and I. Stoica. Judging LLM-as-a-judge with MT-Bench and Chatbot Arena. In Advances in NeurIPS (2023).
  20. Unicode Consortium. Unicode Standard Annex #15: Unicode Normalization Forms.
  21. Unicode Consortium. Unicode Technical Standard #39: Unicode Security Mechanisms.
  22. J. Priem, H. Piwowar and R. Orr. OpenAlex: a fully-open index of scholarly works, authors, venues, institutions, and concepts. arXiv:2205.01833 (2022).
  23. Crossref. REST API and metadata documentation. crossref.org.
  24. Retraction Watch Database, distributed through Crossref. retractionwatch.com.
  25. M. J. Page et al. The PRISMA 2020 statement: an updated guideline for reporting systematic reviews. BMJ 372, n71 (2021).
  26. J. Kelsey, L. T. A. N. Brandão, R. Peralta and H. Booth. A Reference for Randomness Beacons: Format and Protocol Version 2. NISTIR 8213 (draft), National Institute of Standards and Technology (2019).
  27. A. Rundgren, B. Jordan and S. Erdtman. JSON Canonicalization Scheme (JCS). RFC 8785, IETF (2020).
  28. J. Cohen. A coefficient of agreement for nominal scales. Educational and Psychological Measurement 20(1), 37–46 (1960).
Data and code. Code, attack set and harness are in the co-researcher repository (github.com/poemswe/co-researcher), release 2.7.0. The two release runs on 5802823 are published with their snapshots and repair rounds in evals/published/runs/. The paper's evidence package is in evals/published/paper/. It holds the five earlier runs in Table 3, which also carry the trajectories in Figure 6, the 65 judge re-scores behind Table 6 with the script that recomputes the table, and the four §7 counterexample workspaces with their gate reports. Its README maps each table, figure and section to the runs and files behind it, and lists what the package does not hold, such as the earliest runs behind Figure 7. The re-score records keep scores and labels but not the raw judge responses. Reported pilot statistics were recomputed from these artifacts.