Skip to content

fix: strip dangling conjunctions from extract_duration remainder#293

Draft
JarbasAl wants to merge 1 commit into
devfrom
fix/duration-remainder-conjunctions
Draft

fix: strip dangling conjunctions from extract_duration remainder#293
JarbasAl wants to merge 1 commit into
devfrom
fix/duration-remainder-conjunctions

Conversation

@JarbasAl

Copy link
Copy Markdown
Member

What was broken

extract_duration_generic (the shared engine backing extract_duration for
most languages) consumed each matched <number> <unit> chunk by replacing it
with an empty string. When two chunks in the same sentence were joined by a
conjunction or comma, that connector was left stranded in the remainder text.

>>> extract_duration("It will take about 2 hours and 30 minutes", "en")
(timedelta(seconds=9000), "It will take about and")
>>> extract_duration("2 horas, 30 minutos, y 10 segundos", "es")
(timedelta(seconds=9010), "y")

How it fails

The remainder text is meant to be the sentence with the duration wording
removed, for use by callers (e.g. skills) that want to do something with
"the rest" of the utterance. A dangling "and"/"y" (optionally with commas)
is ungrammatical and can trip up anything downstream that expects clean
leftover text.

The fix

extract_duration_generic now replaces consumed matches with an internal
private-use sentinel character instead of "". Once every unit has been
consumed, a connector (with optional surrounding commas) that is sandwiched
between two sentinels — i.e. it only ever joined two consumed chunks — is
collapsed away along with them. A connector that still touches real,
unconsumed text on either side is left alone, so "two hours and rest and
relax" still returns remainder "and rest and relax".

This is opt-in per language via a new DurationLexicon.connectors field
(a tuple of regex fragments for the language's conjunction word(s)), so it
only changes behavior where explicitly wired up. It's wired up for English
("and") and Spanish ("y"), where the bug was confirmed. Other languages
(e.g. German "und", French "et") keep their existing, already-tested
remainder behavior — those tests intentionally leave the connector in the
remainder and are unaffected.

Verification

Following this repo's NL-TDD convention, failing tests were written first
to reproduce the bug (test/parse_tests/test_parse_en.py and
test/parse_tests/test_parse_es.py), then the fix was applied and the
tests turned green.

Ran the full suite before and after the change (PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest test/): the same 14 pre-existing failures are present on dev
before this change (unrelated test_dates_an* and test_packaging
failures) — zero new failures, zero regressions.


Authored with AI assistance (Claude).

The generic duration engine consumed <number> <unit> chunks by
replacing them with empty string, leaving connective tokens ("and",
",") that only joined two consumed chunks stranded in the remainder,
e.g. extract_duration("It will take about 2 hours and 30 minutes",
"en") returned "It will take about and" instead of "It will take
about".

Matches are now replaced with an internal sentinel so, once every
unit is consumed, a connector (with optional surrounding commas)
sandwiched between two sentinels can be told apart from one still
joining unconsumed text and collapsed away. A connector touching real
content on either side is left untouched. Opt-in per language via a
new DurationLexicon.connectors field, wired up for English ("and")
and Spanish ("y") where the bug was confirmed; other languages keep
their existing (tested) remainder behavior unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5887e111-030f-4e59-81c5-292877d37ed6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/duration-remainder-conjunctions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the fix label Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant