Skip to content

fix(core): replace the reexecute dictionary entry with re-execute - #4042

Open
mauropereiira wants to merge 3 commits into
Automattic:masterfrom
mauropereiira:fix/disjoint-prefixes-re-e
Open

fix(core): replace the reexecute dictionary entry with re-execute#4042
mauropereiira wants to merge 3 commits into
Automattic:masterfrom
mauropereiira:fix/disjoint-prefixes-re-e

Conversation

@mauropereiira

@mauropereiira mauropereiira commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Issues

Fixes #3954

Description

Reworked after review. The original version of this PR special-cased DisjointPrefixes; that was patching the symptom, and it silenced far more than it should have. This is now a dictionary change.

reexecute was an explicit entry in dictionary.dict, not an affix-derived form:

reexecute/VSdG

That single entry caused both halves of the bug. Harper accepted reexecute as a correct spelling, and DisjointPrefixes offered it as the replacement for re-execute.

The reporter linked the OED entry for re-execute, and no professional dictionary lists the closed spelling, so the hyphenated form is the one that belongs in the dictionary:

-reexecute/VSdG
+re-execute/VdSG

Flags follow the neighbouring re-enable/VdSG, which gives re-executed, re-executes and re-executing. The entry is placed with the other re- hyphenated entries, after re-enslavement.

Both halves of DisjointPrefixes now decline independently. contains_word_str("re-execute") is true, so it returns early on the original form; and even past that point, joined_valid is false because reexecute is gone.

The linter special case is fully reverted. re-elect, re-examine, re-enter, re-evaluate and re-establish keep their current behaviour, which is what the review asked for, since those joined spellings are attested.

Demo

Please re-execute the migration script.   clean
I re-executed the script.                 clean
It re-executes cleanly.                   clean
We are re-executing it.                   clean

Please reexecute the script.              SpellCheck
I reexecuted the script.                  SpellCheck

We must re-elect the mayor.               DisjointPrefixes   (unchanged)
Please re-run the script.                 DisjointPrefixes   (unchanged)
We need to re-open the file.              DisjointPrefixes   (unchanged)
I will reexamine the data.                clean              (unchanged)

How Has This Been Tested?

cargo test -p harper-core

test result: ok. 6125 passed; 0 failed; 290 ignored; 0 measured; 0 filtered out

harper-cli audit-dictionary harper-core reports nothing, cargo fmt is clean, and no files under harper-core/tests/text/ change.

AI Disclosure

  • I used an AI agent interactively.

If Your PR Implements or Enhances a Linter

  • I'm using examples from the bug report / feature request.

The single test uses the reporter's own wording from the issue. The demo sentences above are mine, used to check the surrounding class rather than as test cases.

Checklist

  • I have performed a self-review of my own code
  • I have added tests to cover my changes
  • I have considered splitting this into smaller pull requests.

`DisjointPrefixes` fires when the joined spelling is in the dictionary but the
written form is not. Harper's affix system generates "reexecute" from
`re` + `execute`, while the hyphenated "re-execute" is not derivable that way,
so the linter told users to replace a correct spelling with a form that Collins
and the OED do not list.

Suppresses the suggestion when the prefix is "re", the separator is a hyphen,
and the stem begins with "e". This only ever removes a suggestion, never adds
one. Space-separated input, other prefixes, and non-e stems such as "re-run"
and "re-open" are unchanged.

Fixes Automattic#3954

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@hippietrail

hippietrail commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

I think an ideal fix would check all the online dictionaries for each affected word.
Personally, if any professional dictionary (so not Wiktionary, Urban Dictionary, etc.) includes a word or spelling we probably should (except when obsolete, archaic, dialectal, or otherwise too marginal).

If our dictionary generates any without hyphen that none of the pro dictionaries include, then we should stop our dictionary from generating it.

We could introduce dictionary annotation flags for this but I think the number of affected words is small enough to handle one-by-one or as a special case in affected linters.

(If you want to pursue this you might find my tool "dicting around" in my GitHub handy for looking up all the online professional dictionaries.)

@mauropereiira

Copy link
Copy Markdown
Contributor Author

That makes a lot of sense. I revisited the change I'd made and turns out I was patching the symptom.

reexecute isn't affix-generated at all. It's an explicit entry we added ourselves, sitting right next to reelect:

reelect/VdSG
reexecute/VSdG

The others genuinely are generated, from the r flag on their base words: enter/~VGdSNr, establish/~VSdGrEL, evaluate/~VGdSrnvX, examine/~VGdSNr.

So I ran a test and removed just that one line, with no linter change at all:

