Skip to content

feat(claims): extract stated event intervals with each bound's own precision (#717, slice 4) - #926

Merged
github-actions[bot] merged 3 commits into
mainfrom
fix/717-claim-event-intervals
Nov 7, 2026
Merged

github-actions[bot] merged 3 commits into
mainfrom
fix/717-claim-event-intervals

Conversation

@cdeust

@cdeust cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Summary

Tranche 4 de #717 : stated_event_time lisait toute phrase contenant une formulation d'intervalle comme unknown. Elle lit désormais les intervalles bornés par des dates complètes, chaque borne gardant sa précision et son fuseau écrits :

  • from D1 to|until|till|through D2 et between D1 and D2 → intervalle fermé ;
  • since D → début connu, fin inconnue ; until|till D → fin connue, début inconnu.

Cause racine : la tranche 3 avait volontairement laissé _RANGE_RE court-circuiter toute la lecture (« stays unknown until intervals are extracted »), alors que EventTime (tranche 1) et le stockage (tranche 2) portent déjà kind="interval" avec bornes optionnelles.

Ce qui reste unknown, pour ne pas inventer de date : les intervalles abrégés (« from 10 to 12 March 2026 », « 10-12 March 2026 ») dont la première borne ne donne ni mois ni année ; une fin avant le début ; une paire où une seule borne indique un fuseau (refusé par EventTime) ; toute autre formulation.

Refs #717

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would change existing behavior)
  • Refactor (no functional change; rules/coding-standards.md compliance)
  • Documentation only
  • Audit-finding closure (cite the finding ID)

