Preferences — a rule kind that Scribe keeps up to date (#3849 steps 1–3) #150

Merged
bvandeusen merged 5 commits from dev into main 2026-09-10 23:34:16 -04:00
Showing only changes of commit 4aae4973f7 - Show all commits
+26 -2
View File
@@ -388,7 +388,7 @@ def test_rule_rows_carry_the_verification_fields():
row = SimpleNamespace( row = SimpleNamespace(
id=1, topic_id=2, project_id=None, title="t", statement="s", id=1, topic_id=2, project_id=None, title="t", statement="s",
why="w", how_to_apply="h", order_index=0, why="w", how_to_apply="h", order_index=0,
when_to_apply="when", tier="conditional", when_to_apply="when", tier="conditional", kind="rule",
verify_with="cat some/file", expires_when="the file grows a shell", verify_with="cat some/file", expires_when="the file grows a shell",
verified_at=checked, arose_from_id=99, verified_at=checked, arose_from_id=99,
created_at=checked, updated_at=checked, created_at=checked, updated_at=checked,
@@ -415,7 +415,7 @@ def test_rule_rows_keep_an_unverified_rule_unverified():
row = SimpleNamespace( row = SimpleNamespace(
id=1, topic_id=2, project_id=None, title="t", statement="s", id=1, topic_id=2, project_id=None, title="t", statement="s",
why=None, how_to_apply=None, order_index=0, why=None, how_to_apply=None, order_index=0,
when_to_apply=None, tier="always_on", when_to_apply=None, tier="always_on", kind="rule",
verify_with=None, expires_when=None, verified_at=None, verify_with=None, expires_when=None, verified_at=None,
arose_from_id=None, arose_from_id=None,
created_at=datetime(2026, 8, 27, tzinfo=timezone.utc), created_at=datetime(2026, 8, 27, tzinfo=timezone.utc),
@@ -426,3 +426,27 @@ def test_rule_rows_keep_an_unverified_rule_unverified():
assert backup._dt_or_none("2026-08-27T12:00:00+00:00") == datetime( assert backup._dt_or_none("2026-08-27T12:00:00+00:00") == datetime(
2026, 8, 27, 12, 0, tzinfo=timezone.utc 2026, 8, 27, 12, 0, tzinfo=timezone.utc
) )
def test_rule_rows_carry_the_kind_so_a_preference_does_not_restore_as_a_rule():
"""FORCE has to survive a backup, and the failure would be silent.
A preference that comes back as a rule is not a missing field anyone would
notice — the rule reads fine, it simply binds when it was only ever meant
to be how the operator prefers things done. Nothing in the restored
rulebook says it used to be softer.
Asserted with `preference` rather than `rule` on purpose: a fixture
carrying the DEFAULT would pass just as happily against a `_rule_rows`
that dropped the field entirely and let the importer's `or "rule"` fill
the hole back in, which is precisely the bug this guards.
"""
stamp = datetime(2026, 9, 10, tzinfo=timezone.utc)
row = SimpleNamespace(
id=1, topic_id=2, project_id=None, title="t", statement="s",
why=None, how_to_apply=None, order_index=0,
when_to_apply="when", tier="conditional", kind="preference",
verify_with=None, expires_when=None, verified_at=None,
arose_from_id=None, created_at=stamp, updated_at=stamp,
)
assert backup._rule_rows([row])[0]["kind"] == "preference"