- reexecute/VSdG
Please re-execute the script.   ->  clean            (the reported issue, fixed)
Please reexecute the script.    ->  SpellCheck       (correct, it isn't a word)
We must re-elect the mayor.     ->  DisjointPrefixes (unchanged, reelect is attested)
I will reexamine the data.      ->  clean            (unchanged)
Please re-run the script.       ->  DisjointPrefixes (unchanged)

cargo test -p harper-core passes, no snapshot changes.

That lines up with what you said about stopping the dictionary generating what the pro dictionaries don't have. DisjointPrefixes already returns None when neither form is in the dictionary, so the false positive goes away by itself.

It also fixes something my patch never touched. Right now Harper accepts reexecute as correctly spelled, so it isn't only recommending a word that doesn't exist, it believes in it.

Which makes my current patch too broad. It silences re-elect, re-examine, re-enter, re-evaluate and re-establish as well, and if those closed spellings are attested then Harper should carry on offering them.

Happy to swap this PR over to the one-line deletion if you think that's the better shape. And if there are other entries like this one, I can go through them with dicting-around in the same pass.

@hippietrail

Copy link
Copy Markdown
Collaborator

That makes a lot of sense. I revisited the change I'd made and turns out I was patching the symptom.

reexecute isn't affix-generated at all. It's an explicit entry we added ourselves, sitting right next to reelect:

reelect/VdSG
reexecute/VSdG

The others genuinely are generated, from the r flag on their base words: enter/~VGdSNr, establish/~VSdGrEL, evaluate/~VGdSrnvX, examine/~VGdSNr.

So I ran a test and removed just that one line, with no linter change at all:

- reexecute/VSdG
Please re-execute the script.   ->  clean            (the reported issue, fixed)
Please reexecute the script.    ->  SpellCheck       (correct, it isn't a word)
We must re-elect the mayor.     ->  DisjointPrefixes (unchanged, reelect is attested)
I will reexamine the data.      ->  clean            (unchanged)
Please re-run the script.       ->  DisjointPrefixes (unchanged)

cargo test -p harper-core passes, no snapshot changes.

That lines up with what you said about stopping the dictionary generating what the pro dictionaries don't have. DisjointPrefixes already returns None when neither form is in the dictionary, so the false positive goes away by itself.

It also fixes something my patch never touched. Right now Harper accepts reexecute as correctly spelled, so it isn't only recommending a word that doesn't exist, it believes in it.

Which makes my current patch too broad. It silences re-elect, re-examine, re-enter, re-evaluate and re-establish as well, and if those closed spellings are attested then Harper should carry on offering them.

Happy to swap this PR over to the one-line deletion if you think that's the better shape. And if there are other entries like this one, I can go through them with dicting-around in the same pass.

Yes I think that's the right approach. At some point there has been an import from Wiktionary, I'm not sure if it was from Wiktionary into Hunspell before Harper started using Hunspell, or if Harper brought in data from both Hunspell and Wiktionary before I found Harper.

Note that Harper's dictionary now supports hyphenated entries, but they are limited. The spellchecker can suggest them and individual linters can look them up, but the spellchecker only works one token at a time and hyphens are separate tokens because they're ambiguous. So I would remove the current reexecute entry and add re-execute if it's not already there. Double-check all the annotation flags while doing so. There is a pending PR for the spellchecker to work with two words separated by space of hyphen but it's still never been reviewed.

Also feel free to file bug reports or PRs against "dicting around" if you use it. The sites change their "URL magic" from time to time as well as their measures against CORS and scraping getting stronger.

Revert the `DisjointPrefixes` special case. It suppressed the suggestion for
every e-initial stem after `re`, which also silenced `re-elect`, `re-examine`,
`re-enter`, `re-evaluate` and `re-establish`, whose joined spellings are
attested.

The actual cause is a dictionary entry. `reexecute` was an explicit entry
rather than an affix-derived form, so Harper both accepted it as a spelling
and offered it as the fix for `re-execute`. The OED lists `re-execute` as a
verb and no professional dictionary lists `reexecute`, so the hyphenated form
is the one that belongs here.

Flags follow the neighbouring `re-enable/VdSG`, giving `re-executed`,
`re-executes` and `re-executing`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9k6gnF8CUtKAPo1LoLZyZ
@mauropereiira mauropereiira changed the title fix(core): keep the hyphen in "re-execute" and other e-initial stems fix(core): replace the reexecute dictionary entry with re-execute Aug 16, 2026
@mauropereiira

Copy link
Copy Markdown
Contributor Author

Swapped over. The linter special case is fully reverted and this is now a dictionary change:

-reexecute/VSdG
+re-execute/VdSG

On the flags, I followed re-enable/VdSG, which sits three lines up and is the closest existing model. That gives re-executed, re-executes and re-executing. The old entry was VSdG, the same four flags in a different order, so nothing is lost. I put the new entry after re-enslavement, where the other re- hyphenated entries live.

On attestation, the reporter had already linked the OED entry for re-execute in the issue, and I could not find the closed spelling in any professional dictionary. So this looks like exactly the case you described, where our dictionary carries something the pro dictionaries do not.

Worth noting that both halves of DisjointPrefixes now decline on their own. contains_word_str("re-execute") is true, so it returns early on the original form, and even past that point joined_valid is false now that reexecute is gone. So the hyphenated entry is doing real work here despite the tokenisation limits you mentioned, at least for this linter.

Behaviour:

Please re-execute the migration script.   clean
I re-executed the script.                 clean
It re-executes cleanly.                   clean
We are re-executing it.                   clean

Please reexecute the script.              SpellCheck
I reexecuted the script.                  SpellCheck

We must re-elect the mayor.               DisjointPrefixes   (unchanged)
Please re-run the script.                 DisjointPrefixes   (unchanged)
We need to re-open the file.              DisjointPrefixes   (unchanged)
I will reexamine the data.                clean              (unchanged)

cargo test -p harper-core passes with 0 failures, audit-dictionary reports nothing, and no snapshots change. I kept one regression test in disjoint_prefixes.rs so nobody re-adds the entry later.

I have not gone hunting for other entries of this kind yet. Happy to do a pass with dicting-around as a separate PR rather than growing this one, if that is useful. And thanks for the pointer to the tool.

@hippietrail hippietrail left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks ready to merge IMHO. Thanks!

@mauropereiira
mauropereiira added this pull request to the merge queue Aug 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 16, 2026
@elijah-potter
elijah-potter added this pull request to the merge queue Aug 19, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 19, 2026
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.

False positive: "re-execute" triggers DisjointPrefixes

2 participants