Skip to content

fix(agents): live round 8 (short columns, color-scale hints, to_long names) - #12206

Merged
MarkusNeusinger merged 5 commits into
mainfrom
fix/agents-live-round-8
Oct 16, 2026
Merged

MarkusNeusinger merged 5 commits into
mainfrom
fix/agents-live-round-8

Conversation

@MarkusNeusinger

@MarkusNeusinger MarkusNeusinger commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

Live test round 8 findings for the admin-only "Use with my data" chat.

  • R8-3, invented "remainder" row (the root cause of R7-6 recurring). I reconstructed what the root sees for energiemix.csv. The profile's top (five values, all ties, so the first five rows) and the five sample rows both stopped at Biomasse. Übrige appeared in no root-visible channel: the session block carries no cells, and the pipeline result carries no categories. The root therefore explained its appearance in the donut as a ring-filler.

    • A text or boolean column with at most 12 distinct values (schemas.MAX_LISTED_VALUES, listed_values) lists every value in top; any other column lists its five most frequent. unique above the count says the list is partial.
    • The dataset judge (opening.judged_view) reads the same values.
    • briefs.trimmed_profiles drops the values past five before the rest of the top values.
    • root.md says when top is complete and that every listed category is the user's data.
    • The stress-inject-long-cell generator now makes 14 products, so its injected cell still stays past the listed values, as its bound says.
  • R8-2, heatmap color scale. Before this change, the readiness scan gave seaborn heatmap-basic only a synthetic-data hint. It now has two more coupling categories:

    • color-scale: vmin, vmax, center, vcenter, clim, and plotly's zmin, zmax and zmid; levels as a list; colorbar ticks in cbar_kws or colorbar(ticks=); cbar.set_ticks; set_clim; a norm's range, center or boundary arguments built from literals, but never an encoding argument such as PowerNorm's gamma. The 0 rule applies, and cmin is not flagged (it is a hist2d count threshold).
    • colorbar-position: cbar_pos.

    heatmap-basic in seaborn now gets center=50, the cbar_kws ticks, vmax=100 and cbar_pos=(...) named. Of the 650 matplotlib and seaborn files in the catalogue, 38 get a color-scale hint and 2 a colorbar-position hint.

  • R8-1, .to_long() names.

    • The new columns get English names: Weekday, Month or Year when every melted header is a weekday, month or year, else Category, plus Value (shape.LONG_NAMES).
    • The names never depend on the session language. After review, this replaced per-language names, which changed under the offer the page had cached when the language changed. The data panel around the offer is English anyway, and the adapter writes the plot's labels in the plot language.
    • A name an input column already has gives way to the role's name, then to a numbered one. The names never decide the offer and never reach pandas' melt as a duplicate. prepare.pivot_longer also refuses a melted column's name (invalid_operation).
    • .to_long() binds the new columns to the roles they were made for (LongSuggestion.bindings → bindings.filled_bindings, the fill half of carry_bindings). Name matching alone would have bound Category to bar-grouped's category. A sweep of 122 spec/table pairs gives the same bindings as the old role-name columns.
    • root.md: the summary offers a rename when the notes or the file name say what the values measure.

Decision on R8-2(b) (forced-repair ids)

The attribution log of that run (session cf336aad9739, seaborn) shows that the reviewer did file the defects, and the repair ran:

  1. Round 1 filed VQ-04 and VQ-05 (technical score 0.945), so a repair ran.
  2. Repair attempt 3 (full code) failed on drift:theme_token; attempt 4 applied one edit.
  3. Round 2 filed VQ-05 and VQ-07. The render shipped needs_attention with those two lines, which the reply quoted.

VQ-05 is already in VISIBLE_DEFECT_IDS, so widening the set would not have changed this run. The cause was the coupled code, which the new hints address up front. VISIBLE_DEFECT_IDS stays unchanged.

Plan

N/A

