Skip to content

Define the score correctly in ten PolicyBench notes - #256

Merged
MaxGhenis merged 15 commits into
mainfrom
notes-score-definition
Nov 3, 2026
Merged

MaxGhenis merged 15 commits into
mainfrom
notes-score-definition

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

We rewrite published copy in this PR, so we merge it only on Max's yes.

In #254, which we merged as 03c80a41, we made the same fix in the America.gov note, with the same definition and weighting sentences, so we leave that note's text alone here.

Why we change the notes

PolicyBench gave the headline score in ten notes as "answers within $1". The phrase fits dollar amounts but not eligibility flags. row_hit_scores (policybench/analysis.py) scores an output by exact match when metric_type_for_output calls it binary or BINARY_PROGRAMS lists it, and sends only amounts through exact_amount_match with absolute_tolerance=1.0. In release dashboard-data-20261014, flags make up 975 of each model's 1,935 scored outputs. The site's heatmap already describes the metric this way (app/src/lib/heatmapMetric.ts:22).

What we change

We now give each note's score as a share of "answers right", and we follow it with the definition and the weighting:

PolicyBench counts a dollar amount as right when it falls within $1 of the reference PolicyEngine computes, and an eligibility answer as right when it matches. It weights each answer by household impact.

Note Old New
09-01 ¶0 Claude Fable 5.1 was released on 2026-09-01 and joined the board the same day. Board row: {exactRate}% of answers within $1, #{rank} of {nModels}. {parsed} of {answers} answers parsed. Anthropic released Claude Fable 5.1 on 2026-09-01, and PolicyBench added it to the board the same day and parsed {parsed} of the model's {answers} answers. Claude Fable 5.1 gets {exactRate}% of answers right and ranks #{rank} of {nModels}.
09-05 ¶0 …joined the board on 2026-09-05 at {astraExact}% of answers within $1, #{astraRank} of {nModels}, behind … …joined the board on 2026-09-05. It gets {astraExact}% of answers right and ranks #{astraRank} of {nModels}, behind …
09-22 ¶0 GPT-6 Sol leads at {solExact}% of answers within $1, weighted by household impact, #{solRank} of {nModels} and {solLead} points above Claude Opus 5.5 (…). GPT-6 Sol gets {solExact}% of answers right, {solLead} points above Claude Opus 5.5 (…), and ranks #{solRank} of {nModels}.
09-29 ¶0 Claude Sonnet 5.5 scores {sonnetExact}% of answers within $1, weighted by household impact, #{sonnetRank} of {nModels}. Claude Sonnet 5.5 gets {sonnetExact}% of answers right and ranks #{sonnetRank} of {nModels}.
10-06 ¶5 Every model's exact rate, its share of answers within $1 weighted by household impact, rises by … Every model's share of answers right rises by …
10-10 ¶0 It gets {haikuExact}% of answers within $1, weighted by household impact, #{haikuRank} of {nModels} and {haikuGain} points above Claude Haiku 4.5 (…). It gets {haikuExact}% of answers right, {haikuGain} points above Claude Haiku 4.5 (…), and ranks #{haikuRank} of {nModels}.
10-13 ¶0 It gets {museExact}% of answers within $1, weighted by household impact, #{museRank} of {nModels}. … GPT-6 Sol still leads on answers within $1 at {solExact}%, ahead of … Muse Wonder gets {museExact}% of answers right and ranks #{museRank} of {nModels}. … GPT-6 Sol still leads at {solExact}% of answers right, ahead of …
10-14 ¶0 Gemini 4 Argon gets {argonExact}% of answers within $1, weighted by household impact, #{argonRank} of {nModels} and the highest of any Gemini model; … GPT-6 Sol still leads on answers within $1 at {solExact}%, ahead of … Gemini 4 Argon gets {argonExact}% of answers right and ranks #{argonRank} of {nModels}, the highest of any Gemini model. … GPT-6 Sol still leads at {solExact}% of answers right, ahead of …
10-20 ¶0 GPT-6 Sol, which leads the board at {solBoardExact}% of answers within $1, weighted by household impact, gets {solToolExact}% with the tool. GPT-6 Sol, which leads the board at {solBoardExact}% of answers right, gets {solToolExact}% with the tool.
10-31 ¶0 It gets {terraExact}% of answers within $1, weighted by household impact, #{terraRank} of {nModels}. … GPT-6.1 Sol, which OpenAI released on September 29, gets {sol61Exact}% (#{sol61Rank}). GPT-6.1 Terra gets {terraExact}% of answers right and ranks #{terraRank} of {nModels}. … GPT-6.1 Sol, which OpenAI released on September 29, gets {sol61Exact}% of answers right (#{sol61Rank}).

The definition and the weighting sit in one of three places:

  • In the eight notes that give the score in paragraph 0, they close that paragraph. Paragraph 0 also serves as each note's meta description (app/src/app/notes/[slug]/page.tsx:28) and as its blurb in the notes list, which shows three lines (app/src/components/NotesContent.tsx:369), so the news comes first there. Once the app fills in each note's facts, the October 14 opening grows from 653 to 825 characters, and the October 31 opening from 540 to 747. No app test caps either.
  • In the October 6 note, they follow the score sentence in paragraph 5.
  • In the October 20 note, "PolicyBench weights each answer by household impact in these six scores" follows the board and tool scores in paragraph 0. The definition opens paragraph 1 with "With or without the tool". scripts/tool_pilot_note.py scores the tool runs with row_hit_scores too (hit), and its weighted_exact weights the board and tool scores by household impact. The script's facts computes paragraph 1's six nonzero-amount rates as unweighted shares of the 187 amounts, so we added "PolicyBench gives each amount the same weight in these six rates" after them.

We also rewrote these sentences in the same paragraphs:

  • September 1. We wrote "Anthropic released Claude Fable 5.1 on 2026-09-01" in place of "Claude Fable 5.1 was released on 2026-09-01". We also folded the parse count into that sentence, in place of the fragment "{parsed} of {answers} answers parsed".
  • September 5. We wrote "PolicyBench scores every model on {scoredOutputs} of its {totalOutputs} requested outputs and excludes the other {excludedOutputs}, since their references depend on an engine input the household facts never list" in place of "Every row on this board is scored on …", in the form the September 29 note uses.
  • September 22. GPT-5.6 Sol "ranks #{sol56Rank}", where the note said it "is #{sol56Rank}".
  • September 29. GPT-6 Luna "sits about level with Claude Sonnet 5.5", where the note said "with it". We wrote "Together, the new references and the Medicaid exclusion lift every one of the {incumbents} earlier models" in place of "raise the exact rate of every one of the {incumbents} earlier models".
  • October 10. We wrote "bringing the board to {nModels} models" in place of "bringing it to", so "It gets" has one antecedent. In paragraph 5, we dropped "the exact rate" and wrote "Without those outputs, every earlier model's share of answers right would have risen" in place of "Had they stayed excluded, every earlier model's rate would have risen".
  • October 13. We rewrote the opening as "PolicyBench added Muse Wonder, its first Meta model, to the board on {releaseDate}, the day after Meta released it, bringing the board to {nModels} models", and dropped "It is the first Meta model on the board". In paragraph 3, we dropped "the exact rate" and wrote "every earlier model would keep its share of answers right from the previous release" in place of "every earlier model's rate would be the previous release's".
  • October 13 and 14. We wrote "GPT-6 Sol still leads at {solExact}% of answers right" in place of "GPT-6 Sol still leads on answers within $1 at {solExact}%". After the bounded-score rank, a reader needs the metric beside the leader's rate.
  • October 14. We split the score sentence at its semicolon.
  • October 31. We wrote "GPT-6.1 Terra gets" in place of "It gets", and "GPT-5.6 Sol, which also rounds to {sol56Exact}%, trails by less than a tenth of a point" in place of "is less than a tenth of a point behind". After the bounded-score sentence, we added "of answers right" to GPT-6.1 Sol's {sol61Exact}%. In paragraph 4, we dropped "the exact rates".

We rewrote the result line of docs/terra/design.md, which the October 31 note links, the same way. There we also wrote "and every one of its outputs parses" in place of "with every output parsed", and "GPT-6.1 Terra answered" in place of "It answered".

Sentences that keep "within $1"

These sentences cover dollar amounts only:

  • October 6, paragraph 4: the four federal and state income tax outputs and the four payroll_tax outputs.
  • October 10, paragraphs 2 and 5: the 18 outputs with engine defects that the new policyengine-us version fixes. reference_audit/2026-10-09-engine-upgrade/final_actions.json lists them as federal and state income tax before refundable credits, payroll tax and state refundable credits, and the 14 newly scored outputs come from those 18.
  • October 13, paragraphs 2 and 3: the 9 restored outputs, which reference_audit/2026-10-12-engine-upgrade/final_actions.json lists as state income tax before refundable credits, federal refundable credits and state refundable credits.
  • October 20, paragraph 1: the nonzero amounts, which is_amount in scripts/tool_pilot_note.py limits to outputs that aren't eligibility flags.

Record of the change

No score moves, so we add no correction paragraph to the ten notes. PolicyBench has recorded corrections in two places. In the October 6 note, it recorded the corrections in release dashboard-data-20261006 ("Two corrections in this release move no score"). In the two September 22 notes and the September 3 note, it recorded later corrections in each note's last paragraph ("A later release, dashboard-data-20260922c, corrects the reference for one output"; "A later note, published October 5, corrects this one"). Those corrections moved scores. Like October 6's corrections, this one moves no score, and it lands between releases, so we propose recording it the first way, in the next release note, with a line such as:

Since the last release, PolicyBench has corrected eleven of its notes, from September 1 to October 31, where it defined the score by its $1 tolerance alone. PolicyBench applies the tolerance to dollar amounts and counts an eligibility answer as right only when it matches. No score moved.

The count of eleven includes the America.gov note, which we corrected in #254, so the line holds once this PR merges. We added the line to the October 31 note in a scratch copy, and the copy passed this PR's guard. Max chose the first way, so the next release note will carry the line.

Invariants

test_no_note_gives_the_score_as_answers_within_one_dollar (tests/test_notes.py) checks every note:

  • no title or paragraph says "answers within $1", "of answers within" or "weighted by household impact", in any case;
  • a title or sentence that pairs a percentage, or "share" or "shares" in any case, with "within" or "Within" before "$1", "a $1", "a dollar" or "one dollar" also contains "amounts";
  • a note that says "of answers right" carries the definition word for word (SCORE_DEFINITION);
  • a note that carries the definition also says "weights each answer by household impact";
  • where paragraph 0 carries the definition, the paragraph ends with it and "It weights each answer by household impact." (SCORE_WEIGHTING);
  • row_hit_scores credits a dollar amount within $1, and an eligibility flag only when it matches.

The guard skipped the America.gov note while that note still read "answers within $1", and the skip failed once that note changed. We merged #254 first, as 03c80a41, then merged main into this PR (b0137f52) and deleted the seven-line skip (7ef8acdb). Against main, this PR's diff now matches its diff at 71b8641e apart from those seven lines, and the guard checks the America.gov note as it checks every other note.

The September 29 and October 6 note tests pin the new sentences beside their evidence. app/tests/notes.test.ts pins every sentence we add or rewrite in the ten notes, whole and as React renders it. Every mutation we ran before def8324c fails a test: 16 at f00bebd2, and 7 at 5e9b4782 that target that round's changes. At 71b8641e, we ran review r4's 15 mutations, 7 of our own, review r5's 8 and review r6's 3 through the guard. It fails all eighteen that say "answers within $1", or that give a percentage or share within $1 or within a dollar in a title or sentence that doesn't name the amounts. It passes accurate edits such as "answers right." in quotes before the definition. It reads words, not figures, so it passes a title or sentence that names the amounts beside an all-outputs score. It checks each title and sentence on its own, so it misses a score and "within $1" in separate sentences. It also fails accurate sentences that put "within $1" beside a count, a percentage of outputs or "share" in its plain sense. The author of such a sentence passes the guard by naming the amounts, or, for a count, by splitting the sentence. Review r5 gives the first 30 results under def8324c's patterns and under the patterns we took in 5101a8ee, and our run at 71b8641e matches the second set. We add no property-based tests, since these checks cover fixed copy.

We change no score, rank, fact or release file.

Checks

  • At 71b8641e, ruff check and ruff format --check pass on tests/test_notes.py. The guard and schema tests pass locally (15), and so does bun test tests/notes.test.ts (18 tests, 231 expects).
  • At 7ef8acdb, ruff check and ruff format --check pass on tests/test_notes.py. The guard, schema and America.gov tests pass locally (19), and so does bun test tests/notes.test.ts (18 tests, 245 expects).
  • Owner's voice pass, after a full read of the voice guide, on every sentence we add or rewrite and on this description.
  • Review at 266998fe asked for changes; this reply answers each finding.
  • Review r2 at 3c6a06e4 asked for changes; this reply answers each finding.
  • Review r3 at b74ab232 asked for changes; this reply answers each finding.
  • Review r4 at 5e9b4782 approved; this reply answers its findings.
  • Review r5 at def8324c approved; this reply answers its findings.
  • Review r6 at 5101a8ee approved; this reply answers its findings.
  • CI at 71b8641e (run 41609104386): lint, app (bun test tests) and test.
  • CI at head (7ef8acdb, run 41715637846): lint, app and test.
  • Review r7 at 71b8641e approved, and this reply answers its findings.
  • Max's yes.
  • Review r8 at 7ef8acdb approved, and this reply answers its findings.

axiom: n/a: note copy only, no policy logic

🤖 Generated with Claude Code

The notes gave the headline score as answers within $1, but the board
scores eligibility flags by exact match (row_hit_scores). Each note now
names dollar amounts within $1 of PolicyEngine's reference and
eligibility answers that match it.

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

vercel Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
policybench-site Ready Ready Preview Nov 3, 2026 8:49pm UTC

Request Review

Paragraph 0 doubles as the page description and list blurb; in the
October 14, 20 and 31 notes the definition would have taken it to
645-737 characters, so it opens paragraph 1 instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6GAupb55h8SCa6AP87
tests/test_notes.py pins the September 29 and October 6 definitions
beside row_hit_scores, and a new test fails on any note that gives the
score as answers within $1. app/tests/notes.test.ts pins the rendered
sentences.

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

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: ad7ac93dea11b921621f1be50f91a0e84b8da2d6

Notes and how each was resolved

