Skip to content

Stop the grounding gate rejecting drafts for saying "I'd" - #41

Merged
ralyodio merged 1 commit into
mainfrom
worktree-draft-contraction-false-positives
Aug 17, 2026
Merged

ralyodio merged 1 commit into
mainfrom
worktree-draft-contraction-false-positives

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What was broken

Asking for a draft on https://outreachgraph.com/approvals?channel=email&filter=needs_draft returned:

No draft: the wording kept asserting things nothing supports — I'd.

The draft was fine. extractClaims in packages/ai/src/checks.ts was wrong, in three ways that all trace back to reading an apostrophe as punctuation it is not.

  1. A first-person contraction was read as a proper noun. The extractor treats a capitalised mid-sentence word as a name that must appear in stored evidence. I'd is capitalised mid-sentence, and nothing can ever support it — normalize turns the apostrophe into a space, so the claim becomes the token i d. Every draft written in the first person failed, retried (told to "remove these entirely: I'd", which it cannot sensibly do), failed again, and was withheld as failed_checks.
  2. Correctly grounded names were rejected. Stripe's normalised to stripe s, which does not match stored evidence reading Stripe. Citing the prospect's own words counted as inventing them.
  3. Apostrophes acted as quote delimiters. The quoted-phrase regex listed the straight ' as a quote mark, so two contractions bracketed the prose between them into a quotation: I've seen this. Curious what you'd try yielded the claim ve seen this. Curious what you.

Reproduced against the real checker before changing anything — case 1 returns exactly ["I'd"], which is the string the approvals card renders.

The fix

  • Strip contraction and possessive endings ('s 'd 'm 't 'll 've 're, straight and curly) before a capitalised word is read as a name. I'd reduces to I and falls under the length floor; Stripe's reduces to Stripe and matches the evidence.
  • Delimit quotations with double quotes only (straight and curly). Single quotes stay out — they are indistinguishable from the apostrophe in I'd.

The gate still does its job

Verified an invented product name, an invented figure, and a genuine double-quoted phrase are all still flagged, including inside first-person prose. Tests cover each.

bun run check is green: format, typecheck, 874 tests across 55 files, 0 failures.

🤖 Generated with Claude Code

The approvals queue answered every request to write an email with "No
draft: the wording kept asserting things nothing supports — I'd". The
draft was fine. The checker was wrong, in three ways that all trace back
to reading an apostrophe as punctuation it is not.

`extractClaims` treats a capitalised mid-sentence word as a name worth
grounding. "I'd" is capitalised mid-sentence, so it was extracted as one,
and nothing could ever support it: `normalize` turns the apostrophe into
a space, so the claim became the token "i d", which appears in no
evidence. Any draft written in the first person failed, retried, failed
again, and was withheld — the composer's second attempt is told to
"remove these entirely: I'd", which it cannot sensibly do.

The same code rejected correctly grounded names. "Stripe's" normalised to
"stripe s" and did not match stored evidence reading "Stripe", so citing
the prospect's own words counted as inventing them.

And the quoted-phrase extractor listed the straight apostrophe as a quote
delimiter, so two contractions bracketed the prose between them into a
quotation: "I've seen this. Curious what you'd try" yielded the claim
"ve seen this. Curious what you".

So: strip contraction and possessive endings before a capitalised word is
read as a name, and delimit quotations with double quotes only. Single
quotes stay out — they are indistinguishable from the apostrophe in "I'd".

The gate still does its job. An invented product name, an invented figure
and a real quoted phrase are all still caught, including inside
first-person prose; there are tests for each.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 2f2a246 into main Aug 17, 2026
4 checks passed
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.

1 participant