Test plan

  • pytest tests_py/core/test_claim_event_time.py : 75 passés. Quatre phrases qui étaient attendues unknown (« Since 2026-01… », « …until March 2026 », « From 2026-01 to 2026-03… », « Between March 2026 and 4 April 2026… ») sont maintenant des intervalles, comme voulu. Nouveaux cas négatifs : fin avant début, fuseau sur une seule borne, mauvais mot de liaison, trois dates, date impossible, date en tête de phrase.
  • Tests voisins (-k "claim or event_time or wiki_extract or mutation" sur tests_py/core et tests_py/handlers) : 140 passés, 1 ignoré.
  • Porte de mutation locale (scripts/mutation_check.sh sur claim_event_time.py) : 204 mutants, 203 tués, 1 survivant enregistré comme équivalent par construction (x__word_before__mutmut_8, valeur par défaut "" → "XXXX", aucune des deux n'est un mot de cadre).
  • ruff check / ruff format --check (0.17.3, version de uv.lock) sur les fichiers modifiés, porte craftsmanship OK.
  • Pas vérifié : la suite complète, pyright et les variantes PostgreSQL. torch ne se télécharge pas dans l'environnement de la routine. La CI fera foi.

Audit notes

  • Couches : changement limité à core (+ shared.wiki_ir déjà importé), pas de nouvel import.
  • Deferred : porter event_time dans la synthèse et la recherche (wiki_view ne filtre pas encore par event_time, et la sémantique de comparaison entre précisions et fuseaux reste à décider), plus les intervalles abrégés. Suivi dans feat: preserve event time separately from extraction time in ClaimEvent #717.

Coding-standards compliance

  • §2.2 Layer dependency direction preserved.
  • §3.2 No untyped dicts at boundaries.
  • §4.1 No file > 500 lines.
  • §4.2 No function > 50 lines.
  • §4.4 No function with > 4 parameters.
  • §7 Local reasoning preserved.
  • §8 Constants annotated with # source:.
  • §9 No dead code.

Breaking changes

Aucun pour le schéma : event_time accepte déjà interval depuis la tranche 1. Certaines claims qui sortaient unknown sortent maintenant interval.

Reviewer checklist

  • CHANGELOG.md updated under the appropriate section.
  • Documentation updated (README / SKILL.md / docs/). Module docstring mise à jour, pas d'autre doc concernée.
  • No secrets / credentials / PII in the diff.
  • CI passes on the latest commit.

Generated by Claude Code

…ecision (#717, slice 4)

stated_event_time left every sentence with interval wording unknown. It now
reads "from D1 to|until|till|through D2" and "between D1 and D2" as a closed
interval, "since D" as a start with an unknown end, and "until|till D" as an
end with an unknown start. Each bound keeps its written precision and zone.
Abbreviated ranges ("from 10 to 12 March 2026", "10-12 March 2026") stay
unknown: their first end names no month or year, and copying them from the
second end would invent them. An end before its start, or a pair where only
one end states a zone, is rejected by EventTime and stays unknown.

The empty-default mutant of _word_before is registered as an equivalent.

Refs #717

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYs2Nms1G85LP4zC4Lk
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T02:41:31.601737Z 7751462 New commits
🔒 Security Review ✅ Completed 2026-11-07T02:42:27.196930Z 7751462 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 2m 5s —— View job


PR #926 review (1 of 3)

I found no Blockers and posted three Notes. I couldn't run pytest or the craftsmanship script because Python needs approval in this sandbox, so CI will have to confirm them.

Verdict: approve

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8d1725205a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +168 to +169
if word in _OPEN_START_WORDS:
return EventTime(kind="interval", end=bound)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject abbreviated closed ranges before accepting an open bound

For We used Redis from 10 until 12 March 2026., only the second endpoint matches a full date, so this branch returns an interval with an unknown start and an end of March 12. The same happens with till. These are abbreviated closed ranges, which the documented contract explicitly leaves unknown, not genuinely open-start intervals. This silently drops the stated lower endpoint and persists a different temporal meaning. Before accepting a single-bound frame, check that it is not the surviving endpoint of an unsupported closed range, and add regression cases for both connectors.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmé et corrigé dans 830568c. Sur 8d17252, « We used Redis from 10 until 12 March 2026. » (et la même phrase avec till) donnait un intervalle à fin seule au 2026-03-12, ce qui perdait la borne de début écrite. Une borne seule n'est désormais ouverte que si son mot-cadre est la seule formulation d'intervalle de la phrase (_RANGE_RE y trouve une seule correspondance). Ces deux phrases, plus « Since 10 until 12 March 2026… », restent unknown. « We worked from home until March 2026. » reste une fin seule, car « from home » n'est pas une formulation d'intervalle. Les 79 tests du module passent. Porte de mutation locale : aucun survivant non enregistré.


Generated by Claude Code

@claude

claude Bot commented Nov 7, 2026

Copy link
Copy Markdown

Review 1 of 3 — PR #926 (#717, slice 4)

I found no Blockers. Five reviews ran (code quality, docs accuracy, performance, security, test coverage), all by reading the code:

  • Layering: the change stays inside core and imports only shared.wiki_ir.
  • Craftsmanship limits: the file is 196 lines and every function is under 40 lines. _CLOSED_ENDS has its # source: comment.
  • Rejections: when EventTime refuses an interval (end before start, or a zone on only one end), it raises a pydantic ValidationError, which is a ValueError. The try catches it and the result is unknown, as the docstring says.
  • Security: none of the regexes can backtrack badly, and no other exception gets out of stated_event_time.
  • Mutation note: x__word_before__mutmut_8 really is equivalent, and the test sentence it names exists.
  • Other tests: no other test expects unknown for interval wording.

I couldn't run pytest or the craftsmanship script here because Python needs approval in this sandbox, so CI will have to confirm them.

Notes, no action before merge

  • If the end bound is coarser than the start, wiki_ir.py:80 compares only the two values and rejects a valid interval. For example, "from 2026-03-12T10:00 to 2026-03-12" gives unknown; it fails safe but the docs don't mention it.
  • The slice-3 entry in CHANGELOG.md:62-63 still says "since 2026-01" stays unknown, which slice 4 changes.
  • No test covers from…till, or a lone through D (which sends the sentence to the interval path and then gives unknown).

View job run

Verdict: approve

… own precision (#717, slice 4)

Codex review on 8d17252 (PR #926): in "from 10 until 12 March 2026" only the second end is a full date, so the single-bound branch returned an end-only interval and dropped the stated start. A single bound is now open only when its frame is the sentence's only interval wording; the abbreviated closed range stays unknown, as the module contract states.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYs2Nms1G85LP4zC4Lk
@claude

claude Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 1m 47s —— View job


PR #926 review (2 of 3)

The fixup fixes the Codex finding: "from 10 until 12 March 2026" now gives unknown instead of an interval with only an end date. I found no Blockers and posted two Notes. Some starts the regex doesn't recognise, such as "from the 10th", still give an end-only interval. The CHANGELOG wording for "since/until" doesn't say those forms now need to be the sentence's only interval wording.

I couldn't run pytest because Python needs approval in this sandbox, so CI will have to confirm the tests.

Verdict: approve

… own precision (#717, slice 4)

Claude review 1 of 3 on PR #926: the slice-3 CHANGELOG entry still said "since 2026-01" stays unknown, which slice 4 changes; and no test covered from...till or a lone "through D" (interval wording with no open-bound frame, so unknown).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYs2Nms1G85LP4zC4Lk

cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

Suite à la revue 1 of 3 (Claude), dans 7751462 :

  • CHANGELOG : l'entrée de la tranche 3 disait encore que « since 2026-01 » reste unknown. Corrigée : elle renvoie à la tranche 4 pour les intervalles à dates complètes.
  • Tests : ajout de from…till (intervalle fermé) et d'un « through D » seul (unknown, car « through » n'ouvre aucune borne seule). 81 tests du module passent.
  • Laissé tel quel : une fin plus grossière que le début (« from 2026-03-12T10:00 to 2026-03-12 ») est refusée par EventTime (wiki_ir.py:80 compare les valeurs, pas les périodes) et sort unknown. Le résultat est sûr, puisqu'aucune date n'est inventée. Comparer des bornes de précisions différentes est justement la décision ouverte notée sur feat: preserve event time separately from extraction time in ClaimEvent #717 pour la recherche, donc je ne la tranche pas dans cette PR.

Generated by Claude Code

@claude

claude Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 1m 34s —— View job


PR #926 review (2 of 3)

I found no Blockers and posted three Notes:

  • "From mid-February until 12 March 2026" still gives an interval with only an end, because a start that isn't a digit or a month name isn't counted.
  • Unrelated range wording elsewhere in a sentence now makes a "since"/"until" sentence unknown. This fails safe.
  • The module docstring doesn't mention the new rule; only the inline comment does.

I couldn't run pytest or the mutation gate because Python needs approval in this sandbox, so CI will have to confirm them.

Verdict: approve

@claude

claude Bot commented Nov 7, 2026

Copy link
Copy Markdown

Review 2 of 3 — PR #926 (#717, slice 4)

Scope: only the commit pushed after 8d17252, which is 830568c (fixup). Review 1 found no Blockers, so there was nothing to re-check. The five reviews (code quality, docs accuracy, performance, security, test coverage) all ran by reading the code and tracing the regexes by hand. Python needs approval in this sandbox, so pytest was not run; CI will have to confirm the results.

The fix works for the Codex finding. For "from 10 until|till 12 March 2026", _RANGE_RE.findall returns two matches ("from 1" and "until 1"), so the new == 1 check fails and the sentence stays unknown (claim_event_time.py:165).

  • All three new negative tests kill a mutant that deletes the check or changes == 1 to >= 1.
  • The positive test "from home until March 2026" checks that the guard is not too strict.
  • The change adds no backtracking risk and no new exceptions, and the craftsmanship limits still hold: _interval is 21 lines and the file is 198 lines.

I found no Blockers.

Notes, no action before merge

  • Starts that _RANGE_RE does not recognise still give an end-only interval and drop the stated start: "from the 10th until 12 March 2026", "10 until 12 March 2026", "from Monday until…". The reverse also happens: "Since January 2026 to June" gives a start-only interval. These belong to the deferred abbreviated-interval work in feat: preserve event time separately from extraction time in ClaimEvent #717.
  • The slice-4 entry in CHANGELOG.md says "since D" / "until D" without conditions. Since this commit, those forms only work when they are the sentence's only interval wording, so "Since 2026-01, output rose from 3 to 5" now gives unknown.

View job run

Verdict: approve

cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

Revue 2 of 3 (Claude) : les deux notes sont prises en compte, sans nouveau push.

  • Débuts non reconnus (« from the 10th until 12 March 2026 », « 10 until 12 March 2026 », « from Monday until… ») : ils donnent encore une fin seule. Les distinguer de « from home until March 2026 », qui doit rester une fin seule, demande de reconnaître les débuts abrégés (ordinaux, jours de la semaine, nombres nus). Cela fait partie de la tranche « intervalles abrégés » listée sur feat: preserve event time separately from extraction time in ClaimEvent #717, je l'y reporte.
  • CHANGELOG : la condition « seule formulation d'intervalle de la phrase » sera précisée dans l'entrée de la tranche 4 au prochain push de code. Le cas cité (« Since 2026-01, output rose from 3 to 5 ») sort unknown, ce qui est sûr.

Generated by Claude Code

@claude

claude Bot commented Nov 7, 2026

Copy link
Copy Markdown

Review 2 of 3 — PR #926 (#717, slice 4)

There were no earlier Blockers to check. This review covers only the commits pushed after 8d17252 (830568c, 7751462). I traced the code and ran five reviews: code quality, docs accuracy, performance, security and test coverage.

Codex P2 is fixed. "We used Redis from 10 until 12 March 2026." now gives two _RANGE_RE matches ("from 10" and "until 12"), so the result is unknown. The till sentence and "Since 10 until 12 March 2026…" also give unknown. "We worked from home until March 2026." still gives an interval with only an end.

Other checks are clean:

  • Size and layers: claim_event_time.py is 199 lines, _interval is 21 lines, there are no new constants and no new imports.
  • Security and performance: the findall runs only when the sentence has one date and _RANGE_RE already matched. _RANGE_RE has no nested quantifiers. No new exception can escape the try.
  • Tests: they pin the rule in both directions (two interval wordings give unknown, one gives an open bound), with a test for each of until and till.

I could not run pytest or the mutation gate because Python needs approval in this sandbox, so the results above come from reading the code and CI will have to confirm them.

Notes, no action before merge

  • The undercount is still open when the start is not a digit or a month name. "From mid-February until 12 March 2026 we ran trials." gives one match, so it still becomes an interval with only an end and loses the stated start.
  • Unrelated range wording elsewhere in a sentence now blocks an open bound. "Since March 2026 we grew from 3 to 5 sites." gives unknown where 8d17252 gave a start-only interval. This fails safe.
  • The single-wording rule is only in the inline comment at claim_event_time.py:163, not in the module docstring at lines 28–35.

Verdict: approve

cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

Deuxième passage de la revue 2 of 3 (sur 7751462) : ses trois notes recoupent celles auxquelles j'ai déjà répondu.

  • Débuts non reconnus (« From mid-February until 12 March 2026… ») : je les reporte à la tranche « intervalles abrégés » de feat: preserve event time separately from extraction time in ClaimEvent #717, comme « from the 10th ».
  • Phrase avec une autre formulation d'intervalle (« Since March 2026 we grew from 3 to 5 sites. ») : elle sort unknown, ce qui est sûr et voulu.
  • Docstring : la règle « seule formulation d'intervalle » sera ajoutée à la docstring du module en même temps que la précision du CHANGELOG, au prochain push de code. Ce n'est pas bloquant, donc je ne pousse pas que pour ça.

Generated by Claude Code

@github-actions
github-actions Bot merged commit 16ab975 into main Nov 7, 2026
18 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.

2 participants