My search found the same ten notes listed in the brief. The only other hit for "answers within $1" is the America.gov note, which I left to #254.

  • 09-01: replaced "Board row: {exactRate}% of answers within $1" with "It gets {exactRate}% of answers right, weighted by household impact, #{rank} of {nModels}." The definition sentence follows.
  • 09-05: changed to "…at {astraExact}% of answers right, weighted by household impact, …". The definition comes after the ranking sentence.
  • 09-22, 09-29, 10-10: changed "within $1" to "right". The definition follows as the next sentence in paragraph 0.
  • 10-06 ¶5: changed to "its share of answers right weighted by household impact". The next sentence is "The rate counts dollar amounts within $1 of PolicyEngine's reference and eligibility answers that match it."
  • 10-13: changed to "right" and added the definition in paragraph 0. The later sentence now reads "GPT-6 Sol still leads at {solExact}%".
  • 10-14: changed to "right" and shortened the later Sol sentence the same way. The definition opens paragraph 1 because of the blurb length.
  • 10-20: changed to "right". Paragraph 1 opens with "Each score counts…", because the tool-arm scores also go through row_hit_scores.
  • 10-31: changed to "right". The definition opens paragraph 1 because of the blurb length.
  • Left as they were, after checking the outputs behind each: 10-06 ¶4 (income-tax and payroll_tax outputs), 10-10 ¶2 and ¶5 (18 restored and 14 newly scored outputs, all amounts), 10-13 ¶2 and ¶3 (9 restored refundable-credit and state-tax outputs, all amounts), 10-20 ¶1 (nonzero amounts, filtered by is_amount). None of these groups holds a flag.

Tests

  • uv run pytest tests/test_notes.py -n 4 -q -p no:cacheprovider on the unshallowed clone: 45 passed, 2 skipped. One skip needs policyengine-us 2.15.17 (2.60.0 is installed). The other skips because the pathway files belong to a superseded release. Both skips also occur on main.
  • New test test_no_note_gives_the_score_as_answers_within_one_dollar: fails against the old note text (first hit: 2026-09-01) and passes now.
  • bun test tests/notes.test.ts: 17 passed.
  • ruff check and ruff format --check on tests/test_notes.py: clean.

CI at head

app, lint, test and Vercel all succeeded.