Test plan

  • uv run pytest tests/unit tests/integration -n 6 (12,004 passed before the review fixes; tests/unit/agents tests/unit/api 8,340 passed after them)

  • ruff check ., ruff format --check ., mypy api core agents and the changelog check pass.

  • New tests cover:

    • The energy-mix profile lists Übrige, and 12 distinct values are listed in full while 13 give the five most frequent.
    • The judge sees every value of a fully listed column, the trim order holds, and the schema caps top at 12.
    • The readiness rules (flagged and not flagged, norm encoding arguments included) and the heatmap-basic seaborn catalogue file.
    • .to_long() names by header kind, names that give way to input columns, and a route that never fails on them.
    • label_siblings sees every offered table, and the bindings on bar-grouped stay pinned.
    • In the service flow, a language change between the paste and .to_long() leaves the offer unchanged.
  • The prep eval (Vertex eu, Claude Haiku 5.5, root prompt changed) passed: 48 of 51 cases matched exactly (94.1 %), 153 calls, $0.114. The misses are model variance on cases that this PR does not touch:

    • de-hard-kette-gesamtzeile left out drop_columns.
    • de-klasse-aus-vorzeichen used the labels 1 and 2.
    • en-growth-column added a sort.

    The review fixes changed one example list in root.md (Weekday, Category, Value).

  • Live: re-run donut-basic and matplotlib with energiemix.csv, and check that the reply does not call Übrige added.

  • Live: run heatmap-basic and seaborn with besucher_heatmap.csv after .to_long(), and check for columns Weekday and Value, a color scale derived from the data, and the colorbar beside the plot.

…or-scale hints, .to_long() names)

- R8-3: a text column with at most 12 distinct values lists every one in the profile's
  `top` (else the five most frequent); the dataset judge reads the same values and the
  trimmer drops the values past five before the rest. The root never saw `Übrige`, the
  sixth row of a six-row energy mix, and called it a row the plot added.
- R8-2: the readiness scan names literal color-scale limits, centers, levels and colorbar
  ticks (`color-scale`) and `cbar_pos` (`colorbar-position`) as adapter hints.
- R8-1: `.to_long()` names its columns in the session language (Wochentag/Monat/Jahr or
  Kategorie, and Wert) and binds them to the roles they were made for.

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

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

Generated value-column names can collide with input headers and cause .to_long() to return HTTP 500.

1 open finding
What changed in this PR

Improves data interpretation and plot adaptation in the admin-only agent chat.

Changes:

  • Lists all categories in short columns and keeps dataset judging aligned.
  • Adds readiness hints for fixed color scales and colorbar positions.
  • Localizes .to_long() column names while preserving intended role bindings.
File Description
tests/​unit/​agents/​test_schemas.py Tests expanded top-value limits.
tests/​unit/​agents/​runtime/​test_stress_bounds.py Tests profile trimming order.
tests/​unit/​agents/​runtime/​test_service_flow.py Tests localized conversion and undo.
tests/​unit/​agents/​runtime/​test_dataset_judge.py Tests judge/profile value parity.
tests/​unit/​agents/​evals/​test_stress.py Updates expected profile size.
tests/​unit/​agents/​data/​test_shape.py Tests localized names and bindings.
tests/​unit/​agents/​data/​test_prepare.py Updates complete-value expectations.
tests/​unit/​agents/​data/​test_parse.py Tests short-column category coverage.
tests/​unit/​agents/​code/​test_readiness.py Tests color-scale and placement hints.
docs/​concepts/​agent-network.md Documents updated agent behavior.
changelog.d/​agent-live-round-8.md Records fixes and naming changes.
agents/​main.py Applies localized suggestions and pinned bindings.
agents/​evals/​make_stress.py Expands the stress fixture generator.
agents/​evals/​fixtures/​cases/​stress-inject-long-cell/​data.csv Adds products to preserve stress bounds.
agents/​anyplot/​tools/​session.py Uses session language for suggestions.
agents/​anyplot/​schemas.py Allows up to twelve listed values.
agents/​anyplot/​prompts/​root.md Clarifies category interpretation and rename offers.
agents/​anyplot/​prompts/​adapter.md Explains complete category lists.
agents/​anyplot/​opening.py Aligns judged values with profiles.
agents/​anyplot/​dataset_versions.py Supports pinned conversion bindings.
agents/​anyplot/​data/​shape.py Generates localized names and role bindings.
agents/​anyplot/​data/​parse.py Lists short-column values in full.
agents/​anyplot/​data/​bindings.py Extracts binding completion logic.
agents/​anyplot/​code/​readiness.py Detects fixed color scales and placement.
agents/​anyplot/​briefs.py Trims extra categories before remaining values.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread agents/anyplot/data/shape.py Outdated
@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.12281% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agents/anyplot/code/readiness.py 97.72% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

