What happens
fact_conflicts.resolution is declared as plain TEXT with a comment listing the values:
-- closed | kept_both | rejected_new
resolution TEXT,
There is no CHECK. The code writes a fourth value, stale, from the lazy cleanup in temporal::list_conflicts, so the documented set and the real set have already diverged.
Compare axiom_violations, which constrains the same kind of column:
resolution TEXT CHECK (resolution IN ('fact_retracted', 'axiom_relaxed', 'accepted'))
Why it matters
stale is not the same kind of thing as the other three. closed, kept_both and rejected_new are decisions a person made; stale means the conflict evaporated because one side was invalidated. A reader that treats the column as "how was this adjudicated" gets a wrong answer for stale rows, and there is nothing in the schema to warn them.
It also matters for #564: if the RDF export echoes this column, an internal cleanup artefact becomes part of a public contract, and the column has no constraint to stop the set from growing again.
Direction
Add the CHECK with the real set, and decide whether stale belongs in it or should be its own status:
- if a conflict that evaporated is not "resolved", it wants
status = 'withdrawn' rather than a fourth resolution;
- if it stays a resolution, the comment and the constraint should both say so.
Either way the constraint should exist, so the next value cannot arrive without a migration. Related: the timestamp question in the companion issue.
What happens
fact_conflicts.resolutionis declared as plainTEXTwith a comment listing the values:There is no
CHECK. The code writes a fourth value,stale, from the lazy cleanup intemporal::list_conflicts, so the documented set and the real set have already diverged.Compare
axiom_violations, which constrains the same kind of column:Why it matters
staleis not the same kind of thing as the other three.closed,kept_bothandrejected_neware decisions a person made;stalemeans the conflict evaporated because one side was invalidated. A reader that treats the column as "how was this adjudicated" gets a wrong answer for stale rows, and there is nothing in the schema to warn them.It also matters for #564: if the RDF export echoes this column, an internal cleanup artefact becomes part of a public contract, and the column has no constraint to stop the set from growing again.
Direction
Add the
CHECKwith the real set, and decide whetherstalebelongs in it or should be its own status:status = 'withdrawn'rather than a fourth resolution;Either way the constraint should exist, so the next value cannot arrive without a migration. Related: the timestamp question in the companion issue.