PR walkthrough: the heteronym fix

2 months ago

Every word I am speaking runs through code that changed last night, in one pull request. I am going to walk you through it. And the walkthrough is also the demo, because this fix is the reason I can say the word present correctly. Three minutes.

Ask

Ask about this presentation

Answers are generated from this presentation.

Chapters

  1. 0:00You are listeningto a pull request.
  2. 0:16Seven hundred ninetywords say it wrong.
  3. 0:42Read one wordof context.
  4. 1:14Exact key first.
  5. 1:47Measured, notvibe checked.
  6. 2:03The agent thatwrote it presents it.
  7. 2:27Ask the agentthat wrote it.
Show transcript

You are listeningto a pull request.

Workflow guides · 02

The walkthrough is the demo: this voice runs the code the PR changed.

01

Every word I am speaking runs through code that changed last night, in one pull request. I am going to walk you through it. And the walkthrough is also the demo, because this fix is the reason I can say the word present correctly. Three minutes.

Seven hundred ninetywords say it wrong.

The bug
WHAT THE ENGINE SAYS NOW, PHONEME BY PHONEME
IˈI
willwɪl
presentpɹizˈɛnt
theðə
recordɹˈɛkəɹd
livelˈIv

The lexicon has both readings for 790 words, keyed by part of speech. The tagger abstained on every ambiguous word, so every one fell back to its default reading.

02

English is full of words spelled one way and spoken two ways. Listen. I will present the record live. Present the verb, record the noun, live the adverb, each chosen from the sentence around it. The engine's lexicon always knew both readings for seven hundred ninety of these words. But the tagger abstained on every ambiguous one, so each fell back to its default. The engine could name a record. It could not present one.

Read one wordof context.

Change one of three

A modal makes a verb. A determiner makes a noun. A sentence opener with an object makes an imperative.

Gated: the rules touch only words whose pronunciation depends on the tag.

let chosen = if p.is_some_and(|p| {
    VERB_TRIGGERS.contains(&p)      // "will present"
        || p.ends_with("'ll")
        || p.ends_with("'d")
}) {
    Some(Tag::Verb)
} else if p.is_some_and(|p| {
    NOUN_DETERMINERS.contains(&p)   // "the record"
        || NOUN_PREPOSITIONS.contains(&p)
}) && next_is_head_boundary
{
    Some(Tag::Noun)
} else if p.is_none()
    && next.as_deref()
        .is_some_and(|n| IMPERATIVE_OBJECTS.contains(&n))
{
    Some(Tag::Verb)                 // "Record the meeting"
} else {
    None                            // keep the default reading
};
03

The pull request makes three changes, and the first is a set of context rules. The tagger now reads one word of left context. A modal before the word makes it a verb, so will present presents. A determiner before it, with nothing after, makes it a noun, so the record stays a record. And a sentence that opens with the word, followed by an object, reads as an imperative. Everything else keeps its default, the rules fire only on words whose pronunciation depends on the tag, so an ordinary word cannot be touched.

Exact key first.

Changes two and three
RESTORE A LOOKUP ORDER

Past tenses live under fine grained keys. The reference implementation tries the exact key before the parent bucket; this port had lost that order. Restoring it reaches the past readings of read, wound, and used.

DELETE A RULE

The suffix guess
is gone.

Ninety one of the words end in ate, like appropriate and separate. An old rule guessed verb from that ending, but the usual reading is the adjective or the noun, so the guess chose the rarer one in every sentence.

04

The second change is smaller. Past tense readings live under fine grained keys, and the reference implementation always tried the exact key before the parent bucket. This port had lost that order. Restoring it is what makes the past tense of read come out right. The third change is a deletion. Ninety one of these words end in ate, like appropriate and separate. An old rule guessed verb from that ending, but for most of them the usual reading is the adjective or the noun. The rule picked the rarer reading in every sentence, so the best fix was removing code.

Measured, notvibe checked.

The measurement

A labelled corpus: 62 sentences where the right reading is not the default.

05

None of this counts without a measurement. The pull request ships a labelled corpus, sixty two sentences where the right reading is not the default. The engine before the change got twenty of them. The engine you are hearing right now gets all sixty two.

The agent thatwrote it presents it.

The workflow

The whole diff was already in its context. The walkthrough cost one sentence, typed after the commit.

FILES CHANGED

4

LINES ADDED

688

WATCH TIME

3 min

THE SENTENCE THAT MADE THIS
Present this pull request as a walkthrough for reviewers.

Send the link with the review request. Reviewers arrive at the diff already knowing the shape of the change.

06

Here is the part you can copy. The agent that wrote this fix had the whole diff in its context, so the walkthrough cost one sentence, typed after the commit. Present this pull request as a walkthrough for reviewers. Four files and six hundred eighty eight added lines became the three minutes you just watched. Send the link with the review request, and reviewers arrive at the diff already knowing the shape of the change.

Ask the agentthat wrote it.

Workflow guides · 02

It was in the room. And now, so were you: I will present the record live.

bisque.cloud

07

The next time a pull request needs more than a diff, ask the agent that wrote it to present it. It was in the room. And one more time, because the fix you just toured is the reason it sounds right. I will present the record live.