Skip to content

test(claims): corrections and contradictory dates keep each claim's own event time (#717, slice 5) - #927

Merged
github-actions[bot] merged 1 commit into
mainfrom
fix/717-claim-event-time-supersession
Nov 7, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
fix/717-claim-event-time-supersession

Conversation

@cdeust

@cdeust cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Summary

Tranche 5 de #717, critère d'acceptation 3 (« Corrections and contradictory dates preserve provenance and uncertainty; do not invent a date »). Aucun test ne le prouvait de bout en bout. Le nouveau test tests_py/handlers/test_claim_event_time_supersession.py passe par le vrai pipeline (wiki_extract puis wiki_resolve, composition root des handlers, backend SQLite par défaut) sur quatre mémoires liées à la même entité : une décision datée au jour, la même décision avec une date contradictoire au mois, une correction datée qui la remplace (switched to … replaces), et une décision sans date.

Après résolution :

  • chaque event_time vaut exactement ce que sa phrase énonce (la résolution écrit supersedes et des memos, jamais event_time) ;
  • la claim remplacée garde sa date plus ancienne à côté du pointeur supersedes et du memo supersedes de la correction ;
  • les deux dates contradictoires survivent avec leur précision, sous un memo conflict_candidate qui nomme la paire ;
  • la claim sans date reste unknown : aucune date reprise des voisines ni d'extracted_at.

Cause racine de la tranche : pas de bug de code trouvé, le comportement était correct mais non prouvé. Aucun changement de code de production.

Refs #717

Type of change

  • New feature (non-breaking change which adds functionality) — tests seulement

Test plan

  • pytest tests_py/handlers/test_claim_event_time_supersession.py : 5 passed.
  • Tests voisins (test_wiki_pipeline_sqlite, test_claim_event_time_persistence, test_claim_event_time, test_wiki_ir_event_time, test_wiki_extract_superseded) : 172 passed, 4 skipped (PostgreSQL absent).
  • Mutation : faire réinitialiser event_time par update_claim_supersedes fait échouer 2 des 5 tests.
  • ruff check, ruff format --check, scripts/check_craftsmanship.py : OK.

Note de conception : chaque extraction est horodatée à sa propre minute (UPDATE … extracted_at), car le résolveur ne remplace qu'une claim extraite strictement plus tôt et datetime('now') de SQLite a une résolution d'une seconde. Les dates d'événement ne sont jamais lues depuis ce champ.

Pas vérifié : la suite complète, pyright et les variantes PostgreSQL (torch ne se télécharge pas dans cet environnement ; le test est SQLite uniquement). La CI fera foi.

Audit notes

  • Observation hors périmètre : le résolveur ordonne la supersession par extracted_at, pas par event_time. Une correction extraite avant le claim qu'elle corrige ne le remplacerait pas. Non modifié ici.

Reviewer checklist

  • CHANGELOG.md updated under the appropriate section.
  • No secrets / credentials / PII in the diff.

Tranches restantes de #717 : recherche (wiki_view sur event_time, décision de comparaison entre précisions), synthèse (_claims_for_memory, wiki_frontmatter), intervalles abrégés si décidé.


Generated by Claude Code

…wn event time (#717, slice 5)

Acceptance criterion 3 of #717 had no end-to-end proof. The new handler
test runs wiki_extract then wiki_resolve on the default SQLite backend over
four memories about one entity: a dated decision, the same decision with a
contradictory month-precision date, a dated correction that replaces it, and
an undated decision. After resolution every event_time equals what its own
sentence states: the superseded claim keeps its older date next to the
correction's supersedes pointer and memo, both contradictory dates survive
under a conflict_candidate memo, and the undated claim stays unknown.

Each extraction is stamped with its own minute because the resolver only
supersedes a prior extracted strictly earlier and SQLite's datetime('now')
has one-second resolution; event times are never read from that stamp.

Mutation check: making update_claim_supersedes also reset event_time fails
2 of the 5 tests.

Refs #717

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYupbw3xqXghCeXjBKy
@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-07T03:29:15.114194Z b308854 PR opened
🔒 Security Review ✅ Completed 2026-11-07T03:30:17.309808Z b308854 PR opened
ℹ️ 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 29s —— View job


Review 1 of 3: PR #927

None of the five reviews found a Blocker. The comment also has three optional notes. I could not run pytest here because the command needed approval, so CI will show whether the tests pass.

Verdict: approve

@claude

claude Bot commented Nov 7, 2026

Copy link
Copy Markdown

Review 1 of 3: PR #927

Five reviews ran on the diff: code quality, test coverage, documentation accuracy, security and performance. None found a Blocker.

Each check below was done by reading the code:

  • The fixture's environment variables are the real CORTEX_MEMORY_* fields (memory_config.py:51-53,172). With STORE_BACKEND=sqlite, every store is built at tmp_path, and DATABASE_URL is not consulted.
  • %s and wiki. are rewritten for SQLite by sqlite_sql_translate.py. event_time and inputs are JSON columns that are decoded when read, so comparing them as dicts is valid.
  • The scenario's assertions all hold:
    • The resolver only supersedes a claim extracted strictly earlier and takes the latest such claim (claim_resolver.py:149,157), so the correction supersedes CONTRADICTION and not FIRST.
    • The FIRST/CONTRADICTION conflict_candidate memo can only come from resolving CONTRADICTION, so the pair check tests something real.
    • wiki_resolve never writes event_time.
  • Craftsmanship limits are met, and the noqa: DTZ001 is needed.

I could not run pytest in this environment because the command needed approval. CI is the source of truth for that.

Notes, no action before merge

  • tests_py/handlers/test_claim_event_time_supersession.py:109-112: the extracted_at UPDATE is never committed by the test itself. It only takes effect because wiki_resolve commits on the same connection (wiki_resolve.py:217). An explicit store._conn.commit() would match test_wiki_pipeline_sqlite.py:134.
  • tests_py/handlers/test_claim_event_time_supersession.py:161-165: the undated claim never enters a supersedes chain, so "takes no date from its neighbours" is only lightly tested. An undated correction ("We switched to SQLite, which replaces PostgreSQL.") that stays unknown would be the stronger case.
  • tests_py/handlers/test_claim_event_time_supersession.py:111: f"10:0{minute}:00" breaks after 10 texts. {minute:02d} costs nothing.

Verdict: approve

@github-actions
github-actions Bot merged commit 0799b17 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