Skip to content

The importer reads utopia:temporal on a property - #1291

Merged
WaylandYang merged 3 commits into
deeplethe:devfrom
gedaiu:feat/import-reads-temporal
Oct 18, 2026
Merged

WaylandYang merged 3 commits into
deeplethe:devfrom
gedaiu:feat/import-reads-temporal

Conversation

@gedaiu

@gedaiu gedaiu commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1292. Related: #1242 (the rule this lets apply to imported ontologies).

The export has written utopia:temporal on every property that is not a state since 0031, and the importer never read it back. An ontology that said a relation is an event came in as a state, and the rule of #1242, which binds a pushed phrase by the declaration only when the relation is not a state, could never apply to an imported vocabulary.

The turtle projection now reads urn:utopia:ns:temporal with one of state, event or eternal. Any other value is reported under the preview's unprojected predicates and the property stays unset. A new relation is created with the value, a re-import updates an existing relation's temporal to what the file says, and a file that says nothing leaves the column alone, so a value a person set on the page survives an unannotated re-import. Attributes are still created as state.

Tests: the projection keeps event and eternal, leaves an unannotated and a misspelled property at none and reports the latter; a full import through the HTTP route creates attended at event, a re-import moves worksAt from state to eternal, and a third unannotated import leaves it there. 0031 gains a status line and the ontology design doc a sentence.

Since the review, the export also writes utopia:temporal "state", so every exported property now carries the annotation and existing exports change by one triple per state relation. That is what makes re-importing an export exact.

The export has written utopia:temporal on every property that is not a
state since 0031, and the importer never read it back: an ontology that said
a relation is an event came in as a state, and the rule of deeplethe#1242, which binds
a pushed phrase by the declaration only when the relation is not a state,
could never apply to an imported vocabulary.

The turtle projection reads urn:utopia:ns:temporal with one of state, event
or eternal; any other value is reported under the preview's unprojected
predicates and the property stays unset. A new relation is created with the
value, a re-import updates an existing relation's temporal to what the file
says, and a file that says nothing leaves it alone, so a value a person set
on the page survives an unannotated re-import. Attributes stay state.

Signed-off-by: Bogdan Szabo <[email protected]>
gedaiu added a commit to gedaiu/utopia that referenced this pull request Oct 16, 2026
gedaiu added a commit to re-cinq/lore that referenced this pull request Oct 16, 2026
The mirror spec gains the Commits section and ADR-052 the amendment that
records the name shapes, the by-name merge that makes CI ordering
irrelevant, the cursor, and the correction: Utopia's importer gave every
imported relation temporal=state, so the rule of #1242 bound no Lore phrase
until deeplethe/utopia#1291 reads the annotation. The history read moves to
platform-github-history.ts, the docs classifier to ingested-docs.ts (breaking
the backfill/commits cycle), the three Utopia routes to utopia-routes.ts; the
OpenAPI document and the web-ui types carry the new route.
gedaiu added a commit to re-cinq/lore that referenced this pull request Oct 16, 2026
Every default-branch commit lands in the repo's Utopia knowledge base as one commit:<sha> item: its paths, parents, pull request, issues and Lore task. lore-api walks the branch above a cursor; the weekly backfill and every push run the walk. Ontology v4 marks each relation event or eternal, which Utopia binds by the declaration once its importer reads the annotation (deeplethe/utopia#1291, re.8).
gedaiu added a commit to re-cinq/lore that referenced this pull request Oct 16, 2026
re.8 = re.7 + deeplethe/utopia#1291: the ontology importer reads utopia:temporal, so Lore's relations can be events or eternal and Utopia binds their pushed phrases by the declaration. No new migration. Apply with terraform -target='kubernetes_deployment_v1.utopia[0]'.

@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. Reading back what the export writes is clearly right, and moving the check into validate_temporal is a nice cleanup. Three things before merging:

  1. Please key the invalid-value report by the predicate IRI (urn:utopia:ns:temporal), not an English sentence. The preview runs every key through shortIri, which keeps what follows the last /, so today the row reads "eternal ×1", which looks as if eternal was the rejected value; the sentence also bypasses i18n. Using the IRI fixes both, and the public constant can go.
  2. The round trip still can't return a relation to state. The export writes utopia:temporal only when the value isn't state (rdf.rs), and the import reads "no annotation" as "leave it alone", so a relation changed from event back to state in one base stays an event when that export is imported again elsewhere. I'd have the export write state too: one line, and re-importing an export becomes exact. If you'd rather not, please say in 0031 that an import can move a relation off state but never back.
  3. A temporal changed by import should count as a change, the way it does on the page. update_relation_type treats temporal as a criterion: it sets updated_at, which 0053's phrase-binding basis reads, and reconciles violations. update_relation_from_import does neither. State versus non-state decides how phrases bind (WAITING_PHRASE, and the #1242 rule), so decisions made under the old value would never be revisited. Please bump updated_at when the value actually changes, with an assertion in the route test. Import never reconciles violations, even for domain/range changes; that's older than this PR and can be its own issue.

Also, the 0031 note went under "Status history", which only keeps the old status lines. Please make it one dated line in the body, next to the 2026-09-27 one.

…ites state too, and an import that changes temporal moves updated_at

Signed-off-by: Bogdan Szabo <[email protected]>
@gedaiu

gedaiu commented Oct 18, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, all three are in 7e5b556.

  1. Report key: an invalid value now falls through to the ordinary unprojected path and is counted under urn:utopia:ns:temporal, so the preview shows the predicate and translates it like any other. UNPROJECTED_TEMPORAL is gone.
  2. Round trip: the export writes utopia:temporal on every property, state included, so re-importing an export is exact. a_state_relation_exports_its_temporal covers the export, and the route test now ends by importing utopia:temporal "state" and checking the relation is back at state.
  3. Change counts: update_relation_from_import bumps updated_at only when the file declares a value that differs from the stored one. The route test checks that it moves on state → eternal, stays put on an unannotated re-import, and moves again on eternal → state. The violations gap is An ontology import does not reconcile violations after it changes a relation #1297.

The 0031 note is now one dated line in decision 1, next to the 2026-09-27 one, and is out of the status history.

Each new assertion fails with its fix reverted. fmt, clippy (-D warnings) and cargo test --workspace are clean locally.

@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 addresses everything from the last review. A value other than state/event/eternal is now counted under urn:utopia:ns:temporal, so the preview reads "temporal ×1"; the export writes state too, and the route test takes a relation back to state with a re-import; and update_relation_from_import moves updated_at only when temporal actually changes, with the test checking both that a change moves it and that an unannotated import leaves it alone, which is what phrase_bindings needs to revisit an old decision. The 0031 note is now one dated line in the body. On my earlier remark (see #1297): import does reconcile violations at the route level in apply_import, so please ignore it. Merging.

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