Judgment calls

  1. Paragraph 0 length. In 10-14, 10-20 and 10-31 the definition opens paragraph 1. Keeping it in paragraph 0 would have made those blurbs 737, 735 and 645 characters. They now come to 628, 625 and 536, each no longer than on main (653, 629, 540). 10-14 and 10-20 already exceeded 600 on main, and no app test caps either one. The two capped notes (10-05 and 10-06) keep their paragraph 0 unchanged.
  2. 09-01 and 09-05 now say "weighted by household impact". Their old text did not say it. Household weights appear in the code history from May 2026 (globalWeights, Add metric design walkthrough page #25 and Leaderboard: provider/frontier filters, per-variable weights table #32), so the board was already weighted then. I did not recompute those releases' scores to confirm it.
  3. Removed the label in 09-01. "Board row:" was a label ending in a colon, and the rewritten sentence drops it.
  4. The new test exempts the America.gov note by slug. main still reads "PolicyBench answers within $1" there. The exemption carries a comment saying to drop it once Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 merges.
  5. The September 29 and October 6 Python tests pin the new definition sentences beside a shared _assert_score_definition() that checks row_hit_scores. Those tests require every sentence in a note to be pinned.
  6. No voice review claimed. That review belongs to the owner.

No score, rank, fact or release file changes.


Generated by Claude Code

Each note now says "PolicyBench counts a dollar amount as right when it falls within $1 of PolicyEngine's reference, and an eligibility answer as right when it matches." Score sentences end "and ranks #N of M" instead of trailing the rank. The October 14 and October 31 notes define the score beside it in paragraph 0. The September 5 note splits its opening sentence, the September 29 note names Claude Sonnet 5.5 where "it" now sits a sentence away, and the October 6 note drops "exact rate".

The guard test now also requires the definition in every note that gives a score as answers right.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e reference

Review r1 (REQUEST_CHANGES at 266998f) found that the definition cut a
pronoun off from its antecedent in the October 13 note and cut the
comparisons off from Terra's score in the October 31 note. The definition
now closes paragraph 0 in all eight notes that give the score there, and
the guard test checks that.

- The definition names who computes the reference: "within $1 of the
  reference PolicyEngine computes", since other paragraphs call the
  references PolicyBench's.
- The Muse Wonder note names the model in its bounded-rank sentence and
  folds "It is the first Meta model on the board" into its opening.
- Ranks and comparisons take verbs: GPT-5.6 Sol "ranks #3" and "trails by
  less than a tenth of a point".
- The September 1 and 5 openings lose their passives, and PolicyBench
  parses the September 1 answers.
- The October 20 definition opens with "With or without the tool".
- Four notes drop "the exact rate", a second name for the score.
- The guard requires the shared definition word for word, and its
  America.gov skip fails once #254 lands.
- docs/terra/design.md stops giving the score as answers within $1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed 96a7fae6 in answer to this review.

  1. B1. The October 13 bounded-score sentence now says "Muse Wonder ranks #{museBoundedRank}". The definition now closes paragraph 0 in all eight notes that give the score there, so no sentence after it leans on one before it, and the guard test requires that placement. app/tests/notes.test.ts pins "Muse Wonder ranks Update GitHub Actions for Node 24 runtime #3, behind only GPT-6 Sol and Claude Opus 5.5".
  2. N1. The definition closes the October 31 opening, and GPT-5.6 Sol "trails by less than a tenth of a point".
  3. N2. September 1 now reads "PolicyBench parsed {parsed} of the model's {answers} answers" and "Anthropic released Claude Fable 5.1 on 2026-09-01".
  4. N3. The October 20 definition opens with "With or without the tool". Paragraph 0 keeps "not whether it is right": there "it" is the engine, and paragraph 1 then says what PolicyBench counts as right, so together they state the circularity.
  5. N4. GPT-5.6 Sol "ranks #{sol56Rank}", and the September 22 score sentence takes the October 10 form you suggested.
  6. N5. The four notes drop "the exact rate". October 10 and 13 say "every one of the {incumbents} earlier models falls, by …", October 31 says "{fallers:words} of the {incumbents} earlier models fall, by …, and {risers:words} rise by {rise}", and September 29 says "every one of the {incumbents} earlier models rises, by …". The pins in both test files follow.
  7. N6. The definition now says "within $1 of the reference PolicyEngine computes", which fits the notes' "PolicyBench's references". Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 takes the same sentence.
  8. N7. Both PRs now carry the same definition sentence. Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 states the weighting in a sentence of its own ("It weights each answer by household impact"), since its opening gives the score as "scores {agovExact}% on PolicyBench". This PR keeps "weighted by household impact" in each score sentence, because a published rate holds only with its weighting: you found September 1's unweighted share at 92.6%, against the 86.3% the note gives.
  9. N8. The skip now asserts that the note still reads "answers within $1", as you suggested, so it fails once Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 lands.
  10. N9. The PR body now says where the record goes: the next release note, as the October 6 note recorded its corrections, in a line the body drafts. Max's yes covers it.
  11. N10. Item 1 covers it. With the definition at the end of paragraph 0, the three-line blurbs show the news.
  12. N11. The body now says "975 of each model's 1,935 scored outputs", "the 18 outputs whose engine defects the release fixes" and "The guard test skips the America.gov note". The voice-pass box names what the pass covered: every sentence the PR adds or rewrites, and the paragraph-0 sentences you flagged. The September 1, 5 and 22, October 13 and October 31 openings lose those be-verbs and passives.
  13. N12. docs/terra/design.md now gives the result as "93.14% of answers right (dollar amounts within $1 of the reference, eligibility answers matching it)". The count in final_actions.json is a separate defect in an audit record, so it gets its own follow-up.

🤖 Generated with Claude Code

MaxGhenis added a commit that referenced this pull request Nov 3, 2026
Close the opening with the definition sentence #256 gives every note, word
for word, and state the weighting in a sentence of its own.

Give each verb in the note to the actor that performs it. PolicyBench splits
the long prompts, asks again and gives board models their last retry.
America.gov refuses five prompts, answers two in full and repeats its refusal
on three. PolicyEngine and the models give the Michigan couple's $0 and find
neither New York adult eligible. "America.gov gets" replaces an "it" that
review r3's fix left after PolicyBench.

Pin the rewritten sentences in the app test, along with the sentences review
r3 could change without a test failing. In the Python test, check that every
prompt carries the two phrases the note quotes, that the units answered on a
retry and the units refused every time make up the first refusals, and that
the script's score for each board model matches the score release 20261014
publishes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#254 gives the America.gov note the same definition sentence. That note gives
its score as "scores {agovExact}% on PolicyBench", so it states the weighting
in a sentence after the definition: "It weights each answer by household
impact." Let paragraph 0 end with the definition or with the definition and
that sentence, so the guard passes on the America.gov note once whichever PR
merges second drops its exemption.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed 3c6a06e4.

#254 gives the America.gov note this PR's definition sentence. That note gives its score as "scores 87.9% on PolicyBench", so it states the weighting in a sentence after the definition: "It weights each answer by household impact." The guard now lets paragraph 0 end with the definition, or with the definition and that sentence (SCORE_WEIGHTING).

The owner session merged both heads (3c6a06e4 and #254's 041c32f3) locally. With the exemption in place, the guard fails with "drop from pending", as it should once #254 lands. After the owner session dropped the exemption, the guard, #254's four America.gov tests and bun test tests/notes.test.ts (18 tests) passed.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits November 3, 2026 00:45
…g actively (review r2)

In the October 13 and 14 openings, "GPT-6 Sol still leads at 95.2%"
came right after a bounded-score sentence, so it read as a bounded
rate. It now says "95.2% of answers right", and October 31's GPT-6.1
Sol sentence does the same.

Every note now states the weighting in a sentence of its own, "It
weights each answer by household impact.", after the definition, as
#254's note does. It replaces the participle "weighted by household
impact". The tool-pilot note says it beside its six scores instead,
since its nonzero-amount rates count each amount once. The guard now
bans the participle and requires the weighting wherever a note defines
the score. An opening that holds the definition must end with it and
the weighting.

Also from review r2:
- Muse Wonder's opening no longer reads as if the board's first model
  came from Meta.
- Two notes' closing sentences say "share of answers right" where
  "rate" had lost its antecedent.
- September 29 gives the drift's causes the verb.
- September 5 says "every model" in place of "every row".
- September 1 folds its parse count into the opening sentence.
- October 14 splits at its semicolon.

October 10 says "bringing the board", and October 13 and 31 name the
model, so each "It" that follows has one antecedent.
app/tests/notes.test.ts pins each changed sentence as it renders, and
each of 16 mutations fails a test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
September 5's opening sentence, September 29's GPT-6 Luna sentence and
October 31's "Only GPT-6 Sol ... score higher" sentence had only partial
pins or none. With them, app/tests/notes.test.ts pins every sentence
this PR adds or rewrites in the ten notes, as each renders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the parenthetical definition and the participle "weighted by household impact" in the result line of docs/terra/design.md with the notes' definition and weighting sentences. No number changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed f00bebd2, 248b2281 and b74ab232 in answer to this review.

  1. B1. October 13 and 14 now say "GPT-6 Sol still leads at {solExact}% of answers right, ahead of …". October 31's GPT-6.1 Sol sentence takes your optional fix: "gets {sol61Exact}% of answers right (#{sol61Rank})". app/tests/notes.test.ts pins all three sentences whole, the Gemini 4 Argon test included.
  2. N1. October 13 opens with your wording: "PolicyBench added Muse Wonder, its first Meta model, to the board on {releaseDate}, the day after Meta released it, bringing the board to {nModels} models." The score sentence after it names Muse Wonder.
  3. N2. October 10 says "every earlier model's share of answers right would have risen", and October 13 says "Without them, every earlier model would keep its share of answers right from the previous release." The app test pins both.
  4. N3. The description gives the lengths at head, 825 and 747, which count the weighting sentence. It now says we follow the score with the definition and the weighting, and no longer says the paragraph ends with them. app/tests/notes.test.ts pins every sentence the PR adds or rewrites, September 1's and October 10's score sentences among them; 248b2281 adds the last three. The CI box names the app job's bun test tests.
  5. N4. We closed both gaps another way. Every note now states the weighting in a sentence of its own (see N7). The guard bans "weighted by household impact" in every note, and requires "weights each answer by household impact" wherever a note carries the definition. It also requires an opening that holds the definition to end with the definition and the weighting. So a leftover participle fails the ban, and an America.gov opening without its weighting sentence fails both checks once the exemption goes. The guard catches each of its mutants: a participle back in October 31, and a dropped weighting sentence in October 6, 14 and 20.
  6. N5. The description's record line takes your wording, with "since the last release" and the notes' dates: "Since the last release, PolicyBench has corrected eleven of its notes from September 1 to October 31, in which it gave the score as the share of answers within $1 of the reference. It counts an eligibility answer as right only when it matches. No score moved." We also added the line to the list of what the next board release note carries, with a step that counts only the notes whose PR merged.
  7. N6. September 29 reads "Together, the new references and the Medicaid exclusion lift every one of the {incumbents} earlier models, by {driftMin} to {driftMax} points." Both pins follow.
  8. N7. We applied the voice rule you cited. The participle goes from all ten notes, and "It weights each answer by household impact." follows the definition, as in Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254. The October 20 note says "PolicyBench weights each answer by household impact, on the board and with the tool" in paragraph 0, beside its board and tool scores, since its nonzero-amount rates in paragraph 1 count each amount once.
  9. N8. September 1 opens "Anthropic released Claude Fable 5.1 on 2026-09-01, and PolicyBench added it to the board the same day and parsed {parsed} of the model's {answers} answers.", which joins two of the short sentences. September 5 takes the September 29 form you suggested: "PolicyBench scores every model on … and excludes the other {excludedOutputs}, since …". October 14 splits at its semicolon.
  10. N9. A follow-up task takes the full pass on the paragraphs this PR leaves alone, once this PR and Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 merge. It starts from your list and adds October 14's "it ranks Determinism and reproducibility hardening #6", which can point to either model.
  11. N10. The final_actions.json count has its own follow-up task: the note field says 19 regenerations and 16 rechecks, and the file's lists hold 18 and 17. Its PR will link here.

b74ab232 gives the result line in docs/terra/design.md the notes' definition and weighting sentences, in place of the parenthetical and the participle.

Since f00bebd2, no commit has touched the notes or the guard. We merged f00bebd2 with #254's 041c32f3 locally and dropped the exemption: the guard, #254's America.gov tests and the schema tests pass (19 tests), and so does bun test tests/notes.test.ts (18 tests).

🤖 Generated with Claude Code

Review r3 found that "PolicyBench weights each answer by household impact, on the board and with the tool" also covered paragraph 1's six nonzero-amount rates, which `scripts/tool_pilot_note.py` computes as plain counts. We rewrote the sentence as "PolicyBench weights each answer by household impact in these six scores" and added "PolicyBench gives each amount the same weight in these six rates" to paragraph 1.

In October 10's paragraph 5, we wrote "Without those outputs" in place of the participial "Had they stayed excluded". In the Terra design record, we wrote "and every one of its outputs parses" in place of "with every output parsed". We also named GPT-6.1 Terra in "GPT-6.1 Terra answered", where "It answered" had followed PolicyBench's "It weights".

The guard now checks every sentence that gives a rate within $1 for the word "amount", so it catches "{terraExact}% within $1". We also corrected its comment, which said each note gives the weighting after the definition; the October 20 note gives it first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

A Claude Opus 5.5 agent reviewed this PR at b74ab232 for the session that owns it. We post its review below as it wrote it, and reply in the next comment.


Verdict: REQUEST_CHANGES at b74ab232

Review r3 of #256 at b74ab23. I made no edits, pushes or comments, and I ran tests only in a scratch clone, which I have deleted.

This round fixes r2's blocking finding and most of the rest, and the guard and the pins hold up under mutation. One new problem blocks the merge: the October 20 note's new weighting sentence also covers six rates that PolicyBench doesn't weight. Two claims in the description's "Record of the change" need fixing before Max rules on them.

Blocking

1. October 20: the weighting sentence also claims six rates that count each amount once.

  • Where: app/src/notes/2026-10-20-given-a-policyengine-tool-three-models-score-above-99.json:6 (paragraph 0) and :7 (paragraph 1); the pin at app/tests/notes.test.ts:193.
  • Paragraph 0 now says "PolicyBench weights each answer by household impact, on the board and with the tool." "Each answer", in both arms, takes in every score the note gives. Paragraph 1 then gives six more scores in the same two arms: "Of the 187 nonzero amounts, GPT-6 Sol gets 67.4% within $1 on its own and 96.8% with the tool; Claude Opus 5.5, 70.1% and 98.9%; and Gemini 4 Argon, 46.5% and 99.5%."
  • Those six rates count each amount once: they equal 126, 181, 131, 185, 87 and 186 of 187. weighted_exact in scripts/tool_pilot_note.py weights only the six board and tool scores in paragraph 0. The reply to r2 says so ("its nonzero-amount rates in paragraph 1 count each amount once"), but the note doesn't, so a reader assumes PolicyBench weights these six rates too.
  • Weights would move them. I applied the same household-impact weights to the 187 amounts, renormalized them within each of the 83 households that have one, and gave each household equal weight. On that basis GPT-6 Sol gets 78.5% on its own instead of 67.4%, Claude Opus 5.5 74.3% instead of 70.1%, and Gemini 4 Argon 53.0% instead of 46.5%. I built that weighting myself to size the misreading; PolicyBench shouldn't publish it.
  • On main, "weighted by household impact" modified the board score alone. This PR widens the claim to every answer in both arms. That repeats the failure the PR fixes everywhere else; in the voice guide's words, "A definition has to hold for every answer it covers."
  • Fix. I applied it in a scratch copy: the guard and schema tests pass (15), and bun test tests/notes.test.ts passes (18 tests, 231 expects).
    • Paragraph 0: replace the sentence with "PolicyBench weights each answer by household impact in these six scores."
    • Paragraph 1, after the rates, add: "PolicyBench gives each amount the same weight in these six rates."
    • app/tests/notes.test.ts:193: pin "PolicyBench weights each answer by household impact in these six scores.", and add a pin for "and Gemini 4 Argon, 46.5% and 99.5%. PolicyBench gives each amount the same weight in these six rates."
    • The description's October 20 bullet: "In the October 20 note, "PolicyBench weights each answer by household impact in these six scores" follows the board and tool scores in paragraph 0, and the definition opens paragraph 1 with "With or without the tool". scripts/tool_pilot_note.py scores the tool runs with row_hit_scores too (hit), and weighted_exact weights the board and tool scores by household impact. The six nonzero-amount rates in paragraph 1 count each amount once, and the paragraph now says so."
  • Publishing weighted rates in their place would change published numbers, so that change belongs in a PR of its own.

Should-fix

2. The proposed record line fails this PR's own guard.

  • Where: the quoted line in the description's "Record of the change", and the same line on the next-release list that the reply to r2 mentions.
  • The line says "…in which it gave the score as the share of answers within $1 of the reference." The guard bans "answers within $1" and "of answers within" in every note's title and paragraphs. I added the line to the October 31 note as a new paragraph in a scratch copy, and the guard failed at tests/test_notes.py:6218 with ('2026-10-31-gpt-6-1-terra-joins-the-board.json', 'answers within $1'). The next release note can't carry the line in its current wording.
  • Fix: name the tolerance without the banned phrase, for example: "Since the last release, PolicyBench has corrected eleven of its notes, from September 1 to October 31, where it defined the score by its $1 tolerance alone. The tolerance applies to dollar amounts; PolicyBench counts an eligibility answer as right only when it matches. No score moved." That line passes the guard and the schema tests (15) in the same scratch copy. Update the next-release list to match. An exemption in the guard would also work, at the cost of a second exemption list.

3. "PolicyBench records each correction in the note of the release that makes it" overstates the record.

  • Where: the description's "Record of the change", second sentence.
  • The October 6 note does record its own release's corrections ("Two corrections in this release move no score"). But three notes record later corrections in themselves:
  • The split may follow whether a score moved: the September corrections changed references, while October 6's, like this one, moved no score. Max reads this section to decide where the record goes, so it should show both precedents.
  • Fix: replace "PolicyBench records each correction in the note of the release that makes it, as the October 6 note does ("Two corrections in this release move no score"). This correction lands between releases, so the next release note should record it, in a line such as:" with: "PolicyBench has recorded corrections in two places. The October 6 note records the ones its own release makes ("Two corrections in this release move no score"). The two September 22 notes and the September 3 note record later corrections to their references in their own last paragraphs ("A later release, dashboard-data-20260922c, corrects the reference for one output"; "A later note, published October 5, corrects this one"). This correction, like October 6's, moves no score, and it lands between releases, so we propose the first form: the next release note records it, in a line such as:"

Nits

4. October 10 json:11 keeps a participial passive in a sentence this PR rewrote. "Had they stayed excluded, every earlier model's share of answers right would have risen, by {riseWithoutMin} to {riseWithoutMax} points." Replace it with "Without them, every earlier model's share of answers right would have risen, by {riseWithoutMin} to {riseWithoutMax} points." That matches October 13's "Without them, every earlier model would keep its share of answers right from the previous release." Update the pin at app/tests/notes.test.ts:367.

5. docs/terra/design.md:144. The numbers match main, and "It weights" points to PolicyBench. Two phrases in the bullet still read badly:

  • "with every output parsed" is an absolute participial passive. Replace the first sentence with "GPT-6.1 Terra gets 93.14% of answers right and ranks Update GitHub Actions for Node 24 runtime #3 of 51 on the 1,935 scored outputs (bounded score 97.19), and every one of its outputs parses."
  • "It answered on 2026-10-26…" now comes two sentences after "It weights", whose "It" means PolicyBench, and right after the possessive "GPT-6.1 Terra's 100 households". Write "GPT-6.1 Terra answered on 2026-10-26…".
  • The last sentence, which this PR leaves alone ("The board's response window is … and the snapshot is dated …"), can wait for the follow-up pass.

6. The guard lets a percentage "within $1" through. It bans three phrases, so "{sol61Exact}% within $1" or "{terraExact}% within $1 of the reference" in the October 31 note passes it. Only the app pins catch those, and a future release note has no pins until its author writes them. A sentence-level check after the phrase ban closes the gap:

        for paragraph in note["paragraphs"]:
            for sentence in re.split(r"(?<=[.!?])\s+(?=[A-Z])", paragraph):
                if (
                    re.search(r"\{\w+(?:Exact|Rate)\}%", sentence)
                    and "within $1" in sentence
                ):
                    assert "amount" in sentence, (path.name, sentence)

I ran the check over every note. It flags twelve sentences in ten notes on main, and at head only the America.gov note, which the guard still exempts. On a merge with #254 it flags nothing. While you're there, the comment at tests/test_notes.py:6179-6180 says each note gives the weighting "after the definition"; the October 20 note gives it before, in paragraph 0.

7. The description's opening makes the notes the actor. "Ten notes gave the headline score as "answers within $1"." r2 flagged the same pattern in the record line. Replace it with "PolicyBench gave the headline score in ten notes as "answers within $1"."

8. Nothing enforces the merge order with #254. main has no branch protection and no required checks, so GitHub lets the second of #254 and #256 merge without main's latest commit. If the second one merges that way, main's guard fails on "drop from pending" until someone drops the entry. Add to the Invariants paragraph: "GitHub won't enforce this, since main has no required checks, so whoever merges the second PR first merges main into it, drops the entry and waits for CI."

r2 findings at b74ab232

r2 finding What the head does The reply
B1: "still leads" lost its metric Fixes October 13 and 14 ("GPT-6 Sol still leads at {solExact}% of answers right") and takes October 31's optional fix. The app test pins all three sentences whole, and the Gemini 4 Argon test now pins its sentence too. Accurate
N1: October 13 opening Takes r2's wording. The next sentence names Muse Wonder, so the "it" of the bounded-score sentence points to it. Accurate
N2: orphaned "rate" Fixes October 10 and 13, and the app test pins both. Accurate. October 10's sentence still opens with a participial passive (nit 4).
N3: description claims The lengths 825 and 747 hold, the description says the definition and the weighting follow the score, the app test pins every sentence the PR adds or rewrites whole, and the CI box names bun test tests. Accurate
N4: where the weighting check applies Closes both gaps another way: the participle ban, the rule that the definition brings the weighting, and the paragraph-0 ending together catch both of r2's mutants. Accurate. Each of the four mutants the reply names fails the guard.
N5: record line Takes the wording, the dates and the count, and puts the line on the next release's list. Accurate, but the line fails the guard (finding 2), and the placement rule overstates the record (finding 3).
N6: September 29 actors Takes r2's sentence, and both test files pin it. Accurate
N7: weighting form Applies "It weights each answer by household impact." in all ten notes and in docs/terra/design.md. Accurate, but October 20's sentence claims too much (finding 1).
N8: rhythm September 1 joins two short sentences, September 5 takes the September 29 form, and October 14 splits at its semicolon. Accurate
N9: untouched paragraphs The owner moved it to a follow-up task. I can't verify it; nothing has reached GitHub yet.
N10: reply nits The reply gives the counts: the note field says 19 and 16, and the lists hold 18 and 17, which I confirmed. No link yet. Accurate; the owner still owes the link.

Checked and sound

  1. CI, checked once. gh pr checks 256 -R PolicyEngine/policybench showed run 41586835277 at b74ab23: lint pass (15s), app pass (1m41s), Vercel pass, test still running (exit 8). I didn't wait for it.

  2. Guard and schema tests at head. python -m pytest tests/test_notes.py -k "within_one_dollar or schema" -p no:cacheprovider -o tmp_path_retention_policy=failed, under a 2 GB memory cap: 15 passed.

  3. App tests at head. bun test tests/notes.test.ts in app/: 18 pass, 0 fail, 230 expect() calls.

  4. Merge rehearsal. I merged Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 onto the head with git merge --no-commit, once at 041c32f (the description's rehearsal) and once at Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's current head, df8289f, one commit later. When I keep the pending entry, the guard fails with "drop from pending", as its comment intends. When I drop the entry, -k "within_one_dollar or schema or america_gov" passes 19 tests on both merges, and bun test tests/notes.test.ts passes 18 (243 expects at 041c32f, 244 at df8289f). git diff --stat f00bebd2 b74ab232 touches only app/tests/notes.test.ts and docs/terra/design.md, so the description's rehearsal at f00bebd still covers the head.

  5. Mutations. On the merge with 041c32f, I ran each mutation through the guard and the app tests, and every one fails at least one:

    Mutation Guard App tests
    Put "weighted by household impact" back in October 31 fails fails
    Drop October 6's weighting sentence fails fails
    Move October 6's weighting sentence after "GPT-6 Sol still leads" passes fails
    Drop October 14's weighting sentence fails fails
    Drop October 20's weighting sentence fails fails
    Write October 20's weighting sentence as "It weights…", after the Opus and Argon sentence passes fails
    Restore r2's B1 in October 13 ("still leads at {solExact}%") passes fails
    Restore r2's B1 in October 14 passes fails
    Put September 22's weighting sentence before the definition fails fails
    Reword September 1's definition fails fails
    Give October 31's GPT-6.1 Sol score as "{sol61Exact}% within $1" passes fails
    Give October 31's GPT-6.1 Terra score as "{terraExact}% within $1 of the reference" passes fails
    Write "of its answers within $1" in October 13 fails fails
    Drop the America.gov weighting sentence fails fails
    Restore "bringing it to" in October 10 passes fails
    Restore GPT-6 Luna's "with it" in September 29 passes fails
    Add a sentence after the weighting in September 29's paragraph 0 fails passes
  6. Pins. I extracted every sentence that git diff 8ac64ac4 b74ab232 -- app/src/notes adds or rewrites and filled in its note's facts the way factText in NotesContent.tsx does: toFixed(1) for Exact and Rate facts, thousands commas, and words for :words facts under ten. Then I escaped apostrophes as renderToStaticMarkup does and searched the note's block in app/tests/notes.test.ts. All 48 sentence instances appear there whole.

  7. The weighting sentence, against the code (row_hit_scores, weighted_hit_rate_scores_by_model and bounded_global_variable_weights in policybench/analysis.py; weighted_exact in scripts/tool_pilot_note.py).

    • Every percentage in the nine notes other than October 20 comes from scores that carry household-impact weights, including the bounded scores and the sensitivity reruns. scorer_vectors.canonical_filtered_scores applies row_hit_scores with globalWeights.household, which equals bounded_global_variable_weights.
    • September 1 and 5: the release manifests at 28e41e8 and c7aaffe name the weighted exact rate as the headline. I recomputed it: Claude Fable 5.1 gets 86.309 (92.641 without weights), and GPT-6 Astra 87.984 (93.512 without weights), which round to the notes' 86.3% and 88.0%.
    • October 20, from release dashboard-data-20261014 (bf845cb): the six paragraph-0 scores reproduce with weighted_exact (95.2 and 99.2, 94.1 and 99.8, 88.7 and 99.9). The six paragraph-1 rates reproduce only as plain counts (finding 1).
    • In all nine notes and in docs/terra/design.md, "It weights" directly follows the definition, whose subject is PolicyBench. The guard's endswith check holds that order in the eight paragraph-0 notes, and the October 6 pin (${closing} GPT-6 Sol still leads at 95.8%) holds it in paragraph 5.
  8. Facts and titles. git diff --stat 8ac64ac4 b74ab232 lists 13 files: ten notes, tests/test_notes.py, app/tests/notes.test.ts and docs/terra/design.md. The note diffs touch paragraphs only: no fact, title or link changes.

  9. docs/terra/design.md numbers. The result line at head and on main give the same 93.14%, Update GitHub Actions for Node 24 runtime #3 of 51, 1,935 outputs, 97.19, $1.2532, $0.0125, 22.4 seconds, dates and input pins.

  10. Opening lengths. For each opening, I filled in the facts, left the HTML unescaped and counted the plain text. October 14 grows from 653 to 825 characters, and October 31 from 540 to 747.

  11. Flag count. In release dashboard-data-20261014, eligibility flags make up 975 of each model's 1,935 scored outputs: free_school_meals_eligible 100, person_chip_eligible 177, person_early_head_start_eligible 38, person_head_start_eligible 38, person_medicaid_eligible 173, person_medicare_eligible 172, person_wic_eligible 177 and reduced_price_school_meals_eligible 100.

  12. Line citations. app/src/app/notes/[slug]/page.tsx:28 (the meta description), app/src/components/NotesContent.tsx:369 (line-clamp-3) and app/src/lib/heatmapMetric.ts:22 hold at head.

  13. "Sentences that keep 'within $1'". At head, outside the definition, "within $1" appears only in October 6 paragraph 4, October 10 paragraphs 2 and 5, October 13 paragraphs 2 and 3, and October 20 paragraph 1, and each of those sentences covers amounts only. reference_audit/2026-10-09-engine-upgrade/final_actions.json regenerates 18 outputs: state income tax before refundable credits 8, federal income tax before refundable credits 7, state refundable credits 2 and payroll tax 1. The 2026-10-12 file regenerates 9: state income tax before refundable credits 6, federal refundable credits 2 and state refundable credits 1. is_amount agrees with the binary rule on all 63 scored variables.

  14. The count of eleven. On main (7bccd96), eleven notes carry "answers within $1" or "of answers within": these ten and the America.gov note. No other note does, and no field outside the prose carries the shorthand. The next-release list, which the owner keeps outside the repo, holds the line and the two checks the reply describes.

  15. The description's quotes. Every old fragment in the description's table and rewrite list appears in the notes on main, and every new one at head.

  16. Stale pins. No test in tests/test_notes.py or app/tests/notes.test.ts quotes a sentence this PR removes.

  17. Voice. I read the whole voice guide first. Then I grepped the changed sentences, the description and the reply for be-verb comparisons and be plus past participle, and read them by hand for participial passives, pronouns and rhythm. The new text accounts for findings 4, 5 and 7; the other hits in the description and the reply sit inside quoted old text. September 1's opening now runs 25, 13, 26 and 7 words.

  18. October 13's pronoun. "it ranks #{museBoundedRank}" follows "Muse Wonder gets…", so "it" points to Muse Wonder.

What I couldn't check

  • The CI test job, still running at my one check.
  • The Python release-note tests in tests/test_notes.py, which load release data and need more than 2 GB; CI runs them.
  • The deployed preview. I measured lengths with my own renderer of the app's fact rules, and checked rendering through the app tests' renderToStaticMarkup.
  • The owner's 16 mutations; I ran the 17 above instead.
  • The N9 follow-up task and the N10 follow-up PR, neither of which has reached GitHub.
  • The weighted rates in finding 1, which come from my own construction, not from PolicyBench code.
  • Where the record goes and the form of the weighting sentence: both are Max's calls.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed 5e9b4782 in answer to this review.

  1. Finding 1. We took your fix. Paragraph 0 of the October 20 note now says "PolicyBench weights each answer by household impact in these six scores." Paragraph 1 ends with "PolicyBench gives each amount the same weight in these six rates." Before writing the second sentence, we read facts in scripts/tool_pilot_note.py: it computes each nonzero-amount rate as hits over len(nonzero), with no weights. app/tests/notes.test.ts pins both sentences, and the description's October 20 bullet says which function computes which scores.
  2. Finding 2. The record line now reads: "Since the last release, PolicyBench has corrected eleven of its notes, from September 1 to October 31, where it defined the score by its $1 tolerance alone. PolicyBench applies the tolerance to dollar amounts and counts an eligibility answer as right only when it matches. No score moved." We gave PolicyBench the verb in the second sentence, where your version had "The tolerance applies". We added the line to the October 31 note in a scratch copy, and the guard and schema tests passed (15). The next-release list carries the same line.
  3. Finding 3. The description now gives both precedents, close to your wording. Release 20260922c also stopped scoring a Texas household's SNAP amount, so for the September 3 note's correction we wrote "later corrections" without "to their references". We also added that release 20260922c's corrections moved scores, while this one, like October 6's, moves none. Max decides where the record goes.
  4. Nit 4. October 10 now reads "Without those outputs, every earlier model's share of answers right would have risen, by …". We wrote "those outputs" where you wrote "them", because the sentence before ends "and {newlyScoredUnmatched:words} by none", which counts models. The pin follows.
  5. Nit 5. We made both changes as you wrote them, and the bullet's last sentence goes to the follow-up pass in item 9.
  6. Nit 6. We added your sentence-level check after the phrase ban and put its rule in the docstring. We also corrected the comment, which now says the October 20 note gives its weighted scores before the definition, so its sentence names PolicyBench and the six scores. Of the seven mutations at 5e9b4782, two give October 31's GPT-6.1 Sol and GPT-6.1 Terra scores "within $1", and both now fail the guard as well as the pins. A third drops "Of the {nonzeroAmounts} nonzero amounts" from October 20, and the guard catches it too.
  7. Nit 7. We opened "Why we change the notes" with your sentence, then gave every editing verb in the description an actor. "This PR rewrites" became "We rewrite published copy in this PR", and each "X replaces Y" became "We wrote X in place of Y".
  8. Nit 8. The Invariants section now says GitHub won't enforce the order, and names the steps for whoever merges second. We confirmed the setting: gh api repos/PolicyEngine/policybench/branches/main/protection returns "Branch not protected", and the branch has no rulesets.
  9. N9 (r2). We queued the full pass on the untouched paragraphs as a task that starts once Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 and this PR merge. It now also takes the last sentence of the design record's result line and October 10's "half of them are answered within $1". We'll link its PR here.
  10. N10 (r2). We queued the final_actions.json count as its own task, and we'll link its PR here too.

At 5e9b4782, the guard and schema tests pass (15), and so does bun test tests/notes.test.ts (18 tests, 231 expects). Each of the seven mutations fails at least one of them, 11 of 11 checks in all. To rehearse the second merge, we merged 5e9b4782 with #254's 70a53d97 and main, and the guard failed with "drop from pending" while we kept the pending entry. When we dropped it, the guard, schema and America.gov tests passed (19), and so did bun test tests/notes.test.ts (18 tests, 245 expects).

🤖 Generated with Claude Code

…shares

Review r4 found that the guard's sentence check reads only paragraphs, only
placeholder rates and only "within $1", and that the singular "amount"
satisfies it. We now check titles too, and treat a literal percentage or the
word "share" as a rate. We also catch "within a dollar" and "within one
dollar", and require the plural "amounts". We split sentences before a
lowercase word, such as policyengine-us, and after a closing quote or
parenthesis. We rewrote the test's docstring to state what the check
enforces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

MaxGhenis commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor Author

A Claude Opus 5.5 agent reviewed this PR at 5e9b4782 for the session that owns it. We post its review below and reply in the next comment. In the post, we bolded the verdict line, shortened its commit hash and left out the list of local files.


Verdict: APPROVE at 5e9b4782

Review r4 of #256 at 5e9b478, one commit after r3 (b74ab23). I made no edits, pushes or comments, and I ran tests only in a scratch clone, which I have deleted.

5e9b478 fixes r3's blocking finding as r3 proposed, and the description and the reply answer the other seven findings. The two new October 20 sentences match scripts/tool_pilot_note.py, CI passes at the head, and the merge with #254's new head, 0c916c2, behaves as the Invariants paragraph says. I found four nits and nothing that blocks. The merge still waits on Max's yes.

Nits

1. The sentence check I proposed in r3 misses literal percentages and titles, and it can fail an accurate sentence.

  • Where: tests/test_notes.py:6222-6230, and the docstring that starts at :6200.

  • On the merged tree, the check reads two sentences, America.gov paragraph 3 ("{fedTaxRate}% of federal amounts within $1") and October 20 paragraph 1, and both pass. I ran 15 mutations at the head through the guard and the app tests (table under "Checked and sound"). The guard catches the four that give a {…Exact}% or {…Rate}% fact "within $1" in one sentence. It misses six:

    • B1, a literal "93.1% within $1";
    • B2, "{terraExact}% within $1 of the reference amount", which passes because "amount" appears anywhere in the sentence;
    • B3, the rate and "within $1" in two sentences;
    • B4, October 6's "Every model's share within $1 rises by", which gives no rate fact;
    • B5, "within a dollar";
    • B6, an October 31 title, "OpenAI's GPT-6.1 Terra joins the board at Update GitHub Actions for Node 24 runtime #3 with 93.1% within $1".
  • The app pins catch B1 to B5, since they pin today's sentences whole. Nothing catches B6: the check reads paragraphs and placeholders, and a title can hold only a literal. A future release note has no pins until its author writes them, so only the guard checks it.

  • Two mutations fail the guard on accurate sentences:

    • C1, October 13 paragraph 3: "Muse Wonder answers {museRestored:words} of them within $1 and gets {museExact}% of answers right overall." The "within $1" belongs to a count. Splitting the sentence fixes it.
    • C2, October 13 paragraph 0: I inserted "policyengine-us {engineVersion} brings every restored output within $1 of the corrected value." after the sentence in which GPT-6 Sol still leads at {solExact}%. The split needs a capital letter after the full stop, so the check reads the two as one sentence, finds "{solExact}%" and "within $1" in it, and fails it. Today's notes hold nine sentences that open with "policyengine-us", a placeholder or a quotation mark.
  • The docstring's "a note that gives a rate within $1 says the rate covers amounts" promises more than the check enforces. The description's Invariants bullet limits it correctly to {…Exact}% and {…Rate}% facts.

  • This variant closes four of the six gaps and the C2 misfire. I ran it as a text scan over the notes, not inside pytest:

            # A rate within $1 covers dollar amounts only, so its sentence
            # names them.
            for part in (note["title"], *note["paragraphs"]):
                for sentence in re.split(r"(?<=[.!?])\s+", part):
                    if re.search(
                        r"(?:\{\w+(?:Exact|Rate)\}|\b\d+(?:\.\d+)?)%", sentence
                    ) and re.search(r"within (?:\$1\b|a dollar|one dollar)", sentence):
                        assert re.search(r"\bamounts\b", sentence), (path.name, sentence)

    It flags nothing on the merge of main, Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 at 0c916c2 and this head. At this head it flags only the America.gov note, which the guard still skips. It catches A1 to A4, B1, B2, B5 and B6, and it passes C2. It still misses B3 and B4, and it still fails C1. Requiring the plural "amounts" catches B2's "reference amount", at the cost of rejecting a singular such as "of each amount", which no note uses. Splitting on any space after ., ! or ? finds no abbreviation in today's notes to split wrongly.

  • Adopt the variant here or in the follow-up pass, or narrow the docstring to what the check enforces.

2. Reply item 3 dates the Texas exclusion to the wrong release.

3. The Invariants paragraph rehearses with #254's 70a53d9, and #254's head has moved to 0c916c2. 0c916c2 adds three lines to test_america_gov_note_predicates and nothing else. At 0c916c2 the rehearsal gives the description's results (item 4 under "Checked and sound"), so only the SHA needs updating.

4. The docstring runs one 54-word sentence, and "the board" takes its first verb. Optional: "PolicyBench scores eligibility flags by exact match, not within $1. So no note gives an all-outputs score as answers within $1, and a note that gives a rate within $1 says the rate covers amounts. A note that gives a score as answers right defines it and says how PolicyBench weights the answers." If you narrow the rate clause under nit 1, carry that wording here.

r3 findings and the reply at 5e9b478

Item What the head does The reply
1 (blocking): October 20's weighting sentence Takes r3's fix. Paragraph 0 says "PolicyBench weights each answer by household impact in these six scores." and paragraph 1 ends "PolicyBench gives each amount the same weight in these six rates." app/tests/notes.test.ts:193 and :200 pin both. The description's October 20 bullet names weighted_exact and facts. Accurate. facts computes the six rates as hits over len(nonzero) with no weights.
2: the record line failed the guard Rewords the line so that PolicyBench takes the verb in both of its first two sentences, and the line passes the guard (item 5 below). The next-release list holds the same line, character for character. Accurate
3: the placement rule overstated the record Gives both precedents in the description and leaves the choice to Max. Accurate, apart from the Texas release (nit 2).
4: October 10's participial passive Writes "Without those outputs", and the pin at app/tests/notes.test.ts:371 follows. "Those outputs" skips past the models that the sentence before counts and points to the restored outputs. Accurate
5: docs/terra/design.md:144 Makes both edits in r3's wording. The bullet's last sentence ("…is dated…") waits for the follow-up pass, as r3 suggested. Accurate
6: the guard let a percentage "within $1" through Adds r3's check, which catches the two October 31 cases. The comment now says October 20 gives its weighted scores before the definition and names the six scores. Accurate. The check's own limits sit in nit 1.
7: the description's opening The description now opens with "PolicyBench gave the headline score in ten notes as "answers within $1"." Each editing verb in it now has an actor. Accurate
8: nothing enforced the merge order Names, in the Invariants paragraph, the steps for whoever merges second. Accurate (item 10 below).
9: r2's N9, untouched paragraphs Leaves it to a follow-up task, which now also takes the design record's last sentence and October 10's "half of them are answered within $1". r2's N9 list already named that phrase in October 10 and October 13. I can't verify it; nothing has reached GitHub.
10: r2's N10, the final_actions.json count Leaves it to a task of its own. I can't verify it; no link yet.

Checked and sound

  1. The delta. git log b74ab232..5e9b4782 lists one commit. It touches five files: the October 10 and October 20 notes, docs/terra/design.md, app/tests/notes.test.ts and tests/test_notes.py. In the notes it changes paragraphs only (October 10's 5, October 20's 0 and 1), with no fact, title or link. The design record's line 144 keeps every figure from main.

  2. CI, which I checked once. gh pr checks 256 -R PolicyEngine/policybench exited 0. Run 41592991867 at 5e9b478 passed lint (14s), app (1m30s) and test (14m22s), and the Vercel and Vercel Preview Comments checks passed. GitHub lists the PR as a draft and reports it MERGEABLE.

  3. Tests at the head. python -m pytest tests/test_notes.py -k "within_one_dollar or schema" -p no:cacheprovider -o tmp_path_retention_policy=failed, under a 2 GB cap: 15 passed, with a peak of 146,880 KiB. bun test tests/notes.test.ts in app/: 18 pass, 0 fail, 231 expects.

  4. Merge rehearsal with Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 at 0c916c2. gh pr view 254 gives head 0c916c2, and main stays at 7bccd96. Both PRs branch from 8ac64ac, so I merged Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 and then main into the head, and both merges went through without conflicts. With the pending entry kept, the guard fails with "drop from pending". With pending: set[str] = set(), -k "within_one_dollar or schema or america_gov" passes 19 tests (peak 871,488 KiB), and bun test tests/notes.test.ts passes 18 with 245 expects. Those match the description's results at 70a53d9.

  5. The record line. On that merge, with the entry dropped, I appended the line to the October 31 note's paragraphs, and the guard and schema tests passed (15). The description and the next-release list hold the same line. On main, eleven notes carry "answers within $1": the ten this PR changes and the America.gov note, so the count holds once both PRs merge.

  6. October 20 against the code. In scripts/tool_pilot_note.py, weights (line 200) splits each output group's household-impact weight across its outputs and renormalizes within the household, and weighted_exact (218) sums each household's weighted hits and averages the households. facts uses weighted_exact for BoardExact and ToolExact (318-319), the six scores in paragraph 0. It computes NonzeroRate and NonzeroToolRate (320-325) as 100 * sum(hit(...) for k in nonzero) / len(nonzero), with no weights, over the 187 amounts that is_amount keeps with nonzero references (309). Both new sentences match the code, and so do the description's October 20 bullet and reply item 1.

  7. The comment's placement claim. On the merge, ten of the eleven notes that carry the definition follow it directly with SCORE_WEIGHTING. October 20 gives "PolicyBench weights each answer by household impact in these six scores." in paragraph 0, before its definition in paragraph 1.

  8. Mutations at the head. I ran each through the guard (-k within_one_dollar) and bun test tests/notes.test.ts, restored the file after each run, and left the clone clean.

    ID Mutation Guard App tests
    A1 October 31: "{sol61Exact}% within $1" fails fails
    A2 October 31: "{terraExact}% within $1 of the reference" fails fails
    A3 October 20: drop "Of the {nonzeroAmounts} nonzero amounts, " fails fails
    A4 October 14: "{argonExact}% within $1" fails fails
    A5 October 20: restore "…by household impact, on the board and with the tool." passes fails
    A6 October 20: drop the equal-weight sentence passes fails
    A7 October 10: restore "Had they stayed excluded," passes fails
    B1 October 31: a literal "93.1% within $1" passes fails
    B2 October 31: "{terraExact}% within $1 of the reference amount" passes fails
    B3 October 31: the rate and "within $1" in two sentences passes fails
    B4 October 6: "Every model's share within $1 rises by" passes fails
    B5 October 31: "{sol61Exact}% within a dollar" passes fails
    B6 October 31 title: "…at Update GitHub Actions for Node 24 runtime #3 with 93.1% within $1" passes passes
    C1 October 13: "…of them within $1 and gets {museExact}% of answers right overall." (accurate) fails fails
    C2 October 13 paragraph 0: insert "policyengine-us {engineVersion} brings every restored output within $1 of the corrected value." (accurate) fails passes

    A1 to A3 and A5 to A7 repeat six of the owner's seven mutations, and the owner's record shows all seven failing the 11 checks they target. I didn't rerun the seventh, which drops October 20's weighting sentence.

  9. Quotes. Every old fragment in the description's table and rewrite list appears on main (7bccd96), and every new one at the head. Each quote in the reply appears where the reply puts it: the new note sentences at the head only, October 10's "half of them are answered within $1" on main and at the head, "drop from pending" in the guard, and the record line in the description.

  10. Branch protection. gh api repos/PolicyEngine/policybench/branches/main/protection returns "Branch not protected", and rules/branches/main and rulesets both return [].

  11. Voice. I read the whole voice guide this turn. The three new note sentences and the design record's two edits give each verb a named actor: "PolicyBench weights…", "PolicyBench gives…", "every one of its outputs parses", "GPT-6.1 Terra answered". Greps of the description and the reply for be-verb plus participle and be-verb comparisons hit only quoted old text ("was released", "is scored", "are answered"). Each of the record line's three sentences has an actor or a real verb, and the line takes the correction as its subject, as a correction record should. The new comments read active, and I found no label openers, self-referential clauses or empty antitheses in the new text.

What I couldn't check

  • The rest of tests/test_notes.py: its release-note tests need more than 2 GB. CI's test job ran them and passed.
  • The deployed preview, beyond the passing Vercel checks.
  • The N9 and N10 follow-up tasks, which haven't reached GitHub.
  • Which release first scored the September 3 households at the rounded minimum. I traced only the Texas exclusion.
  • The variant in nit 1 inside pytest. I ran it only as a text scan.
  • Where the record goes and the merge: Max decides both.

@MaxGhenis

MaxGhenis commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed def8324c in answer to this review.

  1. Nit 1. We adopted your variant and extended it twice. The check also counts the word "share" as a rate, so it catches B4, October 6's "Every model's share within $1 rises by". Its splitter also ends a sentence after a closing quote or parenthesis, so a quoted "answers right." no longer runs into the definition that follows it. At def8324c, we ran your 15 mutations and 7 of our own through the guard (-k within_one_dollar) and restored the note after each run:

    • The guard fails A1 to A4, B1, B2 and B4 to B6, and our D1 ("{sol61Exact}% within one dollar") and D4 (an October 31 title with "the third-highest share within $1").
    • It passes A5 to A7, which your table shows the app pins catching, and C2.
    • It still misses B3, and it still fails C1, which an author can split.
    • D2 and D3 put "answers right." in straight and curly quotes before the definition in October 13's paragraph 0. Your splitter reads each pair as one sentence and flags it, and ours passes both.
    • D5 and D6 give "93.1% of amounts within $1" in a title and "93.1% of nonzero amounts within $1" in a paragraph, and the guard passes both. It also passes D7's "within $10", since the pattern needs a word boundary after "$1".
  2. Nit 2. Item 3 of our reply to r3 named the wrong release. PolicyBench stopped scoring the Texas household's SNAP amount in release dashboard-data-20260922 (Add Claude Opus 5.5, GPT-6 Sol and GPT-6 Luna; publish the September 22 reference audit #174), not 20260922c, and the item's conclusion holds, as you found. In the description's record paragraph, we wrote "Those corrections moved scores." in place of "Those corrections, from release 20260922c, moved scores." We also dropped the release from the same sentence in the next-release list.

  3. Nit 3. Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's head moved again, to ced79ca5, which adds asserts to its predicates test. We merged def8324c with ced79ca5 and main (7bccd967) and ran pytest tests/test_notes.py -k "within_one_dollar or schema or america_gov". When we kept the pending entry, the guard failed with "drop from pending" and the other 18 tests passed. When we dropped it, all 19 passed, and bun test tests/notes.test.ts passed 18 tests with 245 expects. We also added the record line to the October 31 note on that merge, and the guard and schema tests passed (15). We updated the Invariants section with these runs.

  4. Nit 4. We took your docstring, split its second sentence in two and narrowed the rate clause to what the check enforces:

    A title or sentence that gives a percentage or a share within $1, or within a dollar, also names the amounts that figure covers.

At def8324c, the guard and schema tests pass (15), and we'll tick CI's box in the description when its run passes.

🤖 Generated with Claude Code

Review r5 ran four mutations that give a share or a percentage within $1
without naming the amounts, and def8324's guard passes all four. Two use
"share" in the plural or at the start of a sentence, one a {…Share}%
placeholder and one "within a $1 tolerance". The guard read only {…Exact}%
and {…Rate}% placeholders, a literal percentage and the lowercase word
"share", and only "within $1", "within a dollar" and "within one dollar".

We take the reviewer's two patterns. The guard now reads any placeholder or
literal number before "%", "share" or "shares" in any case, and "within",
"within a" or "within one" before "$1" or "dollar". So the docstring and the
comment now describe what the guard reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

A Claude Opus 5.5 agent reviewed this PR at def8324c for the session that owns it. We post its review below without its list of local files, and reply in the next comment.


VERDICT: APPROVE at def8324

Review r5 of #256 at def8324, a delta review of the one commit after r4 (5e9b478). I made no edits, pushes, commits or comments, and I ran tests only in a scratch clone, which I have deleted.

def8324 changes only tests/test_notes.py. At the head, its check fails every mutation that the description and the reply say it fails, and passes every one they say it passes. The merge with #254's ced79ca5 and main behaves as the rehearsal paragraph says. Reply item 1 and the mutation paragraph's counts hold, and CI passes at the head. The docstring, the Invariants bullet and reply item 4 overstate the check: they promise it reads any percentage and the word "share", and the code reads three kinds of percentage and only the lowercase, singular "share". Two wider patterns make those words true and flag nothing in today's notes; I ran them through the guard, both mutation batteries and ruff (nit 1). Nothing blocks. GitHub still lists the PR as a draft, and its merge still waits on Max's yes.

Nits

1. The docstring, the Invariants bullet and reply item 4 promise more than the trigger reads.

  • Where: tests/test_notes.py:6227-6228 and the docstring at :6200; the Invariants bullet ("pairs a percentage or the word "share""); reply item 4 ("narrowed the rate clause to what the check enforces"); the commit message ("to state what the check enforces").

  • The trigger reads {…Exact}%, {…Rate}%, a literal percentage and the lowercase word "share". Three of my mutations give a share or a percentage within $1 without "amounts", and the guard passes all three:

    • E1, October 6: "The models' shares within $1 rise by";
    • E2, October 6: "Share within $1 rises for every model, by";
    • E3, October 31: "gets {sol61Share}% within $1 (#". Today's notes use nine percentage placeholder names that end in neither Exact nor Rate, two of them in Share.
  • A fourth, E4, "gets {sol61Exact}% within a $1 tolerance (#", gets through because the within pattern takes only "within $1", "within a dollar" and "within one dollar". The docstring and the bullet list those phrases, so E4 opens a gap but breaks no promise.

  • These two patterns close all four:

                    if re.search(
                        r"(?:\{\w+(?::\w+)?\}|\b\d+(?:\.\d+)?)%|(?i:\bshares?\b)", sentence
                    ) and re.search(r"within (?:a |one )?(?:\$1\b|dollar\b)", sentence):
    • With them at the head, the guard and schema tests pass (15). On the merge with ced79ca5 and main, once I drop the entry, the guard, schema and America.gov tests pass (19).
    • All 22 of the owner's mutations give the same result as under def8324's patterns. E1 to E4 fail, and E5 and F1 to F3 keep their results (table below).
    • A text replica of the check agrees with pytest on all 30 mutations, verdict and flagged sentence alike. Under both pattern sets it flags the same 12 sentences on main outside the America.gov note, and none at the head or on the merge.
    • ruff check and ruff format --check pass on the patched file. The longer line runs to 87 characters.
    • The wider placeholder pattern also reads limits such as {bbceGrossLimitHigh}%. A future sentence that pairs one with "within $1" then fails until its author names the amounts, as in nit 2, and the author sees that failure at once, while a gap stays silent.
  • With these patterns, the docstring, the comment, the bullet and reply item 4 hold as written. Otherwise, narrow the words to the code, for example "a {…Exact}% or {…Rate}% placeholder, a literal percentage or the lowercase word "share"".

  • Two limits stay with any word check. The guard looks for "%", and no note spells out "percent". And it reads words, not figures. E5, "GPT-6.1 Terra gets {terraExact}% within $1 across amounts and flags and ranks", passes on "amounts", though terraExact covers flags too. The owner's D5 title gives Terra's all-outputs 93.1% (terraExact) as "93.1% of amounts within $1" and passes the same way. So the mutation paragraph's "accurate edits such as … a title that names the amounts" fits D5's wording, not its figure.

2. The guard fails more accurate sentences than the mutation paragraph says.

  • The paragraph names one misfire, C1, "an accurate sentence that gives a count within $1 beside a score, which an author can split". Two accurate sentences of mine also fail the guard, and splitting fixes neither:
    • F1, October 6: "No model gets any share of the {incomeTaxOutputs:words} income tax outputs within $1 of the reference.";
    • F2, October 10: "50% of them are answered within $1 by at most", in place of "half of them".
  • Naming the amounts passes both ("income tax amounts", "50% of those amounts"). The paragraph could end: "…and it fails accurate sentences that put "within $1" beside a count, a percentage of outputs or "share" in its plain sense. Splitting the sentence or naming the amounts passes them."
  • F3 puts "(e.g. tax credits)" after "nonzero amounts" in October 20's paragraph 1. The splitter breaks the sentence after "e.g.", and the guard fails the second half. No note at main, the head or the merge uses "e.g.", "i.e." or another abbreviation with a full stop, so F3 stays theoretical.

3. Two optional edits to the posted reply.

CI at def8324

I read gh pr checks 256 -R PolicyEngine/policybench once, at 08:13Z. It exited 0: lint (16s), app (1m21s) and test (9m53s) pass in run 41598978880, and Vercel and Vercel Preview Comments pass. gh pr view gives head def8324c, mergeable MERGEABLE, merge state CLEAN, and draft. The description's unticked CI box can cite that run.

Checked and sound

  1. Head. At def8324c, the guard and schema tests pass (15; peak 145,648 KiB), and bun test tests/notes.test.ts passes 18 tests with 231 expects.

  2. Mutations. I ran each one through the guard alone (-k within_one_dollar), one at a time, and restored the note after each run; every run peaked under 153,000 KiB. All 22 of the owner's results match the reply, and the clone stayed clean after the def8324 battery. The last column swaps in nit 1's patterns.

    ID Mutation def8324 Nit 1's patterns
    A1 October 31: "{sol61Exact}% within $1" fails fails
    A2 October 31: "{terraExact}% within $1 of the reference" fails fails
    A3 October 20: drop "Of the {nonzeroAmounts} nonzero amounts, " fails fails
    A4 October 14: "{argonExact}% within $1" fails fails
    A5 October 20: restore "…on the board and with the tool." passes passes
    A6 October 20: drop the equal-weight sentence passes passes
    A7 October 10: restore "Had they stayed excluded," passes passes
    B1 October 31: a literal "93.1% within $1" fails fails
    B2 October 31: "{terraExact}% within $1 of the reference amount" fails fails
    B3 October 31: the score and "within $1" in two sentences passes passes
    B4 October 6: "Every model's share within $1 rises by" fails fails
    B5 October 31: "{sol61Exact}% within a dollar" fails fails
    B6 October 31 title: "…at Update GitHub Actions for Node 24 runtime #3 with 93.1% within $1" fails fails
    C1 October 13: a count within $1 and "{museExact}% of answers right" in one sentence (accurate) fails fails
    C2 October 13 paragraph 0: insert "policyengine-us {engineVersion} brings every restored output within $1 of the corrected value." (accurate) passes passes
    D1 October 31: "{sol61Exact}% within one dollar" fails fails
    D2 October 13 paragraph 0: "answers right." in straight quotes before the definition (accurate) passes passes
    D3 The same in curly quotes (accurate) passes passes
    D4 October 31 title: "…with the third-highest share within $1" fails fails
    D5 October 31 title: "…with 93.1% of amounts within $1" passes passes
    D6 October 31: "93.1% of nonzero amounts within $1" passes passes
    D7 October 31: "{sol61Exact}% within $10" passes passes
    E1 October 6: "The models' shares within $1 rise by" passes fails
    E2 October 6: "Share within $1 rises for every model, by" passes fails
    E3 October 31: "{sol61Share}% within $1" passes fails
    E4 October 31: "{sol61Exact}% within a $1 tolerance" passes fails
    E5 October 31: "{terraExact}% within $1 across amounts and flags" passes passes
    F1 October 6: "No model gets any share of the … income tax outputs within $1 of the reference." (accurate) fails fails
    F2 October 10: "50% of them are answered within $1" (accurate) fails fails
    F3 October 20: "nonzero amounts (e.g. tax credits)," fails fails

    A5 to A7 pass the guard, and r4's runs at 5e9b4782 show the app pins failing all three, as reply item 1 says.

  3. Splitter. The owner's split_check.py reproduces: r4's splitter flags D2 and D3, and the committed one passes both. In today's notes, the committed splitter adds 10 split points to 5e9b4782's, each at a real sentence end.

  4. Merge rehearsal. 85e330a8 merges Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's ced79ca5 and then main (7bccd967) into def8324c, and gh still gives both heads. When I kept the entry, -k "within_one_dollar or schema or america_gov" failed 1 test ("drop from pending") and passed 18 (peak 880,384 KiB). When I dropped it, 19 passed (peak 877,648 KiB), and bun test tests/notes.test.ts passed 18 tests with 245 expects. The description's rehearsal paragraph and reply item 3 say the same.

  5. The record line. On that merge, after dropping the entry, I appended the next-release list's line to the October 31 note, and the guard and schema tests passed (15; peak 146,752 KiB). The description and the list hold the same line.

  6. The description, r6 to r7. Five passages change. "Those corrections moved scores." takes r4's wording. The rehearsal paragraph matches item 4. The mutation paragraph's counts match the battery: the guard fails eleven (A1 to A4, B1, B2, B4 to B6, D1 and D4), passes D2, D3 and D5, misses B3 and fails C1; nits 1 and 2 cover the rest. The Checks list ticks r4 and links both comments. Nit 1 covers the Invariants bullet.

  7. The reply. Items 1 to 3 match my reruns, including the Texas release (Add Claude Opus 5.5, GPT-6 Sol and GPT-6 Luna; publish the September 22 reference audit #174) and the October 31 record-line run. Item 4's quote matches the docstring; nit 1 covers its "what the check enforces".

  8. Next-release list. The owner cut ", from release dashboard-data-20260922c," from the list's precedent sentence and kept the record line.

  9. The posted r4. Comment 6598451284 matches my file without its "Local files" section, under the owner's intro line and a reformatted verdict line.

  10. Commit. def8324c changes one file (13 lines in, 14 out). Its message holds, apart from "to state what the check enforces" (nit 1).

  11. Voice. I read the whole voice guide this turn. The changed description sentences, the docstring and the new comment give each verb an actor, and a grep finds no be-verb or passive in them. In the reply, only item 3's participles and item 2's release-as-actor slip (nit 3).

What I couldn't check

  • I ran the guard alone on the mutations at def8324c, without the app tests. A5 to A7 rest on r4's app-test runs at 5e9b4782, and def8324c leaves app/ untouched.
  • I didn't run the whole tests/test_notes.py, whose release-note tests exceed 2 GB. CI's test job ran it at the head.
  • I didn't compute Terra's share of amounts within $1 to test D5's figure. That means loading the 139 MB dashboard data, which I left alone under this review's 1 GB run limit.

@MaxGhenis

MaxGhenis commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed 5101a8ee in answer to this review.

  1. Nit 1. We took your two patterns in 5101a8ee, so the docstring, the comment and the Invariants bullet now describe what the guard reads. We reran your battery at 5101a8ee, one mutation at a time: the guard fails E1 to E4, and the other 26 mutations keep the results in your table's last column. The guard and schema tests pass there (15), and so do ruff check and ruff format --check. We also rewrote the limits in the description's mutation paragraph: the guard reads words, not figures, so it passes D5's title and E5.
  2. Nit 2. We added to the mutation paragraph that the guard fails accurate sentences that put "within $1" beside a count, a percentage of outputs or "share" in its plain sense. We also wrote that the author of such a sentence passes the guard by naming the amounts, or, for a count, by splitting the sentence. We left F3 out, since no note uses an abbreviation that ends in a full stop.
  3. Nit 3. In our reply to r4, we changed item 2 to "PolicyBench stopped scoring the Texas household's SNAP amount in release dashboard-data-20260922 (Add Claude Opus 5.5, GPT-6 Sol and GPT-6 Luna; publish the September 22 reference audit #174), not 20260922c". In item 3, we wrote "When we kept the pending entry" and "When we dropped it". We also changed the header of the r4 post, which said we posted your review "as it wrote it". It now says that we bolded the verdict line, shortened its commit hash and left out the list of local files.

We merged 5101a8ee with #254's ced79ca5 and main (7bccd967) and ran the rehearsal again. When we kept the pending entry, the guard failed with "drop from pending" and the other 18 tests passed. When we dropped it, all 19 passed, and bun test tests/notes.test.ts passed 18 tests with 245 expects. We'll tick CI's box when the run at 5101a8ee passes.

🤖 Generated with Claude Code

The r6 reviewer found three sentences that 5101a8e's guard passes: G1
and G2 open with "Within $1,", and G3 with "Answers within $1". The
guard's pattern matched "within" in lowercase, and its phrase check kept
the text's capitals.

We take the reviewer's two lines, so the guard now matches "within" with
a lowercase or capital w and checks the banned phrases against the
lowercased text. The guard now fails G1, G2 and G3, the other 30
mutations keep their results, and the guard and schema tests pass (15).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

A Claude Opus 5.5 agent reviewed this PR at 5101a8ee for the session that owns it. We post its review below without its list of local files, and reply in the next comment.


VERDICT: APPROVE at 5101a8e

Review r6 of #256 at 5101a8e, a delta review of the one commit after r5 (def8324). I made no edits, pushes, commits or comments, and I ran tests only in a scratch clone, which I have deleted.

In 5101a8ee, the owner took my r5 patterns and changed nothing else: its test file matches def8324's with patch_p2.py applied, byte for byte. Its message holds, apart from one verb (nit 4). The owner's 30 battery results, the rehearsal on the merge with #254 and main, and the head's tests all hold when I rerun them, and CI passes at the head. Description r8, reply r5 and the two edited comments match the code and my runs, apart from two sentences in the mutation paragraph (nits 2 and 3). The guard reads "within" and the three banned phrases in lowercase only, so it passes a sentence that opens "Within $1," or "Answers within $1". I left that gap in my r5 patterns, and a two-line patch closes it without flagging anything new in today's notes (nit 1). Nothing blocks. GitHub still lists the PR as a draft, and its merge still waits on Max's yes.

Nits

1. The guard reads "within" and the banned phrases in lowercase only.

  • tests/test_notes.py:6228 matches "within" but not "Within", and :6221 checks the three banned phrases against the text as written. At 5101a8ee, the guard passes three mutations that open a sentence with a capital:

    • G1, October 6: "Within $1, every model's share rises by {riseMin} to {riseMax} points.";
    • G2, October 31: "Within $1, GPT-6.1 Sol, which OpenAI released on September 29, gets {sol61Exact}% (#{sol61Rank}).";
    • G3, October 6: "Answers within $1 rise for every model, by {riseMin} to {riseMax} points."
  • In r5, I found the same gap in the trigger with E2 ("Share within $1 rises…"), and the guard at 5101a8ee reads "share" in any case for that reason. I left "within" lowercase in the same patterns.

  • This patch closes all three:

    -            assert phrase not in text, (path.name, phrase)
    +            assert phrase not in text.lower(), (path.name, phrase)
    ...
    -                ) and re.search(r"within (?:a |one )?(?:\$1\b|dollar\b)", sentence):
    +                ) and re.search(r"[Ww]ithin (?:a |one )?(?:\$1\b|dollar\b)", sentence):
    • With it at the head, the guard fails G1, G2 and G3, the guard and schema tests pass (15), and ruff check and ruff format --check pass. The longer line runs to 87 characters.
    • A text replica of the check agrees with the owner's pytest results on all 30 mutations, verdict and flagged sentence alike. With the patch, it gives the same 30 results and flags nothing new at main, the head, the merge or Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's head. No note at those four commits has a capital "Within", and when I lowercase the text, the phrase check finds no new hit there.
  • Without the patch, Invariants bullet 1 overstates the guard, since a paragraph that says "Answers within $1" passes. Bullet 2 quotes "within" in lowercase and holds as written; with the patch, it could add "Within".

2. One sentence in the mutation paragraph ties two limits to one cause.

  • "It reads words, not figures, so it passes a title that names the amounts beside an all-outputs score, and it misses a score and "within $1" in separate sentences."
  • The guard misses B3 because it checks each title and sentence on its own, not because it reads words. And the guard passes such sentences as well as such titles. D6 ("93.1% of nonzero amounts within $1") and E5 pass the same way as D5's title, and reply r5 item 1 names E5.
  • You could write: "It reads words, not figures, so it passes a title or sentence that names the amounts beside an all-outputs score. It checks each title and sentence on its own, so it misses a score and "within $1" in separate sentences."

3. Of the three misfires, only C1 passes the guard when its author splits it.

  • The paragraph says "An author who splits such a sentence or names the amounts passes it." C1 gives its count and its score in two clauses with "and" between them, so its author can split them into two sentences, and the guard passes both. F1 and F2 keep "share" or the percentage in one clause with "within $1", so their author has to name the amounts to pass the guard. And in that sentence, "it" can refer to the guard or to the sentence.
  • My r5 text said splitting fixes neither F1 nor F2, and my suggested ending ("Splitting the sentence or naming the amounts passes them") still blurred the point.
  • You could write: "The author of such a sentence passes the guard by naming the amounts, or, for a count, by splitting the sentence."
  • Reply r5 item 2 quotes the same sentence. If you change the description, update item 2 or note the change in the next reply.

4. The commit message gives a review a reviewer's verb.

  • "Review r5 ran four mutations": the reviewer ran them ("The r5 reviewer ran four mutations"). A force-push costs more than the fix, so let a later commit message name the reviewer.
  • The Checks list's "Review r5 at def8324c approved" follows GitHub's review states and the list's earlier lines, so I leave it.

CI at 5101a8e

I read gh pr checks 256 -R PolicyEngine/policybench once, at 08:49Z. It exited 0, with lint (13s), app (59s), test (12m28s), Vercel and Vercel Preview Comments all passing. The three CI jobs ran on 5101a8ee in run 41604152495, which finished at 08:45:57Z. gh pr view gives head 5101a8ee, mergeable MERGEABLE, merge state CLEAN, and draft. The owner can now tick the description's CI box and cite that run, as reply r5 planned.

Checked and sound

  1. Commit. 5101a8ee has one parent, def8324c, and changes only tests/test_notes.py (2 lines in, 2 out). The file I patched in r5, the owner's r8/test_notes.p2.py and the file at 5101a8ee all hash to blob be4a1a81. The message's claims hold: E1 to E4 pass under def8324c (r5's table), and the guard read the forms the message lists. "Any placeholder" holds too: NotesContent.tsx renders only {name} and {name:words}, and the trigger reads both before "%". Nit 4 covers the first verb.
  2. Head. At 5101a8ee, the guard and schema tests pass (15; peak 145,872 KiB), bun test tests/notes.test.ts passes 18 tests with 231 expects, and ruff check and ruff format --check pass.
  3. Battery. The owner's r8/mut/battery.out gives the same 30 results as my r5 table's last column. I reran C2, D2, E1 to E4 and F1 at the head, one at a time, each under 134,000 KiB: E1 to E4 and F1 fail, and C2 and D2 pass, as the owner's file says. The clone stayed clean after.
  4. Merge rehearsal. d7d4ab3 merges Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's ced79ca5 and then main (7bccd967) into 5101a8ee, and at 08:49Z gh still gave both heads. When I kept the entry, -k "within_one_dollar or schema or america_gov" failed 1 test ("drop from pending") and passed 18 (peak 877,024 KiB). When I dropped it as the owner did (pending = set()), 19 passed (peak 869,264 KiB), and bun test tests/notes.test.ts passed 18 tests with 245 expects. When I deleted the whole block instead (the comment, the set and the branch, 7 lines), the 19 tests and ruff passed too (peak 872,288 KiB). So whoever merges second can delete the dead branch with the entry.
  5. The record line. On that merge, after dropping the entry, I appended the next-release list's line to the October 31 note, and the guard and schema tests passed (15; peak 117,872 KiB).
  6. The description, r7 to r8. The owner changed five passages. The Invariants bullet matches the patterns at the head (nit 1 covers case). The rehearsal paragraph matches my reruns. The mutation paragraph's counts hold: 15, 7 and 8 make the 30, and the guard fails the fifteen true catches (A1 to A4, B1, B2, B4 to B6, D1, D4 and E1 to E4). Nits 2 and 3 cover two sentences. In the Checks list, the owner ticked r5 and linked both comments, and the CI line names the head.
  7. Reply r5. Items 1 and 3 and the closing paragraph match my reruns and the edited comments. Item 2's F3 reason holds: in the notes at main, the head, the merge and Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's head, the splitter never splits after an initialism or a listed abbreviation or before a digit. It splits before a lowercase letter seven times, each at a real sentence end before "policyengine-us". Nit 3 covers item 2's second sentence.
  8. The edited comments. In comment 6598452144, item 2 now gives PolicyBench the verb and names release dashboard-data-20260922 (Add Claude Opus 5.5, GPT-6 Sol and GPT-6 Luna; publish the September 22 reference audit #174), as r5 found, and item 3 reads "When we kept" and "When we dropped". Comment 6598451284's header names the edits to the r4 post; apart from the verdict line and the local-files list, the post matches my r4 file.
  9. Voice. I read the whole voice guide this turn. The changed sentences in the description, the reply, both comments and the commit message give each verb an actor, and a grep finds no be-verb or passive in them. Nits 2 to 4 cover the exceptions.

What I couldn't check

  • I didn't run the whole tests/test_notes.py, whose release-note tests exceed 2 GB. CI's test job ran it at the head.
  • I ran nit 1's patch through pytest at the head only. On the merge, I checked it with the text replica and the phrase scan, not with pytest, to stay clear of the release's memory window.

@MaxGhenis

MaxGhenis commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) pushed 71b8641e in answer to this review.

  1. Nit 1. We took your two lines in 71b8641e and reran the battery there with your G1 to G3, one mutation at a time. The guard fails all three, and it gives the other 30 mutations the same verdicts and flags the same sentences as before. The guard and schema tests pass (15), and so do ruff check and ruff format --check. We added "in any case" to the first Invariants bullet and "Within" to the second.
  2. Nit 2. We took your two sentences for the mutation paragraph, so it now gives the per-sentence check as B3's cause and covers sentences as well as titles.
  3. Nit 3. We took your ending: "The author of such a sentence passes the guard by naming the amounts, or, for a count, by splitting the sentence." In item 2 of our reply to r5, we rewrote the second sentence the same way.
  4. Nit 4. We left 5101a8ee's message as it stands, and 71b8641e's message names you as the one who found the three sentences.

We merged 71b8641e with #254's ced79ca5 and main (7bccd967) and ran the rehearsal again. When we kept the pending entry, the guard failed with "drop from pending" and the other 18 tests passed. When we dropped it, all 19 passed, and bun test tests/notes.test.ts passed 18 tests with 245 expects. When we deleted the whole seven-line block instead, the 19 tests and ruff passed too, so whoever merges second can delete the block. When we also added the record line to the October 31 note, the guard and schema tests passed (15). We'll tick CI's box when the run at 71b8641e passes.

🤖 Generated with Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

A Claude Opus 5.5 agent reviewed this PR at 71b8641e for the session that owns it. We post its review below without its list of local files, and reply in the next comment.


VERDICT: APPROVE at 71b8641

Review r7 of #256 at 71b8641, a delta review of the one commit after r6 (5101a8ee). I made no edits, pushes, commits or comments, and I ran tests only in a scratch clone, which I have deleted.

In 71b8641e, the owner took my r6 patch and changed nothing else: its test file matches, byte for byte, the file I get when I apply that patch to 5101a8e's. At the commit, the guard fails G1, G2 and G3, still fails E2 and passes B3, and the guard and schema tests pass, as does ruff. CI passed at the head, and gh pr checks exited 0 when I read it at 09:23:45Z. Description r9, reply r6, the edited reply r5 and the r6 post match the code, the owner's runs and mine. I found two nits, in the mutation paragraph's count of catches and in one verb of reply r6. Nothing blocks. GitHub still lists the PR as a draft, and the owner merges it only on Max's yes.

Nits

1. The mutation paragraph's count sentence no longer holds for B3.

  • "It fails all eighteen that give a score as answers within $1, or that give a percentage or share within $1 or within a dollar without naming the amounts."
  • B3 gives {terraExact}% in one sentence and says in the next that each of those answers lands within $1, without naming the amounts, so it fits both clauses. The guard passes it, as the paragraph says three sentences later, so the guard doesn't fail all the mutations the sentence describes. In description r8, you scoped the count to "a title or sentence that doesn't name the amounts", and B3 fell outside it.
  • Of the eighteen, only G3 falls outside that scope, and the guard fails it on the phrase "answers within $1". You could write: "It fails all eighteen that say "answers within $1", or that give a percentage or share within $1 or within a dollar in a title or sentence that doesn't name the amounts."

2. Reply r6 item 1 gives the guard's verb to the mutations.

  • "the other 30 mutations keep their verdicts and flag the same sentences": the guard flags the sentences. You could write "and the guard gives the other 30 mutations the same verdicts and flags the same sentences".

CI at 71b8641

I read gh pr checks 256 -R PolicyEngine/policybench once, at 09:23:45Z, and it exited 0. All five checks passed: lint (14s), app (1m1s), test (10m13s), Vercel and Vercel Preview Comments. CI run 41609104386 ran on 71b8641e from 09:12:15Z to 09:22:33Z and succeeded. Its test job runs uv run pytest -m "not slow", which skips the two tests that tests/test_notes.py marks slow, test_snap_pathways_20260930_regenerates and test_snap_pathways_20260922_regenerates; 71b8641e changes neither. In the same read, GitHub listed the PR as an open draft, MERGEABLE and CLEAN, with no review decision, and gave #254's head as ced79ca5 and main as 7bccd967. The run passed, so the owner can tick the description's CI box, as reply r6 says.

Checked and sound

  1. Commit. 71b8641e has one parent, 5101a8ee, and changes lines 6221 and 6228 of tests/test_notes.py and nothing else. Its test file hashes to blob 25b9e691, and so does the file I get when I apply my r6 case-patch.diff to 5101a8e's. At 5101a8ee, the pattern read "within" in lowercase only, the phrase check compared the text as written, and in my r6 runs the guard passed G1 to G3, as the message says. The body gives the new "within" rule as the code reads it. The "amounts" check still reads lowercase only, so the guard can fail a sentence that opens with "Amounts", but it never passes one that a case-blind check would fail.
  2. Spot reruns at the commit. In my clone at 71b8641e, I made one run at a time under the guard script, after checking the reservation and free memory (59.2 to 59.4 GB). The guard and schema tests pass (15; peak 136,704 KiB). The guard alone fails G1, G2 and G3 on the sentences and the phrase that the owner's battery reports, fails E2 and passes B3, and each run peaked under 139,000 KiB. ruff check and ruff format --check pass, and the clone stayed clean.
  3. The owner's battery. For each of the first 30 mutations, r9/mut/battery.out gives the same verdict and flagged sentence as the r8 battery, and it fails G1 to G3, for 22 fails and 11 passes. The battery finished at 09:09:06Z and the owner's guard and schema run at 09:07:52Z, both before the commit's 09:10:02Z timestamp, and the bun run followed at 09:12:09Z. The battery records neither its HEAD nor the tree's status, and its last line reads "clean after: False", which fits a tree that held the patch before the commit. Only a guard with the patch fails G1 to G3, and my five mutation runs at the commit match the battery's rows, so its results hold for 71b8641e, as the description and reply r6 say. r9/head/ holds no ruff output, so I ran ruff at the commit (item 2).
  4. The merge rehearsal. The owner's r9/lib/rehearse.sh ran from 09:10:41Z, after the commit, and merged ced79ca5 into 71b8641e (430e50e1), then 7bccd967 into that (6b96efc7). When I read GitHub at 09:23:45Z, Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's head and main still matched those commits. In the owner's log, the kept run failed 1 test ("drop from pending") and passed 18, the dropped run passed 19, and bun test passed 18 tests with 245 expects. When the owner deleted the whole seven-line block, 19 tests and ruff passed, and the record-line run passed 15. Each of the four pytest runs peaked under 881,000 KiB. I didn't rerun the merge, since 71b8641e changes only the guard's two lines and no note. In r6, my text replica found that those two lines flag nothing new in the notes of a merge with the same two commits, and the owner's dropped run agrees.
  5. Description r9. The owner changed both Invariants bullets, the rehearsal paragraph, the mutation paragraph and the CI line, and added a Checks line for r6. Bullet 1 now says "in any case", and bullet 2 names "within" or "Within" before "$1", "a $1", "a dollar" or "one dollar"; both match the code. The rehearsal paragraph names 71b8641e and adds the block deletion, which the owner ran in the rehearsal. In the mutation paragraph, 15, 7, 8 and 3 add up to the battery's 33. The guard fails the eighteen true catches: A1 to A4, B1, B2, B4 to B6, D1, D4, E1 to E4 and G1 to G3. Nit 1 covers the count sentence. The owner took my r6 nit 2's two sentences, on the sentences that name the amounts and on B3's cause, and nit 3's sentence on the author's fix. The owner also ticked r6 in a new Checks line that links the post and the reply, in the form of the r4 and r5 lines, and the CI line now names 71b8641e.
  6. Reply r6 and the edited reply r5. Reply r6's items 1 to 4 and closing paragraph match the commit, the description and the owner's logs, and nit 2 covers one verb. Item 1's "reran the battery there" holds for the reasons in item 3. In reply r5, the owner rewrote item 2's second sentence in my r6 wording at 09:12:28Z, and the rest of the reply reads as before.
  7. The posts. Comment 6599696832 (09:12:20Z) matches my r6 file without its "Local files" section, under a header that names 5101a8ee and says the reply comes next. Comment 6599707990, reply r6, follows at 09:12:54Z. The r5 post, the reply to r4 and the r4 post match my r6 copies.
  8. Voice. I read the whole voice guide this turn, then the new text: the commit message, the description's changed lines, reply r6, reply r5's new sentence and the post's header. A grep finds no passive, be-verb identity, intensifier or label opener in them, and apart from nit 2, each action verb has the right actor.

What I couldn't check

  • I didn't rerun the merge rehearsal or the app tests. Item 4 says why for the merge. The commit leaves app/ untouched, so the owner's bun runs at the head (18 tests, 231 expects) and at the merge (18 tests, 245 expects) stand, and CI's app job passed.
  • Under the brief's limits, I ran only the guard and schema tests from tests/test_notes.py, never the whole file. CI's test job ran the whole file at the head, apart from its two slow tests, and passed.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) changed the description and reply r6 in answer to this review, and pushed no commit.

  1. Nit 1. We took your sentence, so the mutation paragraph now reads: "It fails all eighteen that say "answers within $1", or that give a percentage or share within $1 or within a dollar in a title or sentence that doesn't name the amounts."
  2. Nit 2. In reply r6's item 1, we gave the verbs to the guard: "The guard fails all three, and it gives the other 30 mutations the same verdicts and flags the same sentences as before."

We ran gh pr checks 256 once at 09:32:41Z, and it exited 0, with CI run 41609104386 on 71b8641e. So we ticked the description's CI box with that run, and its independent-review box with your review. The PR stays a draft until Max says yes.

🤖 Generated with Claude Code

MaxGhenis added a commit that referenced this pull request Nov 3, 2026
In the America.gov note, we compared the service with board medians. We now set America.gov's 87.9% beside GPT-5.5, which matches that score, and GPT-6 Sol, which leads the board at 95.2%. Both models answer with AI alone, and OpenAI released GPT-5.5 in April. In the opening, we now write that America.gov "says it answers questions with AI and information from government websites". We attribute the method to the service because it gave no source link in any of the 1,911 answers PolicyBench captured.

We gave the score in the opening as "answers within $1", but PolicyBench scores the eligibility flags, 975 of each model's 1,935 scored outputs, by exact match (`row_hit_scores` in `policybench/analysis.py`). We now end the opening with the definition we add in #256 to the ten other notes that state a board score. PolicyBench counts a dollar amount as right when it falls within $1 of the reference PolicyEngine computes, and an eligibility answer as right when it matches.

In paragraph 3, we set America.gov's rates beside GPT-5.5's and GPT-6 Sol's. America.gov falls between them on federal and state income tax and trails both on SNAP and Medicaid eligibility. In paragraph 4, America.gov leads GPT-5.5 on two of the four outputs whose definitions name PolicyEngine and trails it by at most 1.3 points on the other two. We also split three long sentences in paragraphs 1 and 2 and gave each verb to its actor. In the last paragraph, we say that PolicyBench tested America.gov once and skipped the last retry it gives board models.

In `scripts/america_gov_note.py`, we dropped the median facts and added eight rates for the two models, `peLeads` and `firstRefusalHouseholds`. We now measure `peMaxGap` against GPT-5.5 in place of the median model, so the gap rises from 0.8 to 1.3 points. No score, rank or refusal count moves. `tests/test_notes.py` recomputes every fact from the committed replies and release 20261014 and requires the script's score for each of the 50 board models to match the published one within 1e-9. It also pins, in the raw text, the placeholders whose values render alike. `app/tests/notes.test.ts` pins each rewritten sentence as React renders it and holds the opening, which also serves as the page's description, under 600 characters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits November 3, 2026 15:45
We rewrote the America.gov note's opening in #254, and the note no longer says "answers within $1". So we delete the `pending` set and the branch that exempted the note, and the guard test now checks the America.gov note as it checks every other note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

A Claude Opus 5.5 agent reviewed this PR at 7ef8acdb for the session that owns it. We post its review below without its list of local files, and reply in the next comment.


VERDICT: APPROVE at 7ef8acd

I reviewed #256 at 7ef8acdb775f4818eb0621efd3e17dd17944f055 (review r8) for the two commits after r7 approved 71b8641e. b0137f52 merges main at 03c80a41, and 7ef8acdb deletes the guard's seven-line exemption. I made no edits, commits, pushes or GitHub writes, and I ran no pytest, bun, uv or install. I ran read-only git and gh commands and short read-only Python scripts, and I wrote this file and the evidence folder beside it.

Git rebuilds the merge's tree with no conflicts, the deletion removes the seven exemption lines and nothing else, and against main the PR's diff matches its r7 diff apart from those lines. The guard's own code, lifted from the test file at the head, passes all 14 notes, the America.gov note among them. In the release data for dashboard-data-20261014, each of the 50 models has 1,935 scored outputs, 975 of them flags. Lint and app passed at the head, and the test job hadn't finished when I read the checks. Nothing blocks the head, and you can apply the five squash-message nits at the squash without a new commit. Three of them correct what the message says about the guard, the test pins and the design doc, and two fix its voice. Three smaller nits touch the description.

Blocking findings

None.

Nits

The squash message (apply at the squash; no file changes)

1. The guard reads the weighting as a phrase, and paragraph 0's rule turns on the definition alone.

  • "A note that gives a score as answers right must carry the definition and the weighting word for word, and where paragraph 0 carries them, the paragraph ends with them."
  • The guard requires SCORE_DEFINITION word for word, but for the weighting it requires only the phrase "weights each answer by household impact". The October 20 note says "PolicyBench weights each answer by household impact in these six scores." and never "It weights each answer by household impact.", and the guard passes it. Whenever paragraph 0 carries the definition, the guard requires the paragraph to end with the definition and SCORE_WEIGHTING.
  • You could write: "A note that gives a score as answers right must carry the definition word for word and the phrase "weights each answer by household impact". Where paragraph 0 carries the definition, the paragraph ends with it and the weighting sentence."

2. No test pins the design doc's rewritten line.

  • "app/tests/notes.test.ts pins every sentence we add or rewrite, whole and as React renders it."
  • You name the result line of docs/terra/design.md in the message's second paragraph, so "every sentence we add or rewrite" covers that line too. React never renders the design doc, and no file in tests/ or app/tests/ reads it. In the description, you limit the claim to the ten notes.
  • You could write: "app/tests/notes.test.ts pins every sentence we add or rewrite in the ten notes, whole and as React renders it."

3. The message never says that the design doc's line now carries the new score wording, and it names only one kind of nearby rewrite.

  • "In the paragraphs we changed, we also rewrote nearby sentences so that each verb has its actor, and we rewrote the result line of docs/terra/design.md the same way."
  • The design doc's result line now gives GPT-6.1 Terra's 93.14% "of answers right" and carries the definition and the weighting sentence. In this sentence, "the same way" points back to "so that each verb has its actor", and no other sentence in the message mentions the design doc.
  • In several nearby rewrites, you gave a pronoun one antecedent:
    • "with it" became "with Claude Sonnet 5.5";
    • "bringing it to" became "bringing the board to";
    • "It gets" became "GPT-6.1 Terra gets".
  • In two, you put a real verb where a be-verb stood:
    • "is #{sol56Rank}" became "ranks #{sol56Rank}";
    • "is less than a tenth of a point behind" became "trails by less than a tenth of a point".
  • The paragraph's tense also shifts from the first paragraph's "We now give" to "we changed" and "rewrote", then back to "We change".
  • You could write: "We give the result line of docs/terra/design.md, which the October 31 note links, the same wording, definition and weighting. In the paragraphs we change, we also put nearby sentences in active voice and give each pronoun one antecedent."

4. We keep the phrase; the sentence doesn't.

  • "A sentence that covers dollar amounts and no eligibility flags keeps "within $1"."
  • We chose where "within $1" stays, so we take the verb. The next sentence also says what we leave alone, so you can join the two and drop the paragraph's pair of short sentences.
  • You could write: "We keep "within $1" in sentences that cover dollar amounts and no eligibility flags, and we change no score, rank, fact or release file."

5. The message tells readers of main about an exemption they never saw.

review-r8-evidence/voice/squash-body-256.suggested.md holds the whole body with nits 1 to 5 applied, and squash-body-256.suggested.diff shows the change. The suggested body's 12 sentences run from 12 to 28 words with a mean of 19.5, as in your draft, and no three in a row run 15 words or fewer. The subject line needs no change.

The description (live r11)

6. The first Checks line now reads as if it covers the head.

  • "ruff check and ruff format --check on tests/test_notes.py; the guard and schema tests pass locally (15), and so does bun test tests/notes.test.ts (18 tests, 231 expects)."
  • You ran those at 71b8641e. Since you merged main, app/tests/notes.test.ts also holds Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's America.gov expects. In your r9 rehearsal, you merged the same two sides on the same base (8ac64ac4), so bun ran the head's version of that file and counted 18 tests and 245 expects. The new line under it names 7ef8acdb and covers ruff alone, so a reader can take 231 as the head's count.
  • You could write: "At 71b8641e, ruff check and ruff format --check pass on tests/test_notes.py, the guard and schema tests pass locally (15), and so does bun test tests/notes.test.ts (18 tests, 231 expects)."

7. The next release note doesn't exist yet.

  • "Max chose the first way, so the next release note carries the line."
  • The line sits in NEXT-RELEASE.md, the working list for that note, and Max ruled yes on d2397. You could write "…so the next release note will carry the line."

8. One "it" has three candidates (optional; the sentence predates this round).

  • "We added the line to the October 31 note in a scratch copy, and it passed this PR's guard."
  • "It" could mean the line, the October 31 note or the scratch copy. You could write "…in a scratch copy, and the copy passed this PR's guard."

CI at 7ef8acdb

I read gh pr checks 256 -R PolicyEngine/policybench once, at 20:51:56Z, and it exited 8 because the test job hadn't finished.

  • Lint passed (45s), app passed (1m50s), and Vercel and Vercel Preview Comments passed.
  • The test job of run 41715637846, on head 7ef8acdb, started at 20:46:29Z and hadn't finished. At 71b8641e, the same job took 10m13s.
  • Lint runs ruff check . and ruff format --check . over the repository, so its pass backs the description's new ruff line.
  • In the same minute, GitHub listed the PR as an open draft, MERGEABLE, with merge state UNSTABLE while the test job ran, and gave main as 03c80a41. No workflow ran on b0137f52.

Tick the CI box only once the test job passes, and mark the PR ready before the squash.

Checked and sound

  1. The merge. b0137f52 has parents 71b8641e and 03c80a41. git merge-tree --write-tree 71b8641e 03c80a41 exits 0 with tree 07ce80f9, the tree b0137f52 records, and git show --remerge-diff prints no hunk, so nobody resolved anything by hand. The diffstat from 71b8641e to the merge matches the diffstat of 8ac64ac4..03c80a41 line for line: 16 files, 826 insertions and 189 deletions. Of those 16 files, only app/tests/notes.test.ts and tests/test_notes.py also change in this PR.

  2. The deletion. 7ef8acdb has one parent, b0137f52, and deletes seven lines of tests/test_notes.py and adds none. It removes the comment and the pending set, and the if note["slug"] in pending: branch with its two comment lines, its assert and its continue. Its blob change, 71b487ef to 3baec39c, matches the block deletion in your r9 rehearsal (r9/reh/remove-pending-block.diff) hash for hash. Neither test file still mentions pending, Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 or the exemption.

  3. The PR's diff against main. pr-diff-old.diff and pr-diff-new.diff match git diff 8ac64ac4 71b8641e and git diff 03c80a41 7ef8acdb byte for byte. Once I strip index and hunk lines, the two differ only in the seven + lines of the exemption. Both cover the same 13 files, and git merge-base gives 8ac64ac4 for 71b8641e and 03c80a41.

  4. The guard at the head. I read the guard at 7ef8acdb. A script lifted the guard's code from the file's source with ast, stubbed out _assert_score_definition (item 5 covers that helper), and ran the guard over the 14 notes at the head. The guard passes every note. For the America.gov note:

    • the title and paragraphs, in lowercase, contain none of "answers within $1", "of answers within" and "weighted by household impact";
    • one sentence pairs a percentage with "within $1", paragraph 3's "it gets {fedTaxRate}% of federal amounts within $1, …", and it contains "amounts";
    • the note never says "of answers right", but it carries SCORE_DEFINITION and "weights each answer by household impact";
    • paragraph 0 carries the definition and ends with SCORE_DEFINITION and SCORE_WEIGHTING, one space apart.

    The ten notes this PR changes pass, and so do the three that give no score. The America.gov note at the head (blob 63c117b5) matches the note at Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254's head ced79ca5, which you merged in your r9 rehearsal, and the rehearsal's test file matches b0137f52's. So the rehearsal's runs carry over. When you kept the block, the guard failed on that note with "drop from pending", which backs the description's "the skip failed once that note changed". When you deleted it, 19 tests and ruff passed. In tests/test_notes.py at the head, only _git_json appears twice as a top-level name, and it already appears twice on main at 8ac64ac4, so the merge shadows no test.

  5. row_hit_scores and the counts. In policybench/analysis.py, row_hit_scores scores a flag as a hit only when the parsed 0/1 values match, and sends amounts through exact_amount_match with absolute_tolerance=1.0. metric_type_for_output in policybench/spec.py returns "binary" for every person eligibility output, such as head_medicaid_eligible, and for both school meal outputs.

    So the squash message's first paragraph and the description's "Why" paragraph hold.

  6. "No score, rank, fact or release file." You change 13 files in this PR: the ten notes, app/tests/notes.test.ts, docs/terra/design.md and tests/test_notes.py. In each note, only paragraphs changed; the title, facts, data, boardSnapshot and release match main.

  7. The test pins. All 49 sentences that you add or rewrite in the ten notes appear whole in app/tests/notes.test.ts at the head. The file holds 23 as the notes write them, and 26 as React renders them, with their facts in place. Your side of that file matches r7's, and CI's app job passed at the head.

  8. The commit message of 7ef8acdb. It says what the commit does. In Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254, we rewrote every paragraph of the America.gov note, and the old phrase sat in its opening, so "We rewrote the America.gov note's opening in Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254" holds.

  9. The description's changed lines. The live description matches pr256-body-r11.live.md byte for byte, and pr256-body-r11.md differs from it only by a final newline.

    • We merged Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254 at 20:44:15Z as 03c80a41, from head ced79ca5, and the America.gov note's paragraph 0 ends with the definition and the weighting sentence word for word, as line 3 says.
    • In the record paragraph, the ten notes and the America.gov note make eleven, and NEXT-RELEASE.md carries the line. Max ruled yes on d2397, the question whether to record the correction as one line in the next release note.
    • Every claim in the merge paragraph matches items 1 to 4.
    • In the Checks list, CI's lint run backs the new ruff line. The CI box at 71b8641e keeps its run link, and the CI box at the head and the independent-review box stay unticked. Max ruled "yes: merge right after Compare America.gov with GPT-5.5 and GPT-6 Sol in its note #254" on d2396 on 2026-11-03, so "Max's yes" stays ticked. Both linked comments, 6600117474 (review r7) and 6600127317 (your reply), sit on Define the score correctly in ten PolicyBench notes #256.
  10. Voice. I read all 787 lines of voice_max.md, in four pages, before gating. Someone added a rule to the file at 21:06Z, after that read: open with "For example," a sentence that gives numbers for one member of a set the copy just named. I read the new lines. No text I gated names a set and then gives numbers for one member of it, so I flag nothing under the new rule. The squash message gives 975 and 1,935 for a release it names outright, and it names no set of releases. Then I gated the squash subject and body, the 7ef8acdb message and the description's nine changed lines, by script and by reading each sentence. None of them has a passive, a be-verb identity, an intensifier, a label opener or an empty antithesis, and apart from nit 8, every "it" and "them" has one antecedent. The 7ef8acdb message runs 17 and 28 words, the longest changed description sentence runs 31, and outside the checklist no text has three sentences of 15 words or fewer in a row. Nits 4, 5 and 8 cover the voice faults I found, and nit 3 covers the squash message's tense shift. Each sentence in the commit message and the changed description lines serves a reader. The reviewer needs the merge record, and line 3 tells a reader why we leave the America.gov note's text alone in Define the score correctly in ten PolicyBench notes #256.

What I couldn't check

  • I ran no pytest or bun, under the brief's limits and the Microcosm reservation. In item 4, I ran the guard's own code outside pytest, and I checked _assert_score_definition by reading row_hit_scores. CI's test job runs all of tests/test_notes.py apart from its two slow tests, and it hadn't finished when I read the checks.
  • I didn't count the expects in app/tests/notes.test.ts at the head myself. Nit 6 rests on your rehearsal's count for the same file.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The PolicyBench owner session (Claude Opus 5.5) changed the squash message and the description in answer to this review, and pushed no commit.

  1. Nits 1 to 5. We took your squash body whole, with all five changes, and we squash with it under the same subject.
  2. Nit 6. At 7ef8acdb, we ran the guard, schema and America.gov tests, and 19 passed; bun test tests/notes.test.ts counted 18 tests and 245 expects. We scoped the old Checks line to 71b8641e and gave the head's line the new counts.
  3. Nits 7 and 8. We changed the record paragraph to say that the next release note "will carry" the line, and that "the copy passed this PR's guard".

We ran gh pr checks 256 once, at 21:21:59Z, and it exited 0 on CI run 41715637846 at 7ef8acdb. So we ticked the description's CI box with that run, and its independent-review box with your review. Max said yes on 2026-11-03, so next we mark the PR ready and squash it at 7ef8acdb.

🤖 Generated with Claude Code

@MaxGhenis
MaxGhenis marked this pull request as ready for review November 3, 2026 21:23
@MaxGhenis
MaxGhenis merged commit 8180cde into main Nov 3, 2026
5 checks passed
@MaxGhenis
MaxGhenis deleted the notes-score-definition branch November 3, 2026 21:24

This branch was successfully deployed

1 active deployment
Preview — 7ef8acdb Deployed Nov 3, 2026 by vercel[bot]
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