Skip to content

An end moved to the end of its period says so on the row - #1295

Open
Maya-Kid wants to merge 3 commits into
deeplethe:devfrom
Maya-Kid:fix/end-names-its-period
Open

Maya-Kid wants to merge 3 commits into
deeplethe:devfrom
Maya-Kid:fix/end-names-its-period

Conversation

@Maya-Kid

@Maya-Kid Maya-Kid commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

First of four PRs for #994 cut 1 (plan: my 2026-10-15 comment there; the split and four differences: my 2026-10-17 comment). This one stores the mark and keeps it through every writer; the backfill (0115, per review) and two printing PRs follow.

Problem

Since #975, "left in 2024" closing a row from 2024-03-01 stores 2025-01-01 at year precision, right on the world axis. "Until 2025" stores the same, so nothing on the row says which period the text named; every reader prints 2025.

Change

  • The mark. facts.end_after_period (migration 0114), with a CHECK keeping it on a dated end the timeline did not draw, on a row with a start.
  • One rule. graph::period_mark_fits (a state property, a start, a dated, undrawn end) is the CHECK's Rust side. Both write entries, rewrite_end_tx, mark_end_after_period and the route's 422 and keep rule call it, so cut 2 drops the start clause there and in the CHECK.
  • Setters. Where A binding to a state property says what a single date marks, and a state row whose ends are equal is never written #975 moves an end: insert_fact_on's end-only closing path (including a drawn end there) and refine_target. "Until 2025" and "left in 2024" mark an open row in either order; until first, a locked, merging temporal::mark_end_after_period marks it, so a person's row stays theirs. Corrected ends and other precisions are left alone.
  • Carriers. rewrite_end_tx writes it in Use chapter attestation to order unique state timelines #1054's insert, never for drawn, unknown or start-less ends. rehome_tx, errata revisions and the same-start branch carry it; both write entries drop it where a row cannot carry it. Review, conflict and violation closes write none; their end-before-start bug is A row closed in Review at a date before its start holds at no moment #1294.
  • Correction route. PATCH …/facts/{id} takes an optional end_after_period, the one field whose absence means keep: an unchanged end keeps the mark while a start remains; clearing the start drops it, keeping the instant. An explicit true needs a state property, a start and a dated end, else 422 bad_end_after_period. A changed mark is a changed end. "Unchanged" and interval_inverted compare truncated values (raw values let an 08:30 hour end pass an 08:10 minute start). Entity detail returns the mark.
  • Records. 0053's revision, 0031, time.md, ledger.md.

Size: 761 added lines outside docs, 299 of code and 462 of tests; docs add 128. Still one PR: the mark holds only if every write path keeps it, an unmerge, an errata revision and today's dialog included.

Verification

On dev 86bd5da plus 0114's DDL, each test fails on one assertion listing every case:

  • a_coarse_end_closes_a_row_that_starts_inside_its_period: [[false], [false]], closing path and refinement;
  • one_end_named_two_ways_is_marked, a_drawn_end_the_text_names_as_a_period_is_marked, a_marked_end_rides_through_a_rehome_and_a_revision: unmarked;
  • a_correction_keeps_the_mark_unless_the_request_changes_it: no mark in entity detail, a start-only edit unmarked, mark-only edits ignored, explicit true and the hour inversion accepted.

Linux x86_64, Rust 1.98.1, PostgreSQL 16.15, pgvector 0.8.6, Poppler 25.03, UTOPIA_TEST_REQUIRE_DB=1, commit 3211225, fresh database: cargo test --locked --workspace 1,596 passed, 0 failed, 6 ignored (server 670, store 441); fmt and clippy clean on 1.98.1 and 1.99.1.

Limits

  • Nothing prints the mark yet: An end that names a period prints as the period after it #994's symptom stays until the printing PRs.
  • Rows written before 0114 stay unmarked until the backfill PR.
  • Today's dialog keeps the mark on a start-only save, drops it on a cleared start or edited end.
  • With the until first, History shows a same-date corrected change.
  • On write, an until and a "left in" that both arrive before the start leave the row unmarked (the start-less row in between cannot carry it).

@WaylandYang WaylandYang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you, this is careful work. Both statement orders, the refinement path, the correction route's keep rule and every insert that copies an end hold or drop the mark exactly as the 0053 revision says, and comparing truncated ends in interval_inverted is a good catch.

One structural request: please move the backfill into its own PR (0115, as you offered). This one is about twice our 500-line guideline, and the backfill's single-date guard, which copies materialize's binding match twice to survive a flipped binding, is the SQL that most deserves review on its own. Nothing prints the mark until part B, so the backfill can land in between with no gap anyone would see.

Two smaller things:

  • The rule "a state property, a start, a dated, undrawn end" now appears in the CHECK, drop_period_mark_unless, the guard in rewrite_end_tx, mark_end_after_period and the route. A single helper on the Rust side would make cut 2's relaxation one edit instead of four.
  • In the 0053 revision, the two open questions copied from #994 can stay on the issue; the record should hold what was decided.

And a nit: these commits are signed as "dada-yan", while your earlier ones use "Maya Kid" with the same email. Please keep one name, per the DCO section.

@Maya-Kid
Maya-Kid force-pushed the fix/end-names-its-period branch from d9724ec to 3211225 Compare October 18, 2026 05:00
@Maya-Kid

Copy link
Copy Markdown
Contributor Author

Thank you. Done in 3211225:

  • Backfill. 0114 now holds only the column and the CHECK. The UPDATE, unchanged, and its test follow as their own PR with 0115 once this one merges.
  • One rule. graph::period_mark_fits is the Rust side of the CHECK. Both write entries, rewrite_end_tx, mark_end_after_period and the route's 422 and keep rule call it, so cut 2 relaxes the start clause there and in the CHECK.
  • 0053 keeps only what was decided; the two open questions stay on An end that names a period prints as the period after it #994.
  • Sign-off. All three commits are now Maya Kid <[email protected]>, rewritten and force-pushed, and I'll keep that name.

Re-run on Linux: the five remaining tests fail on dev plus 0114's DDL, the workspace passes (1,596 passed, 0 failed), and fmt and clippy are clean on 1.98.1 and 1.99.1.

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