A generated name equal to a melted column (`Value,Other` into `Value`) made pandas'
melt raise a ValueError, a 500 on the route. long_names now checks every input column,
the suggestion drops the offer when the role-name fallback collides too, and
prepare's pivot_longer refuses such a name with invalid_operation (review of #12206).

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

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

Language-dependent suggestions remain inconsistent with binding detection and cached client state, while norm detection incorrectly flags encoding parameters.

2 open findings
1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Ignore non-bound norm parameters in color-scale checks

agents/​anyplot/​code/​readiness.py:431

Checking every norm argument treats encoding parameters as fixed data bounds. The catalogue's PowerNorm(gamma=0.7, vmin=error_vectors.min(), vmax=error_vectors.max()) (plots/scatter-constellation-diagram/implementations/python/matplotlib.py:69) gets a color-scale hint solely because of gamma, although its bounds are data-derived. The adapter prompt says to rewrite every hint, so this incorrectly targets an intentional encoding choice. Restrict each norm to its range, center, threshold, or boundary parameters, and test that literal gamma with data-derived bounds stays unflagged.

🧠 Review effort: Balanced

Comment thread agents/main.py Outdated
Comment thread agents/main.py Outdated
…ead only range arguments

Review of #12206: names in the session language changed under the offer the page had
cached when the language changed, and could decide the offer (label_siblings, which has
no language, then saw no wide table). The names are English now and never decide the
offer: a taken word gives way to the role name, then to a numbered one. The readiness
scan reads a norm's range, center and boundary arguments only, never PowerNorm's gamma.

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

Copy link
Copy Markdown
Owner Author

The review's previously missed finding (readiness.py, norm parameters) is applied in 94d928e. NORM_CALLS now maps each norm to its range, center and boundary arguments only (positions and keywords), so PowerNorm(gamma=0.7, vmin=data.min(), vmax=data.max()) in scatter-constellation-diagram is no longer flagged. Tests cover PowerNorm and SymLogNorm encoding arguments (not flagged), and PowerNorm(0.5, 10, 90) and BoundaryNorm([0, 10, 20], 256) (flagged). The catalogue now has 38 color-scale hints.

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 dataset judge can omit rare full values that share a clipped display copy with a listed value.

1 open finding
2 resolved since last review

🧠 Review effort: Balanced

Comment thread agents/anyplot/opening.py Outdated
… display copy

