Repository navigation
feat(wiki): keep a claim's event time apart from its extraction time (#717, slice 1) - #875
Conversation
…717, slice 1) ClaimEvent carried only extracted_at, so a historical event extracted today had no structural place for when it happened. Add EventTime (unknown, point, interval) built from TimeBound (value + ISO 8601 precision; a naive value means the source named no zone, an aware one keeps the stated offset). A claim with no stated date stays "unknown": event_time is never derived from extracted_at. Validators reject components finer than the stated precision, bounds that contradict the kind, reversed intervals and intervals mixing zoned and unzoned bounds. Persistence, extraction, synthesis and retrieval are later slices. Refs #717 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_018kyZYtFuPz5BXnBBdsYsJn
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @cdeust's task in 1m 28s —— View job PR #875 review (1 of 3)
I found no Blockers. The review lists three Notes, none of which needs action before merge. The main one: when the two bounds have different precisions, I could not run pytest, ruff or the craftsmanship gate because this job's permissions did not allow it, so the review relies on CI for those. Verdict: approve |
|
Review 1 of 3 (ADR-1119), commit a039118 I found no Blockers. I ran five reviews: code quality, documentation accuracy, performance, security and test coverage. I traced the validators in Notes, no action before merge
Verdict: approve |
|
Les trois notes de la revue 1 restent hors de cette PR (ADR-1119 : on ne pousse que pour un Blocker).
Generated by Claude Code |
|
CI autopilot :
J'ai relancé une fois les jobs en échec ( Generated by Claude Code |
…slice 2) (#894) * feat(wiki): persist a claim's event time in wiki.claim_events (#717, slice 2) ClaimEvent.event_time (slice 1, #875) existed only in memory: the table had no column for it, so a stored claim kept extracted_at and lost the time of the event it describes. The column holds the JSON of EventTime (JSONB in PostgreSQL, JSON in SQLite) so a naive bound stays naive and an aware bound keeps its stated offset; a TIMESTAMPTZ pair would normalise both to UTC. Older stores migrate once, existing rows reading back unknown. Refs #717 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_018kyZYunvyM3xpNmz9DLUT7 * fixup! feat(wiki): persist a claim's event time in wiki.claim_events (#717, slice 2) x * fixup! feat(wiki): persist a claim's event time in wiki.claim_events (#717, slice 2) * fixup! feat(wiki): persist a claim's event time in wiki.claim_events (#717, slice 2) --------- Co-authored-by: Claude <[email protected]>
Summary
First slice of #717.
ClaimEventcarried onlyextracted_at, so a historical event extracted today had no structural place for when it happened. This addsEventTime(unknown/point/interval) built fromTimeBound(a value plus its ISO 8601 precision: year, month, day, hour, minute, second). A naive value means the source stated no zone; an aware value keeps the stated offset.ClaimEvent.event_timedefaults tounknownand is never derived fromextracted_at.Validators refuse anything that would invent information: components finer than the stated precision ("March 2026" must be
2026-03-01+month, never a known day), bounds that contradict the kind, reversed intervals, and intervals mixing zoned and unzoned bounds (not comparable).Refs #717 (not
Closes: the issue spans extraction, persistence, synthesis and retrieval).Root cause addressed in this slice: the contract itself,
mcp_server/shared/wiki_ir.py, had no field to hold an occurrence time. The new models live in that file (already baselined for its pydantic import) so the craftsmanship gate stays at its baseline; the file is now 299 lines.Type of change
Test plan
tests_py/shared/test_wiki_ir_event_time.py: 18 passed. Covers the acceptance items within this slice: a 1969 event extracted in 2026 keeps both times through a JSON round-trip; a claim with no stated date isunknown, not its extraction time; unknown / point (month, minute with +02:00 offset) / closed and open intervals round-trip with precision and offset; invented precision and contradictory bounds are rejected.pytest tests_py/shared/ tests_py/handlers/test_wiki_pipeline_sqlite.py tests_py/handlers/test_wiki_pointer_loop.py tests_py/handlers/test_wiki_draft_tools.py tests_py/handlers/test_wiki_extract_superseded.py tests_py/handlers/test_wiki_refine_confidence.py: 825 passed, 9 skipped (PostgreSQL not reachable here).ruff check/ruff format --checkon the changed files: clean.python scripts/check_craftsmanship.py: OK.download-r2.pytorch.org); dependencies were installed fromuv.lockwithout it. CI is the receipt for those.Audit notes
handlers/wiki_extract._claim_to_dictmaps fields explicitly, so the new field is not written towiki.claim_eventsyet and no schema changes in this slice.event_timeinwiki.claim_eventson PostgreSQL and SQLite with a one-shot migration; (3) extract stated dates incore/claim_extractorviashared/temporal_normalize, with precision, without defaulting toextracted_at; (4) carry it through synthesis and retrieval, with corrections and contradictory dates preserving provenance.Coding-standards compliance
shared/wiki_ir.pykeeps its baselined pydantic import).anyin production code.wiki_ir.pyis 299).# source:(ISO 8601-1:2019 §3.2; feat: preserve event time separately from extraction time in ClaimEvent #717).Breaking changes
None.
event_timeis optional with anunknowndefault; existingClaimEventconstruction is unchanged.Reviewer checklist
Generated by Claude Code