Skip to content

A statement is attested by the date its own section speaks from, and one with no time holds at every moment (0064 cut 3) - #995

Merged
WaylandYang merged 2 commits into
devfrom
feat/as-of-from-context
Sep 28, 2026
Merged

WaylandYang merged 2 commits into
devfrom
feat/as-of-from-context

Conversation

@WaylandYang

Copy link
Copy Markdown
Contributor

ADR 0064 cut 3. Supersedes #988. Refs #987.

The defect. An open statement was written with attested_from = COALESCE(document date, now()). Extraction runs before any date is read, so every statement was attested at the moment its document was processed, and reads take the lower bound of a row with no start from that column. A report from 2020 uploaded today had its facts read as known since today; on the panel every relation said "undated".

What changes

  • No fallback to now() for statements written by extraction. A statement a person nodded through is still attested at the nod.
  • Attestation comes from the section. After extraction each statement is attested by the now entry in force at the position of its quote, the same rule cut 2 uses for relative expressions, and attested_by keeps that entry's words ("提报日期 2026年9月4日"). Minutes are attested by the meeting's date, not the date they were sent. It is an as-of, not a start: valid_from is untouched.
  • Typed rows follow their sources: the earliest attestation among the statements a row was materialised from, kept in step at the end of materialisation.
  • A row with no time at all holds at every moment. An event with no date still holds at none (0022). Reasoning reads an unattested premise as open below.
  • Migration 0100 (constant 91): attested_from nullable, attested_by; existing open statements move to their earliest dated evidence or to NULL; typed rows follow.
  • Panel: "as of 2026-09-04 · 提报日期 2026年9月4日" for a fact with no interval of its own; "undated" only when there is nothing.

As built, against the record. Decision 3 had the model name the entry per statement. Here the entry is chosen by structure; the other named dates of a section (a data cut-off, an effective date) stay in the context and attest nothing yet. Choosing between them is a judgement about the statement and would cost a slot in every extraction reply. The record says so.

Time bench (three runs each): as-of right 0 of 10 before, 9–10 of 10 after, on gemini-3.5-flash and again on claude-haiku-4-5; no sentence without time words was given a start.

Tests: store (a_statement_is_attested_by_what_its_document_says: unattested holds at every moment, attested from its date, only earlier, typed follows its source, undated event holds at none), server (last_week_is_counted_from_the_date_of_its_own_section now also checks each statement's attestation and its name), the existing anchor test for an ending without a date. Store, server and CLI suites and workspace clippy pass.

🤖 Generated with Claude Code

WaylandYang and others added 2 commits September 28, 2026 16:41
…one with no time holds at every moment

ADR 0064 cut 3. Supersedes #988.

An open statement was written with `attested_from = COALESCE(document
date, now())`, and extraction runs before any date is read, so every
statement was attested at the moment its document was processed. Reads
take the lower bound of a row with no start from that column: a report
from 2020 uploaded today had its facts read as known since today, and
the panel could only say "undated" (#987).

- The insert no longer falls back to now(). A statement written by
  extraction has no attestation unless a source system dated the
  document. A statement a person nodded through is still attested at the
  nod: the person is the evidence.
- After extraction, each statement of the document is attested by the
  `now` entry in force at the position of its quote (the rule cut 2 uses
  for relative expressions), with that entry's words: `attested_by` is
  "提报日期 2026年9月4日". Minutes are attested by the meeting's date,
  not the date they were sent. Only earlier, as `attest_earlier`.
- Typed rows have no evidence of their own: their attestation is the
  earliest of the statements they were materialised from, kept in step
  at the end of materialisation and after attesting.
- A row with neither a valid time nor an attestation holds at every
  moment. An event with no date still holds at none (0022); the guard is
  null-safe, a statement has no predicate and its temporal kind is NULL.
  Reasoning reads an unattested premise as open below.
- An ending said without a date needs an anchor by CHECK; with no
  attestation it takes the moment the ledger recorded it.
- Migration 0100: `attested_from` nullable, `attested_by`; open
  statements move to their earliest dated evidence or to NULL, typed rows
  follow their sources.
- The panel says "as of 2026-09-04 · 提报日期 2026年9月4日" for a fact
  with no interval of its own, and "undated" only when there is nothing.

Time bench, three runs: as-of right 0 of 10 before, 9–10 of 10 after; no
sentence without time words was given a start.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Wayland Yang <wayland0916@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Wayland Yang <wayland0916@gmail.com>
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.

1 participant