Skip to content

fix(agents): reviewer confirms requested texts when there is no probe - #12454

Merged
MarkusNeusinger merged 5 commits into
mainfrom
fix/review-requested-texts-without-probe
Oct 29, 2026
Merged

MarkusNeusinger merged 5 commits into
mainfrom
fix/review-requested-texts-without-probe

Conversation

@MarkusNeusinger

Copy link
Copy Markdown
Owner

Summary

  • A render without a text probe (ggplot2, and altair, pygal and lets-plot among the Python libraries) could not check a text the user asked for, so every such request shipped as needs attention with "the requested texts could not be checked", although the image was right (ggplot2 live test on anyplot.ai, 2026-10-29). Owner decision of 2026-10-29: the reviewer now gets the requested texts and confirms them in the image, in the review call it already makes (no new model call).
  • RuntimeAdapter.review_texts gates it (R: on; Python: on for altair, pygal, letsplot, off for matplotlib, seaborn and plotnine, which keep the probe's check unchanged). ReviewRequest.expected_texts carries the texts only for such a render, under a fixed heading, fenced as user text. The reviewer reports a text it cannot find as an SC-04 (or SC-02) line in the prescribed form the requested text "<text>"; grounding.reviewed_misses reads those lines back, and the pipeline treats them like the probe's misses (a repair under AGENT_EXPECT_CHECK=repair, a residual line if no round fixes it). The "could not be checked" note stays only when no readable review answered.
  • The Gemini 3.8 Flash pre-PR check found two misreadings in reviewed_misses (a requested text with quotes of its own was never named; a passage quoted for what the image shows was named as missing) and a dropped number format; all three are fixed in f29100d with tests. Its third finding (no checklist-mode flow test) is left: the checklist path calls the same reviewed_misses, and the catalogue mode is the default.

Plan

N/A (follow-up of the ggplot2 live test; agentic/specs/261024-agent-all-libraries.md covers the R runtime)

Test plan

  • uv run ruff check agents tests && uv run ruff format --check agents tests
  • uv run --extra typecheck --extra agents mypy agents (115 files, clean)
  • uv run --extra agents --extra test pytest tests/unit/agents -q -n auto (13,090 passed, 27 skipped for plotting libraries not installed locally)
  • Flow tests: texts confirmed → ok without a note; a reported miss → one repair round although the score passed; an unfixed miss in repair and note mode → the reviewer's SC-04 line; an unreadable review → the note stays; probe renders → the review request carries no texts
  • uv run python -m tools.changelog check --base origin/main
  • After the deploy: in the admin chat, ask a ggplot2 plot for an axis label and check that the version ships ok without the "could not be checked" note

MarkusNeusinger and others added 3 commits October 29, 2026 19:43
…as no probe

R writes no probe, so every ggplot2 request for a specific text (a title,
an axis label) shipped as needs_attention with UNVERIFIED_LINE, although
the image showed the text (live test 2026-10-29, line-basic, "Temperatur
(°C)"). Owner decision of 2026-10-29: without a probe, the reviewer that
already reviews every render confirms the texts in the image.

Design (decided and documented here):

- Gate: a new RuntimeAdapter.review_texts flag. RRuntime sets True;
  PythonRuntime keeps False, so every Python run is unchanged (see the
  finding below). The flag is read only when the render has no drawn
  texts (drawn is None) and AGENT_EXPECT_CHECK is not off.
- Transport: ReviewRequest.expected_texts, filled only for such a render.
  Both request renderers add a fixed heading (REVIEW_EXPECTED_HEADING)
  and the texts fenced as <user_message>; an empty list adds nothing, so
  the reviewer's static prompts (reviewer.md, reviewer_catalogue.md,
  scorer.md), its output schemas and every review request of a render
  with the probe are byte-identical. No new model call: the texts ride
  in the review the pipeline already makes.
- Answer shape: the existing defect grammar. The reviewer reports a text
  it cannot find as one finding under SC-04 (SC-02 for a number format in
  the catalogue rubric; the checklist has no SC-02, so SC-04 there) whose
  observed part quotes it. grounding.reviewed_misses reads these back
  from every line of the answer, whatever the points: a line names a
  requested text when a quoted passage normalises to it (a quoted
  "Temperatur (°C)" never names a requested "Temperatur"); a line without
  quotes names each requested text it contains whole.
- Status and repair mirror the probe's miss: under AGENT_EXPECT_CHECK=
  repair a reported miss sends the round to the repair whatever the
  points (as a VISIBLE_DEFECT_IDS line does), the render is not clean for
  AGENT_SHIP_BEST, and a shipped miss keeps the reviewer's line as a
  residual line plus the text in PlotShows.requested_not_found. Under
  note it is the residual line only.
- UNVERIFIED_LINE is set at render time as before and cleared only by a
  readable review of that render, so an unreviewed render (budget,
  deadline, unreadable answer, not_rereviewed, padded canvas) keeps it:
  never a silent pass. A readable review that names no miss counts as
  confirming the texts.

Finding for the owner: altair, pygal and lets-plot (Python) write no
probe either and still get UNVERIFIED_LINE for every requested text.
Moving them to the reviewer is setting PythonRuntime.review_texts (or a
per-library value) to True, which changes their review requests, so it
is left to the owner.

Tests: reviewed_misses (quotes, typographic quotes, shorter-in-longer,
SC-02, other ids), finish() with a confirmed and a missed text, the
request rendering in both modes and its absence without texts, the
runtime flags, and catalogue flow runs without drawn texts: confirmed
-> ok; missed -> repair round despite passing points; unfixed miss in
repair and note mode -> needs_attention with the reviewer's line;
unreadable review -> UNVERIFIED_LINE stays. The probe flow tests now
assert that the review request carries no texts.

Docs: docs/concepts/agent-network.md, the AGENT_EXPECT_CHECK setting,
the R runtime docstring, and a changelog fragment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…t too

altair, pygal and lets-plot render without matplotlib and write no probe,
so every requested text there got the same "could not be checked" note as
ggplot2. The owner's decision (reviewer confirms the texts when there is no
probe) covers them: `PythonRuntime.review_texts` is now a property by
library (`TEXTLESS_LIBRARIES`), and `RuntimeAdapter.review_texts` a
read-only protocol member. matplotlib, seaborn and plotnine keep the
probe's check; the Python prompts are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…form

