Repository navigation
Stop rule: hold the gap twice, grade the teacher once; harder tickets; Bedrock - #1
Merged
Merged
Conversation
…; Bedrock Runs kept "converging" without the student learning anything. Two causes, both measurement rather than coaching: - The teacher was re-run and re-graded every round on an unchanged prompt, so its mean drifted purely on evaluator noise (0.875 -> 0.813 -> 0.738 on one run) and walked the bar down to meet the student. It is now graded once in round one and carried forward, which also removes the teacher_baseline averaging and cuts a 4-case round from ~18 model calls to ~10. - The student's single round was compared against that average, so over a 5-round budget it got five chances to clear the bar by luck. The gap now has to hold for two consecutive rounds. The tickets could not separate Sonnet from Haiku either: every policy snippet stated the operative clause outright, so Haiku scored 1.00 on the refund case the README builds its worked example on. Each snippet now buries the operative clause among near-misses that are excludable by one cheap check (a category, an account type, a size limit). Customer messages are unchanged; only refund and multi-request changed their expected checklists. Also: Bedrock documented as a provider (no Anthropic key, boto3 credential chain, and the model ids are not guessable from the first-party ones), retries at the single model-call chokepoint for provider 503s, finish_reason and length attached to malformed-JSON failures so truncation is distinguishable from a model ignoring the format, two-questions renamed multi-request now it carries three requests, and run-id suffix widened to 24 bits. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Runs kept "converging" without the student learning anything. The causes turned out to be measurement, not coaching.
The stop rule
The teacher walked down to meet the student. It was re-run and re-graded every round on an unchanged prompt, so its mean drifted purely on evaluator noise — 0.875 → 0.813 → 0.738 on one run — and the student won by the bar falling rather than by climbing. The teacher is now graded once in round one and carried forward. Its mean is constant for the whole run, which also let
teacher_baselineaveraging go (a constant's running average is itself) and cuts a 4-case round from ~18 model calls to ~10.One lucky round ended the loop. The student's single round was compared against the teacher's average, so across a 5-round budget it got five independent chances to clear the bar by luck. The gap now has to hold for two consecutive rounds. I chose consecutive rounds over comparing running averages because the student is supposed to be trending upward, and averaging its history would drag a genuine catch-up backwards.
Every round still carries the teacher's cells, so the score grid, the per-cell detail view and replay are unchanged.
The tickets could not tell the models apart
Every policy snippet stated the operative clause outright, with the date arithmetic pre-computed in the customer's message. Haiku scored 1.00 on the
refundcase the README builds its worked example around — better than Sonnet, twice.Each snippet now buries the operative clause among near-misses. The rule that emerged while tuning these: a distractor must be excludable by one cheap, unambiguous check — a category, an account type, a size limit. A first attempt at
compensationadded a clause that Sonnet fell for too, which only lowers the teacher and leaves the gap flat.Customer messages are unchanged. Only
refundandmulti-requestchanged theirexpectedchecklists.Also in here
AWS_REGION_NAMEmust be set in.envbecause it is not read from~/.aws/config. The model ids are not guessable from the first-party ones: Sonnet 5 isus.anthropic.claude-sonnet-5with no version suffix, Haiku 4.5 isus.anthropic.claude-haiku-4-5-20251001-v1:0with one.llm.py, for the provider 503s a burst of ~18 parallel calls provokes. One unretried failure used to abort a whole round.finish_reasonand length. "invalid JSON" alone cannot distinguish a truncated reply from a model ignoring the format, which made one real failure undiagnosable. No salvage path: the score would survive a truncation but the reason would not, and the written reasons are the part of this loop you actually read.two-questions→multi-request, now that it carries three requests.token_hex(2)collides ~1.8% of the time over 50 ids, against a docstring promising it never would.Deliberately not included
config.yamlkeeps its shipped models onanthropic/. Onlymin_rounds2→3 andgap0.05 ship from that file — making AWS mandatory would be a product change, and Bedrock is documented as an option instead.Still stale after this
The README's "One real run, and how the prompt changed" section and the three screenshots describe a run against the old tickets under the old stop rule. Regenerating them needs a run under this loop that produces a story worth telling.
Testing
49 offline tests pass,
ruff checkandruff format --checkclean. Four tests encoded the old one-round contract and moved with it; the teacher-variance test is gone because its premise is now impossible, replaced by two covering the new invariants — one lucky round does not stop the loop, and the teacher is called exactly once per case per run.🤖 Generated with Claude Code