Review of #12206: the walk stopped at the last listed copy, so a rare full value whose
40-character copy matched an earlier listed one went unjudged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GdMSqLR5ww4ji74EUSmk9M
@MarkusNeusinger
MarkusNeusinger merged commit 334d601 into main Oct 16, 2026
17 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the fix/agents-live-round-8 branch October 16, 2026 13:58
MarkusNeusinger added a commit that referenced this pull request Oct 16, 2026
…s, visible repair round, kept definition) (#12207)

## Summary

Live round 9 findings (2026-10-16) for the admin-only "Use with my data"
chat, the Gemini review items of #12206, and the owner's telemetry rule
for `kept`.

- **Title asked for before `.confirm()` was lost (bar-grouped,
filialen_qx7).** The root said it had noted the title, but nothing kept
it: the bare `.create_plot()` runs `plot_pipeline` without arguments.
`root.md` now tells the root to call `plot_pipeline` with the request on
unconfirmed data too (it answers `not_ready` and `keep_pending_request`
keeps it), and the result carries a root-only `request_kept: true`, the
only basis on which the root may say a request is kept. Regression test:
text turn on unconfirmed data → confirm → `.create_plot()` → the adapter
input carries the title and its expected text.
- **`.to_long()` names in the session language.** `shape.LONG_NAMES` per
language (en, de, fr, es, it, pt, nl, pl; English fallback). The paste,
undo, `to_long`, profile tool, the language route (`PUT /language` now
answers `suggestion`) and every turn's `done` (`suggestion`, BFF
allowlist extended) compute the offer in the current session language,
and the page refreshes the card (`suggestion_sync`), so the card always
names what the route applies. The user's own headers are never
translated; collision handling is unchanged.
- **Repair round visible.** `Round.defects` (closed rubric ids such as
`VQ-05`) on every round and on the `repairing` status. The grid names
rounds `first try`, `second try`, and so on, and a running repair round
shows `repairing text size, layout`. The result card says `second try`,
or `first try shipped of 2` when an earlier round won. Note: the r9
probe's regex matched only `first try|second try|try \d`, and the old
label was `repair 1`, so part of the "invisible" finding was the label
itself.
- **Review fixes of #12206 (each verified):**
- `judged_view` judges at most 5 full values per display copy and 8,000
characters per column. The most frequent value of each copy is always
judged.
- Weekday sets are per language, and the headers must all come from one
set. Portuguese (with `-feira`) and Dutch are complete. Headers of two
letters or fewer need 5 distinct days, so `FR, SA, SO` and `MO, MI, MA`
stay `Category`.
- `_coupling` keeps every flagged part of a line, joined. A part inside
another flagged part counts once (the `Normalize(...)` call and its
keywords).
- `center` is flagged only on seaborn `heatmap` and `clustermap`, and
`levels` only on contour calls. `str.center(10)` was never flagged
(positional argument); a test pins that.
- `.to_long()` with pinned bindings carries the user's bindings on the
kept columns.
- **Telemetry `kept` (owner rule).** A session is kept when the user
copied or downloaded a result after the session's last run and sent no
`thumbs_down` or `bug` feedback. `saved_session` is never a keep. The
view gets the new states `rejected` and `saved` and the new columns
`saves`, `rejections` and `kept`. The header of `03_sessions.sql` has an
example table. In `04_usage_failures.sql`, `sessions_kept` uses the
view's `kept`. The `/debug` card query uses the same rule and returns
`kept_sessions`/`shipped_sessions` and `repaired_runs`/`runs`, and the
card shows "5 of 12" under both rates.

Decisions taken (documented in code):

- The localized weekday word is short where the full phrase is long:
`Jour`, `Día`, `Giorno`.
- `request_kept` is root-only. It is not part of `stream.PLOT_FIELDS`.
- The judge cap trades completeness for bounded cost. Rare variants
beyond 5 per copy go unjudged; the model only ever reads the display
copies.

## Plan

N/A

## Test plan

- [x] `uv run pytest tests/unit -n auto`: 12,121 passed
- [x] ruff check and format, mypy (api core agents)
- [x] app: lint, prettier, type-check, vitest (1,161 tests), build
- [x] Browser check against the BFF mock (desktop light, 375 px dark):
the timeline shows `second try … repairing text size, layout`, and the
card header shows `second try`. The offer card's language refresh is
covered by a hook test, because the mock's specs have no `.to_long()`
offer.
- [ ] Prep eval (Haiku, eu) for the `root.md` change: the result follows
as a comment
- [ ] Not verifiable here: the BigQuery views, which have no SQL test
harness. The coordinator re-runs `03_sessions.sql` and
`04_usage_failures.sql` after the merge.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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