The Gemini Flash pre-PR check found two ways `reviewed_misses` misread a
review line: a requested text with quotes of its own (`Zone "A"`) was
split by the quote pattern and never named (a silent pass), and a line
that also quoted what the image shows instead ("(the y axis reads
"Score")") named that text as missing when the user had asked for it too.
A line that quotes only the number it saw dropped a missing number format.

A line in the heading's own form, `the requested text "<text>"`, now names
exactly the texts it cites so, compared with every quotation mark kept
(`_norm(quotes=True)`). Other lines keep the quoted-passage rule, and fall
back to whole-text containment for a text with quotes of its own or a
number format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
Copilot AI lite review requested due to automatic review settings October 29, 2026 18:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The checklist branch remains insufficiently covered because its distinct Verdict schema and defect parsing are only exercised through shared helpers, so end-to-end tests for confirmed text, reported misses, and unreadable reviews are needed.

1 open issue
What changed in this PR

This pull request enables reviewer-based verification of requested text for renders without text probes, including ggplot2, Altair, Pygal, and Lets-Plot. Reported missing text is propagated through repair and result grounding, while existing probe-based behavior remains unchanged for other runtimes.

Changes:

  • Adds runtime opt-in support for reviewer-backed text verification.
  • Carries expected texts into eligible review requests and parses reported misses.
  • Integrates missing-text findings into repair and residual-result handling.
  • Adds tests, documentation, and a changelog entry.
File Summary Review findings
tests/​unit/​agents/​runtime/​test_runtimes.py Verifies runtime review-text configuration. No findings.
tests/​unit/​agents/​runtime/​test_grounding.py Tests reviewer-line parsing and prompt construction. No findings.
tests/​unit/​agents/​runtime/​test_catalogue_flow.py Tests confirmation, repair, residual, and unreadable-review flows. No findings.
docs/​concepts/​agent-network.md Documents reviewer-backed requested-text verification. No findings.
changelog.d/​review-requested-texts.md Records the user-visible fix. No findings.
agents/​anyplot/​settings.py Documents expanded expected-text checking behavior. No findings.
agents/​anyplot/​schemas.py Adds expected texts to review requests. No findings.
agents/​anyplot/​render/​runtimes/​r.py Enables reviewer checks for R renders. Nit (1 vote): Runtime prompt instructions remain stale and should be updated with prompt tests.
agents/​anyplot/​render/​runtimes/​python.py Enables reviewer checks for supported probe-less Python libraries. No findings.
agents/​anyplot/​render/​contract.py Extends the runtime adapter contract. No findings.
agents/​anyplot/​pipeline.py Integrates reviewer text checks into rendering, repair, and result handling. Moderate (1 vote): Checklist defect limits can drop requested-text findings. Nit (4 votes): The checklist branch lacks end-to-end flow coverage.
agents/​anyplot/​grounding.py Parses reviewer-reported requested-text misses. Moderate (1 vote): Fallback parsing can misclassify unrelated quoted passages as missing requested text.

Review effort: Lite

Comment thread agents/anyplot/pipeline.py Resolved
…to end

Copilot's review of #12454 (and the Flash pre-PR check): the checklist
reviewer's Verdict schema was exercised only through the shared helpers.
Three flow cases now run it: a confirmed text ships ok, a reported miss
goes to the repair, and an answer that is no verdict keeps the note.
The R adapter's requested_check slot no longer says the result marks the
texts as not checked: the reviewer looks for them now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
@codecov

codecov Bot commented Oct 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.14286% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agents/anyplot/grounding.py 96.77% 1 Missing ⚠️
agents/anyplot/render/contract.py 66.66% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@MarkusNeusinger
MarkusNeusinger merged commit 6a070ed into main Oct 29, 2026
18 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the fix/review-requested-texts-without-probe branch October 29, 2026 19:19
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.

2 participants