Repository navigation
Resolve pushed structured dates and timestamps without a chat model - #1090
Conversation
A pushed statement (0054) carries its when/ended as caller-supplied words, and a complete date or zoned timestamp in that payload is already structured: resolve_time reads it in code at the precision it writes, keeps the literal as the mention, and never asks the model about it. Bare years, year-months and words code cannot read still go to the model, or wait at grade C when no chat model is configured, and the job completes either way instead of failing for a missing chat configuration. The distinction is source identity, not string shape: documents keep the model path even when their text happens to look like a timestamp. Signed-off-by: Anson <310461893+ansonnmm@users.noreply.github.com>
WaylandYang
left a comment
There was a problem hiding this comment.
This is the cut agreed on #1089, and nothing more: a complete date or a zoned timestamp from a pushed statement is read in code and graded A, everything else still goes to the model, and resolve_time no longer fails for a statements source when no chat model is configured.
I ran both builds as a real server with no chat model and pushed the same three statements through POST /sources/{id}/statements:
when / ended |
dev | this PR |
|---|---|---|
2026-09-23T08:14:03+08:00 |
no interval, job retries with "Chat model not configured" | 2026-09-23 00:14:03Z, second precision, grade A |
2024-03-01 / 2025-02-28 |
no interval | 2024-03-01 to 2025-02-28, day precision, grade A |
last Tuesday |
no interval | no interval, grade C |
All three resolve_time jobs finish on the first attempt with the PR; on dev they stay queued and retry.
One thing to know, not a blocker: parse_time reads a clock without a zone (2026-09-23T08:14:03) as the date at day precision, so such a value lands on the day, not the second. That is the reader's existing behaviour and the right side to err on. If you push sensor timestamps, send the offset.
Merging. Thanks for the careful tests and for writing the decision into 0045 and 0054.
Refs #1089
Why
A pushed statement already carries
when/endedas caller-supplied words (ADR 0054). When those words are a complete date or a zoned timestamp, the payload is already structured — yet today every time mention goes through the chat model, so on an installation without a chat model a push leaves aresolve_timejob that fails retries even though the value is deterministically readable.What changes
Inside
resolve_document, for documents whose source kind isstatementsonly:parse_time. A complete date or zoned timestamp (YYYY-MM-DD,YYYY-MM-DDTHH[:MM[:SS]]withZor an offset) becomes a syntheticpoint/absoluteinterpretation at the precision the value writes, and is never included in the model request list — so a rerun asks the same nothing and a model reply cannot overwrite it.resolve_interpretations/combine/set_open_validitymachinery, so it can also anchor model-answered mentions.The distinction is source identity, not string shape: a document whose text happens to contain
2026-09-23T08:14:03Zkeeps the existing model path, and non-pushed documents still fail fast without a chat model.What does not change
statementscontract:when/endedstay polymorphic words; no new slot, no new shape for a bare instant.parse_timeitself, the store/schema,marksbinding semantics, materialization, equal-end invariants, and job retry machinery.Time semantics
A caller-stated complete date/timestamp is grade A at exactly the precision written; a
whendate under a state binding still resolves to whatevermarksdecides;when+endedis an interval; equal-end rows stay forbidden.#994 relationship
A timestamp-valued
endedis read at its stated precision by this change. Period-word ends ("ended last quarter" style) remain words on the model path — this PR does not implement #994's period-end semantics and does not invent a sentinel.Validation
time_resolution::pushed_tests(real Postgres + scripted model endpoint): no-model date/timestamp grade A resolution, precision matrix day/hour/minute/second,+08:00offset folded into the UTC value,when+endedinterval, unreadable mentions at C with the job succeeding, mixed pushes, document-path unchanged, code-resolved mention never asked and stable across reruns (also serving as an anchor for a model-answered relative mention).cargo test -p utopia-servergreen (596 tests incl. all existingtime_resolution/statements/extractiontests),cargo test --workspacegreen,cargo clippyclean,cargo fmtclean.